Compare commits

...

34 Commits

Author SHA1 Message Date
max
e4d44155dc feat: 更改类名 ,处理代码区分 2024-09-12 19:20:13 +08:00
max
06c974a6ed feat: 图片资源 格式转换 2024-09-12 19:03:23 +08:00
max
4bfbd19b53 fix: 修复bug, 调整升级弹窗不再弹出, 兼容旧版本连击横幅,礼物动画加快, 2024-09-12 18:55:55 +08:00
max
61a26f0c4f fix: 调整ui, 修复bug 2024-09-12 10:15:17 +08:00
max
e8cfc8a13b fix:异常注释 2024-09-11 16:23:24 +08:00
max
295de38074 feat: 幸运礼物 弹窗跟飘屏 , 替换 金币图标 2024-09-11 16:21:58 +08:00
max
e3c5f10d02 feat: 联机送礼功能 2024-09-09 18:39:22 +08:00
max
d949cfa7ff temp save 2024-09-05 19:24:44 +08:00
max
e30f4fd15f feat: 更正 tabbar size 2024-08-30 20:57:09 +08:00
max
90ece5366b feat: 更新数据明文处理 2024-08-30 20:54:13 +08:00
max
555b81589c feat: 修正 en 语言的部分 UI 2024-08-30 16:15:31 +08:00
max
e4cdc39ad8 feat: 修正反饋問題 2024-08-30 15:54:20 +08:00
max
09411df1ff feat:UI 調整 2024-08-29 19:21:07 +08:00
max
9cbc6cf39f fix: 修正 VIP 購買選項 model 2024-08-29 18:19:44 +08:00
max
444d043aa8 feat: 修改聯繫人列表 UI 2024-08-29 17:06:40 +08:00
max
f99d193598 feat: 修改信息列表 UI 2024-08-29 16:42:24 +08:00
max
4a57bd50c5 feat:UI 調整 2024-08-29 12:00:28 +08:00
eggmanQQQ
8a59f8a769 feat: 调整 RTL 布局 UI 2024-08-29 11:59:28 +08:00
max
2c1ecbb263 feat:UI 調整 2024-08-28 21:41:19 +08:00
max
aa2987cb0d feat:修正問題 2024-08-28 21:40:15 +08:00
eggmanQQQ
5e6864d87f feat: 更新 UI 2024-08-28 21:39:59 +08:00
eggmanQQQ
6aabeb3eb3 feat: 更新 UI 2024-08-28 17:36:16 +08:00
eggmanQQQ
9ff48bc500 feat: 移除资源,补充多语言 2024-08-28 13:55:59 +08:00
max
e9ba0b1929 feat:調整 VIP 顯示邏輯,移除公聊廳 2024-08-28 13:55:12 +08:00
max
adf2adc173 feat:調整 VIP 顯示邏輯,移除公聊廳 2024-08-27 16:51:46 +08:00
max
74b2d71821 調試 UI 2024-08-27 16:51:46 +08:00
eggmanQQQ
81a5c6ba65 feat: 補充卡片背景,補充 VIP 資源播放 MP4 的功能 2024-08-27 16:31:44 +08:00
eggmanQQQ
5f8a8113c6 feat:个人资料卡支持 MP4 资源 2024-08-27 11:53:49 +08:00
eggmanQQQ
b0bf9ce98d feat: 调整文案 2024-08-27 11:24:32 +08:00
eggmanQQQ
c3fcbc3942 feat: 更新资源,调整布局 2024-08-27 10:33:34 +08:00
max
6e08f397ee fix:Vip 頁面支持 MP4 播放,修正佈局問題 2024-08-26 16:58:19 +08:00
eggmanQQQ
3d29568b3c feat: 更新 VIP 页面 UI & 功能 2024-08-26 09:13:28 +08:00
eggmanQQQ
cb4dac8e81 feat: 更新 VIP 页面 UI & 功能 2024-08-23 19:29:38 +08:00
eggmanQQQ
f58701a2d6 version update 2024-08-20 10:53:52 +08:00
247 changed files with 4476 additions and 2318 deletions

View File

@@ -205,6 +205,7 @@ dependencies {
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2'
api 'androidx.multidex:multidex:2.0.1'
implementation 'androidx.gridlayout:gridlayout:1.0.0'
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.9.1'
@@ -270,6 +271,8 @@ dependencies {
//wheelView
implementation 'com.contrarywind:wheelview:4.1.0'
// 轮播组件
implementation 'io.github.youth5201314:banner:2.2.3'
implementation project(':modules:module_base')
if (!isolationMode && file("../modules/module_google/build.gradle").exists()) {

View File

@@ -733,8 +733,8 @@
android:name=".ui.setting.PermissionGuideActivity"
android:screenOrientation="portrait" />
<activity
android:name=".vip.VipMainActivity"
android:screenOrientation="portrait" /> <!-- 隐私设置 -->
android:name=".vip.VipCenterActivity"
android:screenOrientation="portrait" />
<activity
android:name=".vip.VipSettingActivity"
android:screenOrientation="portrait" /> <!-- 通知提醒设置 -->

Binary file not shown.

View File

@@ -97,7 +97,7 @@ public class GlobalHandleManager {
Activity activity = getActivity();
if (activity == null) return;
if (AvRoomDataManager.get().isSelfGamePlaying()) return;
LevelUpDialog.start(activity, event.getLevelName(), true);
// LevelUpDialog.start(activity, event.getLevelName(), true);
}
@Subscribe(threadMode = ThreadMode.MAIN)
@@ -105,7 +105,7 @@ public class GlobalHandleManager {
Activity activity = getActivity();
if (activity == null) return;
if (AvRoomDataManager.get().isSelfGamePlaying()) return;
LevelUpDialog.start(activity, event.getLevelName(), false);
// LevelUpDialog.start(activity, event.getLevelName(), false);
}
private static final class Helper {

View File

@@ -0,0 +1,126 @@
package com.chwl.app.avroom.dialog
import android.content.Context
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.Window
import android.view.WindowManager
import androidx.annotation.StyleRes
import androidx.viewbinding.ViewBinding
import com.chwl.app.R
import com.chwl.app.avroom.widget.VDHLayout
import com.chwl.app.ui.widget.dialog.BaseDialog
abstract class BaseRoomNotifyeBaseDialog<VB : ViewBinding>(context: Context, theme: Int = 0) : BaseDialog(context, theme) {
protected val handle = Handler(Looper.getMainLooper())
protected lateinit var mBinding: VB
abstract fun createBinding(inflater: LayoutInflater): VB
abstract fun init()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mBinding = createBinding(LayoutInflater.from(context))
setContentView(mBinding.root)
setCancelable(true)
setCanceledOnTouchOutside(false)
window?.let {
initWindow(it)
}
init()
handle.postDelayed({
dismissDialog()
}, (getStaySecond()*1000).toLong())
}
override fun onDetachedFromWindow() {
handle.removeCallbacksAndMessages(null)
super.onDetachedFromWindow()
}
protected open fun initWindow(window: Window) {
window.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
val windowParams = window.attributes
windowParams.width = WindowManager.LayoutParams.MATCH_PARENT
windowParams.height = WindowManager.LayoutParams.WRAP_CONTENT
windowParams.dimAmount = 0.0f
windowParams.gravity = Gravity.TOP
windowParams.x = 0
windowParams.y = getTopOffset()
window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
window.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL)
window.attributes = windowParams
window.setWindowAnimations(getAnimations())
}
protected open fun getStaySecond():Float{
return 5f
}
protected open fun getTopOffset():Int{
return 0
}
@StyleRes
protected open fun getAnimations():Int{
return R.style.anim_left
}
override fun setContentView(view: View) {
if (useSlipSlip()) {
val vdhLayout = VDHLayout(context, null)
vdhLayout.addView(view)
vdhLayout.setListener { dismissDialog() }
super.setContentView(vdhLayout)
return
}
super.setContentView(view)
}
override fun setContentView(layoutResID: Int) {
if (useSlipSlip()) {
val vdhLayout = VDHLayout(context, null)
LayoutInflater.from(context).inflate(layoutResID, vdhLayout)
vdhLayout.setListener { dismissDialog() }
super.setContentView(vdhLayout)
return
}
super.setContentView(layoutResID)
}
override fun setContentView(view: View, params: ViewGroup.LayoutParams?) {
if (useSlipSlip()) {
val vdhLayout = VDHLayout(context, null)
vdhLayout.addView(view)
vdhLayout.setListener { dismissDialog() }
super.setContentView(vdhLayout, params)
return
}
super.setContentView(view, params)
}
open fun dismissDialog(){
try {
dismiss()
} catch (e: Exception) {
}
}
/**
* 是否启动侧滑,左滑:删除,右滑:回到原位置
*/
protected open fun useSlipSlip(): Boolean {
return true
}
}

View File

@@ -0,0 +1,75 @@
package com.chwl.app.avroom.dialog
import android.content.Context
import android.view.LayoutInflater
import com.chwl.app.R
import com.chwl.app.avroom.activity.AVRoomActivity
import com.chwl.app.common.widget.dialog.DialogManager
import com.chwl.app.common.widget.dialog.DialogManager.OkCancelDialogListener
import com.chwl.app.databinding.RoomNotifyLuckGiftDlgBinding
import com.chwl.app.ui.utils.ImageLoadUtils
import com.chwl.app.utils.NumberUtils
import com.chwl.core.gift.bean.LuckyGiftMsgAllBean
import com.chwl.core.manager.AvRoomDataManager
import com.chwl.library.utils.ResUtil
import com.example.lib_utils.UiUtils
/**
* @Author Vance
* 幸运礼物的飘屏,全服但是展示的时候限制只有房间才展示
*/
class BaseRoomNotifyeLuckGiftDialog(private val context: Context) : BaseRoomNotifyeBaseDialog<RoomNotifyLuckGiftDlgBinding>(context) {
override fun createBinding(inflater: LayoutInflater): RoomNotifyLuckGiftDlgBinding {
return RoomNotifyLuckGiftDlgBinding.inflate(inflater)
}
private var mDialogManager: DialogManager? = null
var luckyGiftMsgBean: LuckyGiftMsgAllBean ? = null
override fun init() {
if (UiUtils.isRtl(context)) {
mBinding.bg.scaleX = -1f
}
ImageLoadUtils.loadImage(mBinding.avatar,luckyGiftMsgBean?.sender?.avatar?:"")
mBinding.giftName.text = luckyGiftMsgBean?.giftNameMap?.getFirstText()
mBinding.winNum.text = luckyGiftMsgBean?.times.toString()
val coinNum = NumberUtils.format(luckyGiftMsgBean?.coins?:0)
mBinding.coinNum.text = coinNum
mBinding.clickArea.setOnClickListener {
mDialogManager = DialogManager(context)
mDialogManager?.showOkCancelDialog(ResUtil.getString(R.string.changeRoomTips), true, object : OkCancelDialogListener {
override fun onCancel() {
mDialogManager?.dismissDialog()
}
override fun onOk() {
mDialogManager?.dismissDialog()
luckyGiftMsgBean?.roomUid?.let {
if (AvRoomDataManager.get().roomUid != it) {
AVRoomActivity.start(context, it)
}
}
}
})
}
}
var mCallBack : CallBack? = null
interface CallBack{
fun onHide();
}
override fun dismissDialog() {
super.dismissDialog()
mCallBack?.onHide()
}
}

View File

@@ -77,6 +77,14 @@ public class RoomOperationDialog extends BottomSheetDialog {
private Context context;
private OptAdapter optAdapter;
private OnActionListener onActionListener;
private CallBack callBack;
public void setCallBack(CallBack callBack) {
this.callBack = callBack;
}
public interface CallBack{
void onCLick(int Type);
}
public RoomOperationDialog(@NonNull Context context) {
super(context, R.style.ErbanBottomSheetDialogDimFalse);
@@ -133,6 +141,7 @@ public class RoomOperationDialog extends BottomSheetDialog {
addSuperAdminAction(optAdapter);
addShieldReportAction(optAdapter);
addRoomTypeSwitchAction(optAdapter);
//todo-- add pk btn
rvOPtList.setAdapter(optAdapter);
}

View File

@@ -22,9 +22,7 @@ import android.widget.RelativeLayout
import android.widget.TextView
import androidx.annotation.CallSuper
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LiveData
import androidx.lifecycle.lifecycleScope
@@ -48,7 +46,6 @@ import com.chwl.app.avroom.dialog.RoomGameListDialog
import com.chwl.app.avroom.dialog.RoomGameplayDialog
import com.chwl.app.avroom.dialog.RoomOperationDialog
import com.chwl.app.avroom.presenter.BaseRoomPresenter
import com.chwl.app.avroom.public_chat.PublicChatRoomMessageWidget
import com.chwl.app.avroom.room_album.RoomAlbumModel
import com.chwl.app.avroom.view.IBaseRoomView
import com.chwl.app.avroom.widget.BottomView
@@ -60,9 +57,7 @@ import com.chwl.app.event.OpenRoomIntroEvent
import com.chwl.app.friend.view.SelectFriendActivity
import com.chwl.app.home.adapter.RoomActAdapter
import com.chwl.app.music.widget.MusicPlayerView
import com.chwl.app.public_chat.ui.message.HeadlineViewModel
import com.chwl.app.room_chat.activity.RoomMsgActivity
import com.chwl.app.ui.pay.ChargeActivity
import com.chwl.app.ui.webview.CommonWebViewActivity
import com.chwl.app.ui.webview.DialogWebViewActivity
import com.chwl.app.ui.widget.ButtonItem
@@ -70,7 +65,6 @@ import com.chwl.app.ui.widget.GiftDialog
import com.chwl.app.ui.widget.GiftDialog.OnGiftDialogBtnClickListener
import com.chwl.app.ui.widget.GiftDialog.SenGiftCallback
import com.chwl.app.ui.widget.UserInfoDialog
import com.chwl.app.ui.widget.dialog.CommonTipDialog
import com.chwl.app.ui.widget.dynamicface.DynamicFaceDialog
import com.chwl.app.ui.widget.magicindicator.MagicIndicator
import com.chwl.app.ui.widget.magicindicator.buildins.UIUtil
@@ -79,13 +73,13 @@ import com.chwl.app.ui.widget.rollviewpager.RollPagerView
import com.chwl.app.ui.widget.rollviewpager.Util
import com.chwl.app.ui.widget.rollviewpager.hintview.ColorPointHintView
import com.chwl.app.utils.KeyBoardUtils
import com.chwl.app.vip.dialog.SelectPayTypeDialog
import com.chwl.core.Constants
import com.chwl.core.UriProvider
import com.chwl.core.auth.AuthModel
import com.chwl.core.bean.RoomMicInfo
import com.chwl.core.gift.GiftModel
import com.chwl.core.gift.bean.GiftInfo
import com.chwl.core.gift.event.GiftComboEvent
import com.chwl.core.gift.event.RoomFreeGiftEvent
import com.chwl.core.helper.AtProxy
import com.chwl.core.home.bean.BannerInfo
@@ -119,12 +113,15 @@ import com.chwl.core.support.room.RoomWidget
import com.chwl.core.user.UserModel
import com.chwl.core.user.bean.BaseInfo
import com.chwl.core.user.bean.UserInfo
import com.chwl.core.utils.net.BalanceNotEnoughExeption
import com.chwl.core.utils.net.VipLevelNotEnoughException
import com.chwl.library.common.util.LimitClickUtils
import com.chwl.library.net.rxnet.utils.RxNetWorkUtils
import com.chwl.library.rxbus.RxBus
import com.chwl.library.utils.*
import com.chwl.library.utils.JavaUtil
import com.chwl.library.utils.ListUtils
import com.chwl.library.utils.ResUtil
import com.chwl.library.utils.SingleToastUtil
import com.chwl.library.utils.UIUtils
import com.google.gson.Gson
import com.netease.nim.uikit.common.antispam.AntiSpamEvent
import com.netease.nimlib.sdk.StatusCode
@@ -136,7 +133,6 @@ import com.tbruyelle.rxpermissions2.RxPermissions
import com.trello.rxlifecycle3.android.FragmentEvent
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
@@ -157,12 +153,10 @@ open class BaseRoomFragment<V : IBaseRoomView?, P1 : BaseRoomPresenter<V>?> :
private var myUid: Long = 0
protected lateinit var messagePager: ViewPager2
protected lateinit var messageView: MessageView
protected var publicChatMessageWidget: PublicChatRoomMessageWidget? = null
protected lateinit var bottomView: BottomView
protected lateinit var inputLayout: RelativeLayout
protected lateinit var inputEdit: EditText
protected lateinit var inputSend: ImageView
protected lateinit var inputHeadlineSend: ImageView
protected lateinit var microView: MicroView
private var musicPlayerView: MusicPlayerView? = null
private var mVsMusicPlayer: ViewStub? = null
@@ -204,8 +198,6 @@ open class BaseRoomFragment<V : IBaseRoomView?, P1 : BaseRoomPresenter<V>?> :
// 房间小组件
private var widgets: HashMap<String, RoomWidget> = HashMap()
private val headlineViewModel by activityViewModels<HeadlineViewModel>()
@CallSuper
override fun onFindViews() {
initMessageView()
@@ -221,7 +213,6 @@ open class BaseRoomFragment<V : IBaseRoomView?, P1 : BaseRoomPresenter<V>?> :
false
}
inputSend = mView.findViewById(R.id.input_send)
inputHeadlineSend = mView.findViewById(R.id.input_headline_send)
microView = mView.findViewById(R.id.micro_view)
mVsMusicPlayer = mView.findViewById(R.id.vs_music_player)
messageView.setClickConsumer {
@@ -244,10 +235,9 @@ open class BaseRoomFragment<V : IBaseRoomView?, P1 : BaseRoomPresenter<V>?> :
protected open fun initMessageView() {
messagePager = mView.findViewById<ViewPager2>(R.id.message_pager)
messageView = MessageView(context)
publicChatMessageWidget = PublicChatRoomMessageWidget(requireContext())
val tabList: MutableList<String> = java.util.ArrayList(2)
tabList.add(getString(R.string.room))
tabList.add(getString(R.string.public_chat))
// tabList.add(getString(R.string.public_chat))
val messageIndicator = mView.findViewById<MagicIndicator>(R.id.message_indicator)
messagePager.offscreenPageLimit = tabList.size
messagePager.adapter = object : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
@@ -255,12 +245,8 @@ open class BaseRoomFragment<V : IBaseRoomView?, P1 : BaseRoomPresenter<V>?> :
parent: ViewGroup,
viewType: Int
): RecyclerView.ViewHolder {
val view = if (viewType == 0) {
messageView
} else {
publicChatMessageWidget
}
view?.layoutParams = ViewGroup.LayoutParams(
val view = messageView
view.layoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
)
@@ -314,7 +300,6 @@ open class BaseRoomFragment<V : IBaseRoomView?, P1 : BaseRoomPresenter<V>?> :
override fun onSetListener() {
bottomView.setMagicBtnEnable(true)
inputSend.setOnClickListener(this)
inputHeadlineSend.setOnClickListener(this)
inputLayout.setOnTouchListener { _: View?, _: MotionEvent? ->
inputEdit.clearFocus()
inputLayout.visibility = View.GONE
@@ -322,7 +307,6 @@ open class BaseRoomFragment<V : IBaseRoomView?, P1 : BaseRoomPresenter<V>?> :
false
}
messageView.setOnLongClickListener { _, account, name ->
showInputLayout()
if (atProxy == null) atProxy = AtProxy(inputEdit)
@@ -378,44 +362,6 @@ open class BaseRoomFragment<V : IBaseRoomView?, P1 : BaseRoomPresenter<V>?> :
//获取免费礼物详情
mvpPresenter?.queryFreeFlower()
initRoomAlbum()
initHeadline()
}
private fun initHeadline() {
headlineViewModel.loadingLiveData.observe(this) {
if (it) dialogManager?.showProgressDialog(context)
else dialogManager?.dismissDialog()
}
lifecycleScope.launch(Dispatchers.Main) {
headlineViewModel.sendHeadlineFlow.collect {
if (it.isSuccess) {
SingleToastUtil.showToast(R.string.sent_success)
inputEdit.setText("")
KeyBoardUtils.hideKeyBoard(activity, inputEdit)
} else {
if (it.code == BalanceNotEnoughExeption.code) {
showBalanceNotEnoughDialog()
} else {
SingleToastUtil.showToast(it.message)
}
}
}
}
headlineViewModel.getHeadlinePayMoneyIsNull()
}
private fun showBalanceNotEnoughDialog() {
val tipDialog = CommonTipDialog(context)
tipDialog.setTipMsg(ResUtil.getString(R.string.insufficient_balance_recharge_tips))
tipDialog.setOkText(getString(R.string.charge))
tipDialog.setOnActionListener(
object : CommonTipDialog.OnActionListener {
override fun onOk() {
ChargeActivity.start(context)
}
}
)
tipDialog.show()
}
@SuppressLint("CheckResult")
@@ -819,9 +765,6 @@ open class BaseRoomFragment<V : IBaseRoomView?, P1 : BaseRoomPresenter<V>?> :
R.id.input_send -> {
sendMsg()
}
R.id.input_headline_send -> {
sendHeadline()
}
R.id.layout_room_rank -> {
DialogWebViewActivity.start(mContext, UriProvider.getRoomRanking())
}
@@ -869,41 +812,6 @@ open class BaseRoomFragment<V : IBaseRoomView?, P1 : BaseRoomPresenter<V>?> :
}
}
private fun sendHeadline() {
val message = inputEdit.text.toString().trim()
if (TextUtils.isEmpty(message)) {
SingleToastUtil.showToast(ResUtil.getString(R.string.avroom_fragment_baseroomfragment_08))
return
}
if (message.length > 100) {
toast(R.string.headline_input_length_limit_tips)
return
}
val money = headlineViewModel.headlinePayMoneyLiveData.value
if (money != null) {
showHeadlinePayDialog(money, message)
} else {
SingleToastUtil.showToast(R.string.ui_setting_modifypwdactivity_01)
headlineViewModel.getHeadlinePayMoney()
}
}
private fun showHeadlinePayDialog(money: Long, message: String) {
KeyBoardUtils.hideKeyBoard(activity, inputEdit)
SelectPayTypeDialog.newInstance(
money.toString(),
money,
false
).apply {
setOnDiamondChargeClick {
headlineViewModel.sendHeadline(message)
}
setOnChargeClick {
ChargeActivity.start(context)
}
}.show(context)
}
@SuppressLint("CheckResult")
fun sendMsg(msg: String) {
if (!AuthModel.get().isImLogin) {
@@ -934,7 +842,6 @@ open class BaseRoomFragment<V : IBaseRoomView?, P1 : BaseRoomPresenter<V>?> :
return
}
mvpPresenter?.sendPublicChatTextMessage(message)
publicChatMessageWidget?.getMessageView()?.setNeedAutoScroll(true) // 發送後自動滾動公屏列表
inputEdit.setText("")
}
@@ -960,6 +867,9 @@ open class BaseRoomFragment<V : IBaseRoomView?, P1 : BaseRoomPresenter<V>?> :
for (i in micMemberInfos.indices) {
targetUids.add(micMemberInfos[i].account.toLong())
}
EventBus.getDefault().post(GiftComboEvent(GiftComboEvent.Action.ACT_GIFT_BEGIN))
GiftModel.get()
.sendRoomGift(
giftInfo.giftId,
@@ -981,11 +891,16 @@ open class BaseRoomFragment<V : IBaseRoomView?, P1 : BaseRoomPresenter<V>?> :
dialogManager.showOkDialog(message)
}
}
.subscribe { _, throwable ->
.subscribe { gift, throwable ->
if (throwable != null) {
toast(throwable.message)
callback.onFail()
EventBus.getDefault().post(GiftComboEvent(GiftComboEvent.Action.ACT_GIFT_CANCEL))
} else {
giftDialog?.hide()
val giftComboEvent = GiftComboEvent(GiftComboEvent.Action.ACT_GIFT_END)
giftComboEvent.giftNumber = gift.data.giftNum
EventBus.getDefault().post(giftComboEvent)
callback.onSuccess()
}
}
@@ -1250,7 +1165,6 @@ open class BaseRoomFragment<V : IBaseRoomView?, P1 : BaseRoomPresenter<V>?> :
}
override fun onSendPublicChatMsgSuccess(msg: ChatRoomMessage) {
publicChatMessageWidget?.getMessageView()?.addMessages(msg)
inputEdit.setText("")
KeyBoardUtils.hideKeyBoard(activity, inputEdit)
}
@@ -1371,6 +1285,7 @@ open class BaseRoomFragment<V : IBaseRoomView?, P1 : BaseRoomPresenter<V>?> :
giftDialog?.setOnDismissListener { giftDialog = null }
}
if (giftDialog?.isShowing != true && !requireActivity().isFinishing) {
EventBus.getDefault().post(GiftComboEvent(GiftComboEvent.Action.ACT_GIFT_POINT))
giftDialog?.show()
}
}
@@ -1542,9 +1457,6 @@ open class BaseRoomFragment<V : IBaseRoomView?, P1 : BaseRoomPresenter<V>?> :
}
open fun initWidget() {
publicChatMessageWidget?.let {
registerWidget(PublicChatRoomMessageWidget::class.java.simpleName, it)
}
}
@Subscribe(threadMode = ThreadMode.MAIN)
@@ -1562,7 +1474,6 @@ open class BaseRoomFragment<V : IBaseRoomView?, P1 : BaseRoomPresenter<V>?> :
* 打开公屏输入
*/
fun openMessageInput(text: String?) {
inputHeadlineSend.isVisible = isPublicMessageTab()
inputLayout.visibility = View.VISIBLE
if (text != null) {
inputEdit.setText(text)
@@ -1578,6 +1489,26 @@ open class BaseRoomFragment<V : IBaseRoomView?, P1 : BaseRoomPresenter<V>?> :
}
protected open fun onInitMusicPlayerView(view: MusicPlayerView) {
//todo-- 音乐按钮
}
@Subscribe(threadMode = ThreadMode.MAIN)
fun onGiftComboEvent(event: GiftComboEvent) {
when (event.action) {
GiftComboEvent.Action.ACT_GIFT_START-> {
giftDialog?.sendGift()
}
GiftComboEvent.Action.ACT_GIFT_SHOW-> {
giftDialog?.show()
}
else -> {}
}
}
}

View File

@@ -100,9 +100,6 @@ class GameRoomFragment : BaseRoomFragment<IGameRoomView?, GameRoomPresenter?>(),
messageView.messageListView?.let {
setMessagePagerAutoHeight(it)
}
publicChatMessageWidget?.getMessageView()?.messageListView?.let {
setMessagePagerAutoHeight(it)
}
}
override fun onClick(v: View) {

View File

@@ -6,7 +6,10 @@ import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewStub;
@@ -19,9 +22,23 @@ import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.Fragment;
import com.chwl.app.avroom.activity.RoomTitleEditActivity;
import com.chwl.app.avroom.dialog.BaseRoomNotifyeLuckGiftDialog;
import com.chwl.app.databinding.LayoutRoomNotifyLuckyGiftTipBinding;
import com.chwl.app.utils.GiftAnimUtil;
import com.chwl.app.utils.NumberUtils;
import com.chwl.app.utils.WeakPool;
import com.chwl.core.auth.AuthModel;
import com.chwl.core.gift.bean.LuckyGiftMsgAllBean;
import com.chwl.core.gift.bean.LuckyGiftMsgSelfBean;
import com.chwl.core.gift.bean.MsgSuperLuckyGift;
import com.chwl.core.utils.ComboUtil;
import com.chwl.app.ui.utils.ImageLoadUtilsV2;
import com.chwl.app.ui.widget.BonsellaJoinAttackButtonView;
import com.chwl.app.ui.widget.GiftDialog;
import com.chwl.app.ui.widget.UserInfoDialog;
import com.chwl.core.gift.event.GiftComboEvent;
import com.chwl.core.gift.toolbox.GiftToolbox;
import com.chwl.core.utils.LogUtils;
import com.chwl.library.utils.JavaUtil;
import com.example.lib_utils.UiUtils;
import com.netease.nim.uikit.common.util.string.StringUtil;
@@ -66,6 +83,7 @@ import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import java.lang.reflect.Field;
import java.util.ArrayList;
import io.reactivex.SingleObserver;
import io.reactivex.disposables.Disposable;
@@ -101,6 +119,9 @@ public class HomePartyFragment extends BaseFragment implements View.OnClickListe
//收藏房间
private String FOLLOW_ROOM_TYPE = "";
//幸运礼物 飘屏队列
private ArrayList<LuckyGiftMsgAllBean> mLuckyGiftList = new ArrayList<>();
public static HomePartyFragment newInstance() {
HomePartyFragment homePartyFragment = new HomePartyFragment();
Bundle bundle = new Bundle();
@@ -243,7 +264,7 @@ public class HomePartyFragment extends BaseFragment implements View.OnClickListe
case RoomEvent.ROOM_INFO_UPDATE:
updateView(AvRoomDataManager.get().mCurrentRoomInfo);
break;
case RoomEvent.RECEIVE_NORMALE_GIFT:
case RoomEvent.RECEIVE_NORMALE_GIFT://普通
onReceiveGiftMsg(roomEvent.getGiftReceiveInfo());
break;
case RoomEvent.RECEIVE_MUTLT_NORMALEI_GIFT://普通多人
@@ -267,12 +288,17 @@ public class HomePartyFragment extends BaseFragment implements View.OnClickListe
case RoomEvent.FANS_TEAM_JOIN:
onReceiveFansTeamJoinMsg(roomEvent.getChatRoomMessage());
break;
case RoomEvent.MSG_SUPER_LUCKY_GIFT:
onLuckyGiftMsg(roomEvent);
break;
default:
break;
}
});
}
/**
* 获取礼物飘屏是否展示
*
@@ -491,10 +517,16 @@ public class HomePartyFragment extends BaseFragment implements View.OnClickListe
@Override
public void onDestroy() {
luckyGiftTipPool.clear();
handler.removeCallbacksAndMessages(null);
mLuckyGiftList.clear();
if (giftView != null) {
giftView.release();
}
EventBus.getDefault().unregister(this);
gameMainBinding.giftComboBtn.cancel();
super.onDestroy();
}
@@ -508,10 +540,10 @@ public class HomePartyFragment extends BaseFragment implements View.OnClickListe
updateOnlineNumberView(onlineNumber);
}
/**
* 普通多人
*
* @param giftMultiReceiverInfo
*/
private void onReceiveMultiGiftMsg(GiftMultiReceiverInfo giftMultiReceiverInfo) {
if (giftMultiReceiverInfo == null || !isResumed()) return;
@@ -519,12 +551,12 @@ public class HomePartyFragment extends BaseFragment implements View.OnClickListe
giftView = (GiftV2View) mVsGift2View.inflate();
}
giftView.onReceiveGiftToMultiMsg(giftMultiReceiverInfo);
giftMultiReceiverInfo.isMulti = true;
gameMainBinding.giftComboLayout.onRoomCustomMsg(giftMultiReceiverInfo);
}
/**
* 普通全麦
*
* @param multiGiftReceiveInfo
*/
private void onReceiveAllMicGiftMsg(MultiGiftReceiveInfo multiGiftReceiveInfo) {
if (multiGiftReceiveInfo == null || !isResumed()) return;
@@ -532,14 +564,20 @@ public class HomePartyFragment extends BaseFragment implements View.OnClickListe
giftView = (GiftV2View) mVsGift2View.inflate();
}
giftView.onReceiveMultiGiftMsg(multiGiftReceiveInfo);
gameMainBinding.giftComboLayout.onRoomCustomMsg(GiftToolbox.transformToGiftMultiReceiverInfo(multiGiftReceiveInfo));
}
/**
* 普通
*/
private void onReceiveGiftMsg(GiftReceiveInfo giftReceiveInfo) {
if (giftReceiveInfo == null || !isResumed()) return;
if (giftView == null) {
giftView = (GiftV2View) mVsGift2View.inflate();
}
giftView.onReceiveGiftMsg(giftReceiveInfo);
gameMainBinding.giftComboLayout.onRoomCustomMsg(GiftToolbox.transformToGiftMultiReceiverInfo(giftReceiveInfo));
}
private void onReceiveMagicMsg(MagicReceivedInfo magicReceivedInfo) {
@@ -611,4 +649,149 @@ public class HomePartyFragment extends BaseFragment implements View.OnClickListe
dialogFragment.show(requireActivity().getSupportFragmentManager(), "roomTitle");
}
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onGiftComboEvent(GiftComboEvent event) {
if (event.getAction() == GiftComboEvent.Action.ACT_GIFT_BEGIN) {
if (gameMainBinding.giftComboBtn.isInCombo()){
gameMainBinding.giftComboBtn.waitStart();
}
} else if (event.getAction() == GiftComboEvent.Action.ACT_GIFT_END) {
showComboBtn(event.getGiftNumber());
}else if (event.getAction() == GiftComboEvent.Action.ACT_GIFT_CANCEL) {
if (gameMainBinding.giftComboBtn.isInCombo()) {
gameMainBinding.giftComboBtn.cancel();
}
}else if (event.getAction() == GiftComboEvent.Action.ACT_GIFT_POINT) {
ComboUtil.INSTANCE.setPoint(gameMainBinding.giftComboBtn);
}
}
private void showComboBtn(int number) {
if (gameMainBinding.giftComboBtn.getOnGiftComboEndListener() == null) {
gameMainBinding.giftComboBtn.setOnClickListener(v -> {
ComboUtil.INSTANCE.setPoint(gameMainBinding.giftComboBtn);
EventBus.getDefault().post(new GiftComboEvent(GiftComboEvent.Action.ACT_GIFT_START));
gameMainBinding.giftComboBtn.onBtnDown();
});
gameMainBinding.giftComboBtn.setOnGiftComboEndListener(new BonsellaJoinAttackButtonView.OnGiftComboEndListener() {
@Override
public void onGiftComboEnd() {
gameMainBinding.giftComboBtn.showView(false);
EventBus.getDefault().post(new GiftComboEvent(GiftComboEvent.Action.ACT_GIFT_SHOW));
}
});
}
gameMainBinding.giftComboBtn.showView(true);
gameMainBinding.giftComboBtn.start();
gameMainBinding.giftComboBtn.updateNumber(number);
}
private void onLuckyGiftMsg(RoomEvent roomEvent) {
MsgSuperLuckyGift msgSuperLuckyGift = roomEvent.getMsgSuperLuckyGift();
if (msgSuperLuckyGift != null) {
if (msgSuperLuckyGift.luckyGiftMsgAllBean != null) {
showLuckyGiftDlg(msgSuperLuckyGift.luckyGiftMsgAllBean);
}
if (msgSuperLuckyGift.luckyGiftMsgSelfBean != null) {
showLuckyGiftDlgNotify(msgSuperLuckyGift.luckyGiftMsgSelfBean);
}
}
}
private Handler handler = new Handler(Looper.getMainLooper());
private WeakPool<View> luckyGiftTipPool = new WeakPool<>(3);
private void showLuckyGiftDlgNotify(LuckyGiftMsgSelfBean luckyGiftMsgBean) {
if (luckyGiftMsgBean == null) return;
if (luckyGiftMsgBean.getUid() != AuthModel.get().getCurrentUid()) return;
if (luckyGiftMsgBean.getRoomId() != AvRoomDataManager.get().getRoomId()) return;
if (luckyGiftMsgBean.getRoomUid() != AvRoomDataManager.get().getRoomUid()) return;
LogUtils.i(" showLuckyGiftDlgNotify = start");
View root = luckyGiftTipPool.acquire(() -> {
return LayoutInflater.from(gameMainBinding.flLuckyGiftNotifyLayout.getContext()).inflate(R.layout.layout_room_notify_lucky_gift_tip, gameMainBinding.flLuckyGiftNotifyLayout, false);
});
LayoutRoomNotifyLuckyGiftTipBinding binding = LayoutRoomNotifyLuckyGiftTipBinding.bind(root);
binding.coinNum.setText(NumberUtils.format(luckyGiftMsgBean.getCoins()));
binding.winNum.setText(java.lang.String.valueOf(luckyGiftMsgBean.getTimes()));
if (luckyGiftMsgBean.getLevel() > 1) {
binding.rootView.setBackgroundResource(R.drawable.bg_lucky_gift_tip_2);
}
root.setAlpha(0f);
root.setScaleX(0f);
root.setScaleY(0f);
gameMainBinding.flLuckyGiftNotifyLayout.addView(root);
GiftAnimUtil.showAnimation(root);
// GiftAnimUtil.expandAnimation(root);
handler.postDelayed(() -> {
try {
root.animate()
.alpha(0f)
.setDuration(500)
.withEndAction(() -> {
gameMainBinding.flLuckyGiftNotifyLayout.post(new Runnable() {
@Override
public void run() {
root.clearAnimation();
gameMainBinding.flLuckyGiftNotifyLayout.removeView(root);
luckyGiftTipPool.release(root);
}
});
})
.start();
} catch (Exception e) {
}
}, 2300);
}
BaseRoomNotifyeLuckGiftDialog allServiceLuckGiftDialog;
private void showLuckyGiftDlg(LuckyGiftMsgAllBean luckyGiftMsgAllBean){
LogUtils.d(" LuckyGiftDlg -- showLuckyGiftDlg() ");
mLuckyGiftList.add(luckyGiftMsgAllBean);
if (!(allServiceLuckGiftDialog != null && allServiceLuckGiftDialog.isShowing())) {
LuckyGiftMsgAllBean data = mLuckyGiftList.remove(0);
LogUtils.d(" LuckyGiftDlg -- showLuckyGiftDlg() -> showLuckyGiftDialog"+mLuckyGiftList.size());
showLuckyGiftDialog(data);
}
}
private void showLuckyGiftDialog(LuckyGiftMsgAllBean luckyGiftMsgAllBean){
LogUtils.d(" LuckyGiftDlg -- showLuckyGiftDialog() ");
allServiceLuckGiftDialog = new BaseRoomNotifyeLuckGiftDialog(requireContext());
allServiceLuckGiftDialog.setLuckyGiftMsgBean(luckyGiftMsgAllBean);
allServiceLuckGiftDialog.setMCallBack(new BaseRoomNotifyeLuckGiftDialog.CallBack() {
@Override
public void onHide() {
LogUtils.d(" LuckyGiftDlg -- showLuckyGiftDialog() ->onHide");
gameMainBinding.getRoot().postDelayed(new Runnable() {
@Override
public void run() {
LogUtils.d(" LuckyGiftDlg -- showLuckyGiftDialog() ->onHide->postDelayed");
if (!mLuckyGiftList.isEmpty()){
LuckyGiftMsgAllBean data = mLuckyGiftList.remove(0);
LogUtils.d(" LuckyGiftDlg -- showLuckyGiftDialog() ->onHide->postDelayed-> "+mLuckyGiftList.size());
showLuckyGiftDialog(data);
}
}
},100);
}
});
allServiceLuckGiftDialog.show();
}
}

View File

@@ -93,8 +93,8 @@ class RoomHeadlineWidget : FrameLayoutRoomWidget {
private fun requestCurrentHeadline() {
safeLaunch {
val data = PublicChatModel.getCurrentHeadline()
updateHeadline(data)
// val data = PublicChatModel.getCurrentHeadline()
// updateHeadline(data)
}
}

View File

@@ -1,884 +0,0 @@
package com.chwl.app.avroom.public_chat;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.text.Spannable;
import android.text.TextUtils;
import android.text.method.LinkMovementMethod;
import android.text.style.ForegroundColorSpan;
import android.text.style.ImageSpan;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.core.content.res.ResourcesCompat;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.SimpleItemAnimator;
import com.chwl.app.R;
import com.chwl.app.UIHelper;
import com.chwl.app.avroom.activity.AVRoomActivity;
import com.chwl.app.avroom.dialog.RoomTeamPKResultDialog;
import com.chwl.app.avroom.widget.OnMsgLongClickListener;
import com.chwl.app.avroom.widget.TemplateMessageAdapter;
import com.chwl.app.common.widget.CustomImageSpan;
import com.chwl.app.common.widget.OriginalDrawStatusClickSpan;
import com.chwl.app.photo.BigPhotoActivity;
import com.chwl.app.photo.PagerOption;
import com.chwl.app.public_chat.core.viewholder.ChatRoomMessageViewHolderThumbBase;
import com.chwl.app.ui.utils.ImageLoadUtils;
import com.chwl.app.ui.utils.ImageLoadUtilsV2;
import com.chwl.app.ui.widget.DividerItemDecoration;
import com.chwl.app.ui.widget.MyItemAnimator;
import com.chwl.app.ui.widget.RecyclerViewNoViewpagerScroll;
import com.chwl.app.ui.widget.TextSpannableBuilder;
import com.chwl.app.ui.widget.magicindicator.buildins.UIUtil;
import com.chwl.app.utils.ObjectTypeHelper;
import com.chwl.app.utils.RegexUtil;
import com.chwl.core.DemoCache;
import com.chwl.core.auth.AuthModel;
import com.chwl.core.bean.attachmsg.RoomQueueMsgAttachment;
import com.chwl.core.decoration.car.bean.CarInfo;
import com.chwl.core.home.event.FollowRoomEvent;
import com.chwl.core.home.model.CollectionRoomModel;
import com.chwl.core.im.custom.bean.CustomAttachment;
import com.chwl.core.im.custom.bean.HeadlineChangedAttachment;
import com.chwl.core.im.custom.bean.MonsterHuntingResultAttachment;
import com.chwl.core.im.custom.bean.MonsterStatusAttachment;
import com.chwl.core.im.custom.bean.RoomBoxPrizeAttachment;
import com.chwl.core.im.custom.bean.RoomFollowOwnerAttachment2;
import com.chwl.core.im.custom.bean.RoomTipAttachment;
import com.chwl.core.im.custom.bean.TarotAttachment;
import com.chwl.core.level.UserLevelResourceType;
import com.chwl.core.manager.AvRoomDataManager;
import com.chwl.core.monsterhunting.bean.MonsterDataBean;
import com.chwl.core.monsterhunting.bean.MonsterHuntingResult;
import com.chwl.core.noble.NobleUtil;
import com.chwl.core.praise.PraiseModel;
import com.chwl.core.public_chat_hall.bean.HeadlineBean;
import com.chwl.core.room.bean.RoomInfo;
import com.chwl.core.room.pk.attachment.RoomPkAttachment;
import com.chwl.core.user.bean.UserInfo;
import com.chwl.core.utils.ExtensionUtil;
import com.chwl.library.common.util.Utils;
import com.chwl.library.utils.JavaUtil;
import com.chwl.library.utils.ListUtils;
import com.chwl.library.utils.ResUtil;
import com.chwl.library.utils.SingleToastUtil;
import com.chwl.library.utils.SizeUtils;
import com.example.lib_utils.UiUtils;
import com.example.lib_utils.spannable.SpannableTextBuilder;
import com.netease.nim.uikit.business.session.emoji.MoonUtil;
import com.netease.nim.uikit.common.util.media.ImageUtil;
import com.netease.nim.uikit.common.util.sys.ScreenUtil;
import com.netease.nimlib.sdk.chatroom.model.ChatRoomMessage;
import com.netease.nimlib.sdk.chatroom.model.ChatRoomMessageExtension;
import com.netease.nimlib.sdk.chatroom.model.ChatRoomNotificationAttachment;
import com.netease.nimlib.sdk.msg.attachment.ImageAttachment;
import com.netease.nimlib.sdk.msg.attachment.MsgAttachment;
import com.netease.nimlib.sdk.msg.constant.MsgTypeEnum;
import com.netease.nimlib.sdk.msg.constant.NotificationType;
import org.greenrobot.eventbus.EventBus;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import io.reactivex.Single;
import io.reactivex.functions.Consumer;
import kotlin.jvm.functions.Function1;
/**
* 直播間消息界面
*
* @author xiaoyu
*/
public class PublicChatMessageView extends FrameLayout {
private static final String TAG = "PublicChatMessageView";
private final static int MAX_MESSAGE_SIZE = 100;//公屏最多展示條數
private final static int BLOCK_MAX_MESSAGE_SIZE = MAX_MESSAGE_SIZE * 3 / 2;//在查看消息停住的時候 最多消息條數.
private final List<ChatRoomMessage> atMessages = new ArrayList<>();
private final List<ChatRoomMessage> chatRoomMessages = new LinkedList<>();
private RecyclerView messageListView;
private TextView tvBottomTip;
private TextView tvAtTip;
private MessageAdapter mMessageAdapter;
private LinearLayoutManager layoutManger;
private int paddingWidth;
private int paddingHeight;
private int whiteColor;
private int greyColor;
private int roomTipColor;
private int badgeWidth;
private int badgeHeight;
private int expLevelHeight;
private int defTextSize = 12;
private volatile boolean needAutoScroll = true;//是否自動滾動到底部
private Consumer<String> clickConsumer;
private OnClick onClick;
private OnMsgLongClickListener onLongClickListener;
private TemplateMessageAdapter templateMessageAdapter;
public PublicChatMessageView(Context context) {
this(context, null);
}
public PublicChatMessageView(Context context, AttributeSet attr) {
this(context, attr, 0);
}
public PublicChatMessageView(Context context, AttributeSet attr, int i) {
super(context, attr, i);
init(context);
}
public void setOnLongClickListener(OnMsgLongClickListener onLongClickListener) {
this.onLongClickListener = onLongClickListener;
}
public void setClickConsumer(Consumer<String> clickConsumer) {
this.clickConsumer = clickConsumer;
}
public void setOnClick(OnClick onClick) {
this.onClick = onClick;
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
}
@SuppressLint("ClickableViewAccessibility")
private void init(Context context) {
whiteColor = ContextCompat.getColor(context, R.color.white);
greyColor = ContextCompat.getColor(context, R.color.white_transparent_50);
roomTipColor = ContextCompat.getColor(context, R.color.color_FEE057);
paddingWidth = Utils.dip2px(context, 11);
paddingHeight = Utils.dip2px(context, 6);
badgeWidth = Utils.dip2px(context, 15);
badgeHeight = Utils.dip2px(context, 15);
//經驗等級圖片後臺已經更換尺寸了公屏同步下尺寸是36:18
expLevelHeight = Utils.dip2px(context, 18);
// 內容區域
layoutManger = new LinearLayoutManager(context, RecyclerView.VERTICAL, false);
LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
messageListView = new RecyclerViewNoViewpagerScroll(context);
messageListView.setLayoutParams(params);
messageListView.setFadingEdgeLength(60);
messageListView.setVerticalFadingEdgeEnabled(true);
messageListView.setOverScrollMode(OVER_SCROLL_NEVER);
messageListView.setHorizontalScrollBarEnabled(false);
addView(messageListView);
messageListView.setLayoutManager(layoutManger);
messageListView.addItemDecoration(new DividerItemDecoration(context, layoutManger.getOrientation(), 16, R.color.transparent));
mMessageAdapter = new MessageAdapter(getContext());
mMessageAdapter.setData(chatRoomMessages);
messageListView.setAdapter(mMessageAdapter);
messageListView.setItemAnimator(new MyItemAnimator());
messageListView.getItemAnimator().setAddDuration(0);
messageListView.getItemAnimator().setChangeDuration(0);
messageListView.getItemAnimator().setMoveDuration(0);
messageListView.getItemAnimator().setRemoveDuration(0);
((SimpleItemAnimator) messageListView.getItemAnimator()).setSupportsChangeAnimations(false);
// 底部有新消息
tvBottomTip = new TextView(context);
LayoutParams params1 = new LayoutParams(
Utils.dip2px(context, 115F), Utils.dip2px(context, 27));
params1.gravity = Gravity.BOTTOM;
params1.leftMargin = UIUtil.getScreenWidth(context) / 2 - UIUtil.dip2px(context, 115 / 2);
tvBottomTip.setBackgroundResource(R.drawable.bg_messge_view_bottom_tip);
tvBottomTip.setGravity(Gravity.CENTER);
tvBottomTip.setText(context.getString(R.string.message_view_bottom_tip));
tvBottomTip.setTextColor(context.getResources().getColor(R.color.appColor));
tvBottomTip.setLayoutParams(params1);
tvBottomTip.setVisibility(GONE);
tvBottomTip.setOnClickListener(v -> {
tvBottomTip.setVisibility(GONE);
needAutoScroll = true;
if (mMessageAdapter.getItemCount() > 0) {
messageListView.smoothScrollToPosition(mMessageAdapter.getItemCount() - 1);
}
});
addView(tvBottomTip);
//有人@我
tvAtTip = new TextView(context);
LayoutParams params2 = new LayoutParams(
Utils.dip2px(context, 115F), Utils.dip2px(context, 27));
params2.gravity = Gravity.BOTTOM;
params2.leftMargin = UIUtil.getScreenWidth(context) / 2 - UIUtil.dip2px(context, 115 / 2);
tvAtTip.setBackgroundResource(R.drawable.bg_messge_view_bottom_tip);
tvAtTip.setGravity(Gravity.CENTER);
tvAtTip.setText(context.getString(R.string.message_view_bottom_tip));
tvAtTip.setTextColor(context.getResources().getColor(R.color.color_FD85C9));
tvAtTip.setLayoutParams(params2);
tvAtTip.setVisibility(GONE);
tvAtTip.setOnClickListener(v -> {
if (!atMessages.isEmpty()) {
int scrollIndex = chatRoomMessages.indexOf(atMessages.remove(0));
if (scrollIndex != -1 && scrollIndex < mMessageAdapter.getItemCount()) {
messageListView.smoothScrollToPosition(scrollIndex);
}
}
needAutoScroll = false;
checkShowAtTip();
});
addView(tvAtTip);
messageListView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
}
@Override
public void onScrollStateChanged(final RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (newState == RecyclerView.SCROLL_STATE_DRAGGING) {
// Logger.e(TAG, "onScrollStateChanged: SCROLL_STATE_DRAGGING");
needAutoScroll = false;
}
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
// Logger.e(TAG, "onScrollStateChanged: SCROLL_STATE_IDLE");
int lastVisibleItemPosition = layoutManger.findLastVisibleItemPosition();
if (lastVisibleItemPosition == RecyclerView.NO_POSITION) {
// Logger.e(TAG, "lastCompletelyVisibleItemPosition : RecyclerView.NO_POSITION");
needAutoScroll = true;
} else if (!atMessages.isEmpty() && atMessages.remove(chatRoomMessages.get(lastVisibleItemPosition))) {
checkShowAtTip();
}
// Log.e(TAG, "lastVisibleItemPosition:" + lastVisibleItemPosition
// + " mMessageAdapter.getItemCount()-1:" + (recyclerView.getAdapter().getItemCount()-1)
// + " dis:"+ (lastVisibleItemPosition-(recyclerView.getAdapter().getItemCount()-1)));
if (lastVisibleItemPosition >= recyclerView.getAdapter().getItemCount() - 3) {
//最後一個顯示出來了
// Logger.e(TAG, ResUtil.getString(R.string.avroom_widget_messageview_01));
needAutoScroll = true;
tvBottomTip.setVisibility(GONE);
keepSizeUnderLimit();
} else {
// Logger.e(TAG, ResUtil.getString(R.string.avroom_widget_messageview_02));
// needAutoScroll = false;
}
}
}
});
}
private TemplateMessageAdapter getTemplateMessageAdapter() {
if (templateMessageAdapter == null) {
templateMessageAdapter = new TemplateMessageAdapter(uid -> {
if (clickConsumer != null) {
Single.just(String.valueOf(uid)).subscribe(clickConsumer);
}
});
}
return templateMessageAdapter;
}
/**
* 添加公屏消息請使用 {@link AvRoomDataManager#addChatRoomMessage(ChatRoomMessage)}
*/
public void addMessages(ChatRoomMessage msg) {
if (msg == null) return;
chatRoomMessages.add(msg);
//通知adapter 刷新
mMessageAdapter.notifyItemInserted(mMessageAdapter.getItemCount() - 1);
showTipsOrScrollToBottom();
checkAtMe(msg, false);
}
public void addMessages(List<ChatRoomMessage> messages) {
if (messages == null) return;
chatRoomMessages.addAll(messages);
//通知adapter 刷新
mMessageAdapter.notifyDataSetChanged();
showTipsOrScrollToBottom();
for (ChatRoomMessage message : messages) {
checkAtMe(message, true);
}
}
public void addHistoryMessages(List<ChatRoomMessage> messages) {
chatRoomMessages.addAll(0, messages);
mMessageAdapter.notifyDataSetChanged();
messageListView.scrollToPosition(mMessageAdapter.getItemCount() - 1);
for (ChatRoomMessage message : messages) {
checkAtMe(message, true);
}
}
private void keepSizeUnderLimit() {
while (chatRoomMessages.size() > MAX_MESSAGE_SIZE) {
Log.i("keepSizeUnderLimit", "size" + chatRoomMessages.size());
ChatRoomMessage message = chatRoomMessages.remove(0);
if (atMessages.remove(message)) {
checkShowAtTip();
}
mMessageAdapter.notifyItemRemoved(0);
}
}
private void checkShowAtTip() {
tvAtTip.setText(getContext().getString(R.string.message_at_tip, atMessages.size()));
tvAtTip.setVisibility(atMessages.size() == 0 ? GONE : VISIBLE);
}
private void checkAtMe(ChatRoomMessage msg, boolean history) {
if (msg.getMsgType() != MsgTypeEnum.text) return;
List<String> atUids = ExtensionUtil.getListExtension(msg, UserInfo.AT_UIDS);
List<String> atNames = ExtensionUtil.getListExtension(msg, UserInfo.AT_NAMES);
if (!ListUtils.isListEmpty(atUids) && !ListUtils.isListEmpty(atNames)) {
for (int i = 0; i < atUids.size(); i++) {
String uid = atUids.get(i);
// 只有當被 @ 人的數組中包含自己的時候才會去變色
if (Objects.equals(uid, String.valueOf(AuthModel.get().getCurrentUid()))) {
Map<String, Long> atMap = DemoCache.readAtMsgUuid();
if (atMap == null || !atMap.containsKey(msg.getUuid())) {
if (!atMessages.contains(msg) && (!needAutoScroll || history)) {
atMessages.add(msg);
checkShowAtTip();
}
DemoCache.saveAtMsgUuid(msg.getUuid());
}
}
}
}
}
public void showTipsOrScrollToBottom() {
if (!needAutoScroll) {
tvBottomTip.setVisibility(VISIBLE);
//超過某值後自動滾動下去
if (mMessageAdapter.getItemCount() > BLOCK_MAX_MESSAGE_SIZE) {
if (mMessageAdapter.getItemCount() > 0) {
messageListView.smoothScrollToPosition(mMessageAdapter.getItemCount() - 1);
}
}
return;
}
}
public void release() {
}
public void clear() {
if (mMessageAdapter != null) {
chatRoomMessages.clear();
mMessageAdapter.notifyDataSetChanged();
}
if (tvBottomTip != null) {
needAutoScroll = true;
tvBottomTip.setVisibility(GONE);
}
}
public void setNeedAutoScroll(boolean needAutoScroll) {
this.needAutoScroll = needAutoScroll;
}
public RecyclerView getMessageListView(){
return messageListView;
}
public interface OnClick {
/**
* 公屏查看公告
*/
void onShowRoomIntroduction();
}
private class MessageAdapter extends RecyclerView.Adapter<MessageAdapter.MessageViewHolder> implements OnClickListener,Function1<Drawable, ImageSpan> {
private Context mContext;
private List<ChatRoomMessage> data;
private int ITEM_TYPE_IMAGE = 1;
public MessageAdapter(Context mContext) {
this.mContext = mContext;
}
public void setData(List<ChatRoomMessage> data) {
this.data = data;
}
@Override
public int getItemViewType(int position) {
ChatRoomMessage chatRoomMessage = data.get(position);
if (chatRoomMessage.getMsgType() == MsgTypeEnum.image) {
return ITEM_TYPE_IMAGE;
}
return super.getItemViewType(position);
}
@Override
public MessageViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == ITEM_TYPE_IMAGE) {
return new MessageAdapter.MessageViewHolder(LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_item_chatroom_msg_image, parent, false));
}
return new MessageViewHolder(LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_item_chatrrom_msg, parent, false));
}
@Override
public void onBindViewHolder(MessageViewHolder holder, int position) {
if (getItemViewType(position) == ITEM_TYPE_IMAGE) {
convertImage(holder, data.get(position));
} else {
convert(holder, data.get(position));
}
}
@Override
public int getItemCount() {
return data.size();
}
protected void convertImage(MessageViewHolder baseViewHolder, ChatRoomMessage chatRoomMessage) {
TextView tvContent = baseViewHolder.tvContent;
tvContent.setLineSpacing(0, 1);
tvContent.setGravity(Gravity.START | Gravity.CENTER_VERTICAL);
tvContent.setOnClickListener(this);
tvContent.setTag(chatRoomMessage);
if (UiUtils.INSTANCE.isRtl(tvContent.getContext())) {
tvContent.setTextDirection(View.TEXT_DIRECTION_RTL);
}
try {
setVIPMessageBackground(chatRoomMessage, baseViewHolder.itemView);
ChatRoomMessageExtension extension = chatRoomMessage.getChatRoomMessageExtension();
TextSpannableBuilder text = new TextSpannableBuilder(tvContent);
addCommonTag(chatRoomMessage, text, tvContent);
String nickName = extension == null ? ResUtil.getString(R.string.avroom_widget_messageview_0116) : RegexUtil.getPrintableString(extension.getSenderNick());
text.append(nickName, new ForegroundColorSpan(greyColor));
tvContent.setText(text.build());
ImageView imageView = baseViewHolder.itemView.findViewById(R.id.iv_image);
ImageAttachment msgAttachment = (ImageAttachment) chatRoomMessage.getAttachment();
String path = msgAttachment.getThumbPath();
if (TextUtils.isEmpty(path)) {
path = msgAttachment.getPath();
}
if (TextUtils.isEmpty(path)) {
path = "";
}
ImageLoadUtilsV2.loadImage(imageView, path);
int[] bounds = new int[]{msgAttachment.getWidth(), msgAttachment.getHeight()};
ImageUtil.ImageSize imageSize = ImageUtil.getThumbnailDisplaySize(bounds[0], bounds[1], ChatRoomMessageViewHolderThumbBase.getImageMaxEdge(), ChatRoomMessageViewHolderThumbBase.getImageMinEdge());
ViewGroup.LayoutParams maskParams = imageView.getLayoutParams();
maskParams.width = imageSize.width;
maskParams.height = imageSize.height;
imageView.setLayoutParams(maskParams);
String finalPath = path;
imageView.setOnClickListener(v -> {
BigPhotoActivity.start((Activity) mContext, ObjectTypeHelper.pathToCustomItems(finalPath),
0, new PagerOption());
});
} catch (Exception e) {
e.printStackTrace();
}
}
protected void convert(MessageViewHolder baseViewHolder, ChatRoomMessage chatRoomMessage) {
if (chatRoomMessage == null) return;
TextView tvContent = baseViewHolder.tvContent;
tvContent.setLineSpacing(0, 1);
tvContent.setTextColor(Color.WHITE);
tvContent.setTextSize(defTextSize);
tvContent.setOnClickListener(this);
tvContent.setOnLongClickListener(null);
tvContent.setTag(chatRoomMessage);
tvContent.setGravity(Gravity.START | Gravity.CENTER_VERTICAL);
if (UiUtils.INSTANCE.isRtl(tvContent.getContext())) {
tvContent.setTextDirection(View.TEXT_DIRECTION_RTL);
}
clearBackground(tvContent);
try {
if (chatRoomMessage.getMsgType() == MsgTypeEnum.tip) {
// 房間通告
tvContent.setTextColor(ContextCompat.getColor(mContext, R.color.color_white));
tvContent.setText(chatRoomMessage.getContent());
tvContent.setBackgroundResource(R.drawable.shape_room_message_tip_bg);
} else if (chatRoomMessage.getMsgType() == MsgTypeEnum.text) {
setMsgText(chatRoomMessage, tvContent);
setVIPMessageBackground(chatRoomMessage, tvContent);
} else if (chatRoomMessage.getMsgType() == MsgTypeEnum.notification) {
// 加上勛章
setMsgNotification(chatRoomMessage, tvContent, baseViewHolder.getAdapterPosition());
setVIPMessageBackground(chatRoomMessage, tvContent);
} else if (chatRoomMessage.getMsgType() == MsgTypeEnum.custom) {
if (chatRoomMessage.getAttachment() != null && chatRoomMessage.getAttachment() instanceof CustomAttachment) {
CustomAttachment attachment = (CustomAttachment) chatRoomMessage.getAttachment();
int first = attachment.getFirst();
int second = attachment.getSecond();
if (first == CustomAttachment.CUSTOM_MSG_HEADLINE_CHANGED) {
if (second == CustomAttachment.CUSTOM_MSG_HEADLINE_CHANGED_SUB) {
setHeadlineMsg(chatRoomMessage, tvContent, attachment);
}
} else {
tvContent.setTextColor(Color.WHITE);
tvContent.setText(tvContent.getResources().getText(R.string.not_support_message_tip));
}
} else {
tvContent.setText("");
}
}
} catch (UnsupportedOperationException e) {
e.printStackTrace();
clearBackground(tvContent);
tvContent.setTextColor(Color.WHITE);
tvContent.setText(tvContent.getResources().getText(R.string.not_support_message_tip));
} catch (Exception e) {
clearBackground(tvContent);
tvContent.setText("");
}
}
private void clearBackground(TextView textView) {
// 清除文字
textView.setText("");
// 清除聊天氣泡
textView.setBackgroundResource(R.drawable.shape_room_message_bg);
textView.setPadding(paddingWidth, paddingHeight, paddingWidth, paddingHeight);
}
private void setNullBackground(TextView textView) {
// 清除聊天氣泡
textView.setBackground(null);
textView.setPadding(0, 0, 0, 0);
}
public void setVIPMessageBackground(ChatRoomMessage chatRoomMessage, View view) {
String androidBubbleUrl = NobleUtil.getResource(UserInfo.BUBBLE_URL_ANDROID, chatRoomMessage);
if (TextUtils.isEmpty(androidBubbleUrl)) return;
view.setPadding(paddingWidth, ScreenUtil.dip2px(10), paddingWidth, ScreenUtil.dip2px(10));
ImageLoadUtils.loadNinePatchBg(view, androidBubbleUrl);
}
/**
* {badge}{level}xxx: 文字內容
*
* @param chatRoomMessage -
* @param tvContent -
*/
private void setMsgText(ChatRoomMessage chatRoomMessage, TextView tvContent) {
TextSpannableBuilder text = new TextSpannableBuilder(tvContent);
addCommonTag(chatRoomMessage, text, tvContent);
String nickName;
if (chatRoomMessage.getFromAccount() != null && chatRoomMessage.getFromAccount().equals(AuthModel.get().getCurrentUid() + "")) {
nickName = ResUtil.getString(R.string.avroom_widget_messageview_0116);
} else {
nickName = NobleUtil.getNamePlate(UserInfo.NICK, chatRoomMessage);
}
text.append(nickName, new ForegroundColorSpan(greyColor));
text.append(": " + chatRoomMessage.getContent(), new ForegroundColorSpan(getResources().getColor(R.color.white)));
List<String> atUids = ExtensionUtil.getListExtension(chatRoomMessage, UserInfo.AT_UIDS);
List<String> atNames = ExtensionUtil.getListExtension(chatRoomMessage, UserInfo.AT_NAMES);
if (!ListUtils.isListEmpty(atUids) && !ListUtils.isListEmpty(atNames)) {
for (int i = 0; i < atUids.size(); i++) {
String name = atNames.get(i);
String uid = atUids.get(i);
// 只有當被 @ 人的數組中包含自己的時候才會去變色
if (Objects.equals(uid, String.valueOf(AuthModel.get().getCurrentUid()))) {
Pattern pattern = Pattern.compile(Pattern.quote(name));
Matcher matcher = pattern.matcher(text.build().toString());
while (matcher.find()) {
int start = matcher.start();
int end = matcher.end();
text.build().setSpan(new ForegroundColorSpan(getContext().getResources().getColor(R.color.color_FD85C9)),
start, end, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
}
}
}
}
if (Objects.equals(chatRoomMessage.getFromAccount(), String.valueOf(AuthModel.get().getCurrentUid()))) {
tvContent.setOnLongClickListener(null);
} else {
tvContent.setOnLongClickListener(v -> {
if (onLongClickListener != null) {
onLongClickListener.onLongClick(v, chatRoomMessage.getFromAccount(), nickName);
}
return true;
});
}
MoonUtil.replaceEmoticons(getContext(), text.builder.toString(), text.builder, this);
tvContent.setText(text.build());
}
private void addCommonTag(ChatRoomMessage chatRoomMessage, @NonNull TextSpannableBuilder builder, TextView tvContent) {
ChatRoomMessageExtension extension = chatRoomMessage.getChatRoomMessageExtension();
String userLevel = NobleUtil.getLevel(UserLevelResourceType.EXPER_URL, chatRoomMessage);
boolean isOfficial = NobleUtil.getIsOfficial(UserInfo.IS_OFFICIAL, chatRoomMessage);
String vipIcon = NobleUtil.getResource(UserInfo.VIP_ICON, chatRoomMessage);
builder.append(vipIcon, expLevelHeight)
.append(isOfficial ? ResourcesCompat.getDrawable(getResources(),
R.mipmap.ic_user_official_13dp, null) : null,
badgeWidth, badgeHeight)
.append(getNewUserDrawable(chatRoomMessage), badgeWidth, badgeHeight)
.append(AvRoomDataManager.get().isSuperAdmin(chatRoomMessage.getFromAccount()) ? ResourcesCompat.getDrawable(getResources(),
R.drawable.ic_room_super_admin, null) : null,
SizeUtils.dp2px(tvContent.getContext(), 23), expLevelHeight);
// 官方主播認證
String tvOfficialMask = NobleUtil.getLevel(UserInfo.OAC_NAME, chatRoomMessage).trim();
String ivOfficialMask = NobleUtil.getLevel(UserInfo.OAC_ICON, chatRoomMessage);
if (!TextUtils.isEmpty(tvOfficialMask) && !TextUtils.isEmpty(ivOfficialMask) && extension != null) { // extension != null 表示自己
builder.appendBgAndContent(ivOfficialMask, tvOfficialMask);
} else if (!TextUtils.isEmpty(ivOfficialMask)) {
builder.append(ivOfficialMask, SizeUtils.dp2px(tvContent.getContext(), 62), expLevelHeight);
}
//等級
builder.append(userLevel, expLevelHeight);
//銘牌
String tvNamePlate = NobleUtil.getNamePlate(UserInfo.NAMEPLATE_WORD, chatRoomMessage).trim();
String ivNamePlate = NobleUtil.getNamePlate(UserInfo.NAMEPLATE_PIC, chatRoomMessage);
if (!TextUtils.isEmpty(tvNamePlate) && !TextUtils.isEmpty(ivNamePlate)) { // extension != null 表示自己
builder.appendBgAndContent(ivNamePlate, tvNamePlate);
} else if (!TextUtils.isEmpty(ivNamePlate)) {
builder.append(ivNamePlate, expLevelHeight);
}
}
private void setHeadlineMsg(ChatRoomMessage chatRoomMessage, TextView tvContent, CustomAttachment attachment) {
HeadlineChangedAttachment headlineAttachment = (HeadlineChangedAttachment) attachment;
SpannableTextBuilder builder = new SpannableTextBuilder(tvContent);
if (attachment.getSecond() == CustomAttachment.CUSTOM_MSG_HEADLINE_CHANGED_SUB) {
HeadlineBean data = headlineAttachment.getHeadlineData();
String nick = null;
if (data != null) {
nick = data.getNick();
}
if (nick == null) {
nick = "";
}
builder.appendText(String.format(ResUtil.getString(R.string.headline_message_format), nick), null, null, null, null, null, null);
builder.setTextStyle(nick, ContextCompat.getColor(getContext(), R.color.color_DE3446), null, null, null, null, null);
}
tvContent.setText(builder.build());
tvContent.setTextSize(11);
setNullBackground(tvContent);
}
/**
* {badge}xxx來了
*
* @param chatRoomMessage -
* @param tvContent -
*/
private void setMsgNotification(ChatRoomMessage chatRoomMessage, TextView tvContent, int position) {
int fromType = 0;
String fromNick = "";
String fromUid = "";
Map<String, Object> remoteExtension = chatRoomMessage.getRemoteExtension();
if (remoteExtension != null) {
fromType = (int) remoteExtension.get("fromType");
fromNick = (String) remoteExtension.get("fromNick");
fromUid = (String) remoteExtension.get("fromUid");
}
ChatRoomNotificationAttachment attachment = (ChatRoomNotificationAttachment) chatRoomMessage.getAttachment();
String senderNick = "";
List<String> nicks = attachment.getTargetNicks();
if (nicks != null && nicks.size() > 0)
senderNick = RegexUtil.getPrintableString(attachment.getTargetNicks().get(0));
if (attachment.getType() != NotificationType.ChatRoomMemberIn) return;
// 座駕
String carName = NobleUtil.getCarName(CarInfo.CAR_NAME, chatRoomMessage);
carName = TextUtils.isEmpty(carName) ? "" : "\"" + carName + "\"";
TextSpannableBuilder text = new TextSpannableBuilder(tvContent);
addCommonTag(chatRoomMessage, text, tvContent);
text.append(senderNick, new ForegroundColorSpan(roomTipColor),
new OriginalDrawStatusClickSpan() {
@Override
public void onClick(@NonNull View view) {
if (clickConsumer != null) {
Single.just(chatRoomMessage.getFromAccount())
.doOnSuccess(clickConsumer).subscribe();
}
}
});
text.append(TextUtils.isEmpty(carName) ? "" : ResUtil.getString(R.string.avroom_widget_messageview_0150), new ForegroundColorSpan(greyColor))
.append(carName, new ForegroundColorSpan(roomTipColor));
String enterText = ResUtil.getString(R.string.avroom_widget_messageview_0151);
if (fromType == AVRoomActivity.FROM_TYPE_RECOMMEND) {
enterText = ResUtil.getString(R.string.avroom_widget_messageview_0152);
}
if (fromType == AVRoomActivity.FROM_TYPE_USER || fromType == AVRoomActivity.FROM_TYPE_HELLO) {
String finalFromUid = fromUid;
text.append(ResUtil.getString(R.string.avroom_widget_messageview_0153), new ForegroundColorSpan(whiteColor))
.append(fromNick, new ForegroundColorSpan(roomTipColor),
new OriginalDrawStatusClickSpan() {
@Override
public void onClick(@NonNull View view) {
if (clickConsumer != null) {
Single.just(finalFromUid).doOnSuccess(clickConsumer).subscribe();
}
}
});
enterText = ResUtil.getString(R.string.avroom_widget_messageview_0154);
}
if (fromType == AVRoomActivity.FROM_TYPE_GAME_RECOMMEND) {
String finalFromUid = fromUid;
text.append(ResUtil.getString(R.string.avroom_widget_messageview_0155), new ForegroundColorSpan(whiteColor))
.append(fromNick, new ForegroundColorSpan(roomTipColor),
new OriginalDrawStatusClickSpan() {
@Override
public void onClick(@NonNull View view) {
if (clickConsumer != null) {
Single.just(finalFromUid).doOnSuccess(clickConsumer).subscribe();
}
}
});
enterText = ResUtil.getString(R.string.avroom_widget_messageview_0156);
}
text.append(enterText, new ForegroundColorSpan(whiteColor));
tvContent.setText(text.build());
tvContent.setOnClickListener(null);
tvContent.setMovementMethod(new LinkMovementMethod());
}
@Nullable
private Drawable getNewUserDrawable(ChatRoomMessage chatRoomMessage) {
boolean newUser = NobleUtil.getIsNewUser(UserInfo.IS_NEW_USER, chatRoomMessage);
boolean isHelloUser = NobleUtil.getIsNewUser(UserInfo.IS_FROM_SAY_HELLO_CHANNEL, chatRoomMessage);
if (newUser) {
return ResourcesCompat.getDrawable(getResources(),
isHelloUser ? R.drawable.ic_new_user_hello : R.drawable.ic_new_user,
null);
}
return null;
}
@SuppressLint("CheckResult")
@Override
public void onClick(View v) {
String account = "";
ChatRoomMessage chatRoomMessage = (ChatRoomMessage) v.getTag();
if (chatRoomMessage.getMsgType() != MsgTypeEnum.tip) {
if (chatRoomMessage.getMsgType() == MsgTypeEnum.text) {
account = chatRoomMessage.getFromAccount();
} else if (chatRoomMessage.getMsgType() == MsgTypeEnum.notification) {
account = chatRoomMessage.getFromAccount();
} else if (chatRoomMessage.getMsgType() == MsgTypeEnum.custom) {
CustomAttachment attachment = (CustomAttachment) chatRoomMessage.getAttachment();
if (attachment.getFirst() == CustomAttachment.CUSTOM_MSG_HEADER_TYPE_ROOM_TIP) {
account = ((RoomTipAttachment) attachment).getUid() + "";
} else if (attachment.getFirst() == CustomAttachment.CUSTOM_MSG_BOX) {
account = String.valueOf(((RoomBoxPrizeAttachment) attachment).getUid());
} else if (attachment.getFirst() == CustomAttachment.CUSTOM_MSG_HEADER_TYPE_QUEUE) {
long handleUid = ((RoomQueueMsgAttachment) attachment).handleUid;
if (handleUid > 0) {
account = ((RoomQueueMsgAttachment) attachment).handleUid + "";
} else {
//ios沒用handleUid導致iOS發的自定義消息拿不到uid
account = chatRoomMessage.getFromAccount();
}
} else if (attachment.getFirst() == CustomAttachment.CUSTOM_MSG_HEADER_TYPE_MONSTER_HUNTING) {
switch (attachment.getSecond()) {
case CustomAttachment.CUSTOM_MSG_SUB_TYPE_MONSTER_HUNTING:
MonsterDataBean dataBean = ((MonsterStatusAttachment) attachment).getDataBean();
RoomInfo mCurrentRoomInfo = AvRoomDataManager.get().mCurrentRoomInfo;
if (!Objects.equals(mCurrentRoomInfo.getUid(), dataBean.getAppearRoomUid())) {
AVRoomActivity.start(getContext(), dataBean.getAppearRoomUid());
} else {
SingleToastUtil.showToast("你已經在怪獸房間內");
}
break;
case CustomAttachment.CUSTOM_NOTI_SUB_GAME_RESULT:
MonsterHuntingResult result = ((MonsterHuntingResultAttachment) attachment).getResult();
UIHelper.showMonsterResult(getContext(), String.valueOf(result.getMonster().getMonsterId()));
break;
}
} else if (attachment.getFirst() == CustomAttachment.CUSTOM_MESS_HEAD_ROOM_PK) {
if (attachment.getSecond() == CustomAttachment.CUSTOM_MESS_SUB_ROOM_PK_RESULT) {
RoomTeamPKResultDialog pkResultDialog = new RoomTeamPKResultDialog(getContext(), ((RoomPkAttachment) attachment).getRoomPkData());
pkResultDialog.show();
}
} else if (attachment instanceof RoomFollowOwnerAttachment2 && !AvRoomDataManager.get().isRoomFans) {
CollectionRoomModel.get().followRoom("1", ((RoomFollowOwnerAttachment2) attachment).getOwnerUid())
.subscribe(s -> {
AvRoomDataManager.get().isRoomFans = true;
SingleToastUtil.showToast("收藏成功!");
EventBus.getDefault().post(new FollowRoomEvent());
PraiseModel.get().setFollowRoomSuccessRoomTip(JavaUtil.str2long(chatRoomMessage.getFromAccount()));
});
} else if (attachment.getFirst() == CustomAttachment.CUSTOM_MESS_TAROT) {
if (attachment instanceof TarotAttachment) {
account = ((TarotAttachment) attachment).getTarotMsgBean().getUid() + "";
}
}
}
if (TextUtils.isEmpty(account)) return;
if (clickConsumer != null) {
Single.just(account).subscribe(clickConsumer);
}
} else {
String content = chatRoomMessage.getContent();
if (!TextUtils.isEmpty(content) && content.equals(ResUtil.getString(R.string.yizhuan_xchat_android_constants_xchatconstants_08)))
if (onClick != null) {
onClick.onShowRoomIntroduction();
}
}
}
@Override
public ImageSpan invoke(Drawable drawable) {
return new CustomImageSpan(drawable);
}
class MessageViewHolder extends RecyclerView.ViewHolder {
TextView tvContent;
public MessageViewHolder(View itemView) {
super(itemView);
tvContent = itemView.findViewById(R.id.tv_content);
}
}
}
}

View File

@@ -1,111 +0,0 @@
package com.chwl.app.avroom.public_chat
import android.content.Context
import android.util.AttributeSet
import com.chwl.app.R
import com.chwl.app.public_chat.core.ChatRoomClient
import com.chwl.app.public_chat.core.ChatRoomClientManager
import com.chwl.core.im.custom.bean.HeadlineChangedAttachment
import com.chwl.core.support.room.FrameLayoutRoomWidget
import com.chwl.core.support.room.RoomView
import com.chwl.library.utils.SingleToastUtil
import com.netease.nim.uikit.api.model.NimException
import com.netease.nimlib.sdk.chatroom.model.ChatRoomMessage
import com.netease.nimlib.sdk.msg.constant.MsgTypeEnum
import com.netease.nimlib.sdk.msg.model.QueryDirectionEnum
class PublicChatRoomMessageWidget : FrameLayoutRoomWidget {
private val messageView: PublicChatMessageView = PublicChatMessageView(context)
private var chatRoomClient: ChatRoomClient? = null
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
context,
attrs,
defStyleAttr
)
constructor(
context: Context,
attrs: AttributeSet?,
defStyleAttr: Int,
defStyleRes: Int
) : super(context, attrs, defStyleAttr, defStyleRes)
init {
addView(messageView, LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT))
}
override fun onStart(roomView: RoomView) {
super.onStart(roomView)
chatRoomClient = ChatRoomClientManager.getPublicChatClient()
if (chatRoomClient == null) {
SingleToastUtil.showToast(R.string.public_chat_not_found)
}
chatRoomClient?.let {
initChatRoom(it)
}
}
private fun onReceiveMessage(message: ChatRoomMessage) {
if (!filterMessageForMessageList(message)) {
messageView.addMessages(message)
}
}
private fun initChatRoom(chatRoomClient: ChatRoomClient) {
getCompositeDisposable().add(
chatRoomClient.enterChatRoom()
.subscribe({ requestHistory(chatRoomClient) },
{
if (it is NimException) {
SingleToastUtil.showToast(context.getString(R.string.avroom_fragment_homepartyroomfragment_011) + "(${it.code})")
} else {
SingleToastUtil.showToast(R.string.avroom_fragment_homepartyroomfragment_011)
}
})
)
getCompositeDisposable().add(chatRoomClient.messageObservable.subscribe {
it.forEach { message ->
onReceiveMessage(message)
}
})
}
private fun requestHistory(chatRoomClient: ChatRoomClient) {
val typeEnums = arrayOf(MsgTypeEnum.text, MsgTypeEnum.image)
getCompositeDisposable().add(
chatRoomClient.requestRemoteMessageType(
0,
50,
QueryDirectionEnum.QUERY_OLD,
typeEnums
).subscribe({
messageView.addHistoryMessages(it.reversed())
}, {
it.printStackTrace()
})
)
}
private fun filterMessageForMessageList(message: ChatRoomMessage): Boolean {
if (message.msgType == MsgTypeEnum.custom && message.attachment is HeadlineChangedAttachment) {
val data = (message.attachment as HeadlineChangedAttachment).headlineData
if (data == null || !data.isValid()) {
return true
}
}
return false
}
fun getMessageView() = messageView
override fun onStop() {
super.onStop()
chatRoomClient = null
}
}

View File

@@ -21,6 +21,7 @@ import com.example.lib_utils.ktx.singleClick
/**
* 房间榜单入口
* //todo-- 房间榜单入口
*/
class RoomRankNumberWidget : FrameLayoutRoomWidget, RoomWidget {

View File

@@ -261,6 +261,7 @@ public class BottomView extends LinearLayout implements View.OnClickListener {
}
public void updateGameEntrance() {
//todo-- game btn
if (AvRoomDataManager.get().isManager() || SuperAdminUtil.isSuperAdmin()) {
if (!AvRoomDataManager.get().isCpRoom()) {
pkGameView.setVisibility(VISIBLE);
@@ -273,6 +274,7 @@ public class BottomView extends LinearLayout implements View.OnClickListener {
if (AvRoomDataManager.get().isSingleRoom() || AvRoomDataManager.get().isDatingMode()) {
pkGameView.setVisibility(GONE);
}
}
public void showHomePartyDownMicBottom() {

View File

@@ -23,6 +23,8 @@ import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import com.chwl.core.utils.ComboUtil;
import com.chwl.core.auth.AuthModel;
import com.example.lib_utils.UiUtils;
import com.netease.nim.uikit.common.util.log.LogUtil;
import com.netease.nimlib.sdk.chatroom.model.ChatRoomMessage;
@@ -89,6 +91,7 @@ public class GiftV2View extends FrameLayout implements GiftEffectView.GiftEffect
private int mScreenWidth;
private int mScreenHeight;
private Keyframe[] keyScale;
private Keyframe[] keyScaleCombo;
private Keyframe[] keyTrans;
private SvgaObjectPool mMagicViewPool;
@@ -126,6 +129,13 @@ public class GiftV2View extends FrameLayout implements GiftEffectView.GiftEffect
keyScale[4] = (Keyframe.ofFloat(0.5f, 2f));
keyScale[5] = (Keyframe.ofFloat(0.8f, 2f));
keyScale[6] = (Keyframe.ofFloat(1f, 1f));
keyScaleCombo = new Keyframe[4];
keyScaleCombo[0] = (Keyframe.ofFloat(0f, 0.25f));
keyScaleCombo[1] = (Keyframe.ofFloat(0.25f, 0.5f));
keyScaleCombo[2] = (Keyframe.ofFloat(0.5f, 0.75f));
keyScaleCombo[3] = (Keyframe.ofFloat(1f, 1f));
keyTrans = new Keyframe[3];
keyTrans[0] = (Keyframe.ofFloat(0f, 0));
keyTrans[1] = (Keyframe.ofFloat(0.2f, 0));
@@ -255,6 +265,14 @@ public class GiftV2View extends FrameLayout implements GiftEffectView.GiftEffect
}
Point senderPoint = micViewPoint.get(senderPosition);
Point receivePoint = micViewPoint.get(receivePosition);
// 连击 特殊动画
if (giftReceiveInfo.getUid() == AuthModel.get().getCurrentUid()){
if (ComboUtil.INSTANCE.isChangePoint()) {
senderPoint = ComboUtil.INSTANCE.getPoint();
}
}
//设置动画结束的位置
if (receivePoint == null || isGameRoomMoreThan6People()) { //这种情况就是接收者已经不在麦上
//礼物送到中间的位置
@@ -627,6 +645,7 @@ public class GiftV2View extends FrameLayout implements GiftEffectView.GiftEffect
return;
}
GiftInfo giftInfo = giftReceiveInfo.getGift();
giftInfo.uid = giftReceiveInfo.getUid();
if (giftInfo == null) {
return;
}
@@ -668,8 +687,24 @@ public class GiftV2View extends FrameLayout implements GiftEffectView.GiftEffect
PropertyValuesHolder p1 = PropertyValuesHolder.ofKeyframe("translationY", keyTrans[0], keyTrans[1], keyTrans[2], keyTransY3, keyTransY4, keyTransY5);
PropertyValuesHolder p2 = PropertyValuesHolder.ofKeyframe("scaleX", keyScale);
PropertyValuesHolder p3 = PropertyValuesHolder.ofKeyframe("scaleY", keyScale);
ObjectAnimator objectAnimator = ObjectAnimator.ofPropertyValuesHolder(imageView, p2, p3, p1, p0);
objectAnimator.setDuration(4000);
PropertyValuesHolder p0c = PropertyValuesHolder.ofKeyframe("translationX", keyTrans[0], keyTransX5);
PropertyValuesHolder p1c = PropertyValuesHolder.ofKeyframe("translationY", keyTrans[0], keyTransY5);
PropertyValuesHolder p2c = PropertyValuesHolder.ofKeyframe("scaleX", keyScaleCombo);
PropertyValuesHolder p3c = PropertyValuesHolder.ofKeyframe("scaleY", keyScaleCombo);
long time;
ObjectAnimator objectAnimator;
// 连击 特殊动画
if (ComboUtil.INSTANCE.isChangePoint() && giftInfo.uid == AuthModel.get().getCurrentUid()){
objectAnimator = ObjectAnimator.ofPropertyValuesHolder(imageView, p2c, p3c, p1c, p0c);
time = 600;
}else {
objectAnimator = ObjectAnimator.ofPropertyValuesHolder(imageView, p2, p3, p1, p0);
time = 2000;
}
objectAnimator.setDuration(time);
objectAnimator.start();
objectAnimator.addListener(new AnimatorListenerAdapter() {
@Override

View File

@@ -1442,6 +1442,7 @@ class RoomEffectView @JvmOverloads constructor(
enterRoomEffects = remoteExtension[UserInfo.ENTER_ROOM_EFFECTS] as String?
}
val wrapNick = "" + targetNicks[0].subAndReplaceDot(7) + "" + enterText
if (!TextUtils.isEmpty(enterRoomEffects)) {
playMemberInAnimByUrl(wrapNick, enterRoomEffects)
} else {
@@ -1495,7 +1496,11 @@ class RoomEffectView @JvmOverloads constructor(
private fun playMemberInAnim(text: String, svgaVideoEntity: SVGAVideoEntity) {
binding.roomMenberInSvga.visibility = VISIBLE
binding.roomMenberInSvga.loops = 1
if (svgaVideoEntity.frames == 1) {
binding.roomMenberInSvga.loops = 50
} else {
binding.roomMenberInSvga.loops = 1
}
binding.roomMenberInSvga.clearsAfterStop = true
val dynamicEntity = SVGADynamicEntity()
val textPaint = TextPaint()

View File

@@ -0,0 +1,118 @@
package com.chwl.app.avroom.widget;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Point;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
import androidx.annotation.NonNull;
import androidx.core.view.ViewCompat;
import androidx.customview.widget.ViewDragHelper;
import com.netease.nim.uikit.common.util.sys.ScreenUtil;
/**
* 侧滑FrameLayout
* 子View左滑删除右滑弹起后复位
*/
public class VDHLayout extends FrameLayout {
private final ViewDragHelper mDragHelper;
private final Point mAutoBackOriginPos = new Point();
private OnViewGoneListener listener;
public VDHLayout(Context context, AttributeSet attrs) {
super(context, attrs);
mDragHelper = ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() {
@Override
public boolean tryCaptureView(@NonNull View child, int pointerId) {
mAutoBackOriginPos.x = child.getLeft();
mAutoBackOriginPos.y = child.getTop();
return true;
}
/**
* view的left
*/
@Override
public int clampViewPositionHorizontal(@NonNull View child, int left, int dx) {
return left;
}
/**
* view的top
*/
@Override
public int clampViewPositionVertical(@NonNull View child, int top, int dy) {
return child.getTop();
}
//手指释放的时候回调
@Override
public void onViewReleased(@NonNull View releasedChild, float xvel, float yvel) {
//mAutoBackView手指释放时可以自动回去
if (releasedChild.getLeft() < 0 && ((Math.abs(releasedChild.getLeft()) >= releasedChild.getMeasuredWidth() * 0.2))) {
releasedChild.setEnabled(false);
releasedChild.animate()
.setDuration(100L)
.translationX(-ScreenUtil.getDisplayWidth())
.alpha(0F)
.withEndAction(() -> {
releasedChild.setVisibility(GONE);
if(listener != null){
listener.onViewGone();
}
}).start();
} else {
mDragHelper.settleCapturedViewAt(mAutoBackOriginPos.x, mAutoBackOriginPos.y);
ViewCompat.postInvalidateOnAnimation(VDHLayout.this);
}
}
//在边界拖动时回调
@Override
public void onEdgeDragStarted(int edgeFlags, int pointerId) {
}
@Override
public int getViewHorizontalDragRange(@NonNull View child) {
return child.getMeasuredWidth();
}
});
mDragHelper.setEdgeTrackingEnabled(ViewDragHelper.EDGE_LEFT);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
return mDragHelper.shouldInterceptTouchEvent(event);
}
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouchEvent(MotionEvent event) {
mDragHelper.processTouchEvent(event);
return true;
}
@Override
public void computeScroll() {
if (mDragHelper.continueSettling(true)) {
invalidate();
}
}
public void setListener(OnViewGoneListener listener) {
this.listener = listener;
}
public interface OnViewGoneListener{
void onViewGone();
}
}

View File

@@ -28,6 +28,7 @@ import android.text.Spannable;
import android.text.SpannableString;
import android.text.TextUtils;
import android.text.style.StyleSpan;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
@@ -46,6 +47,7 @@ import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.chwl.app.notify.GlobalNotifyManager;
import com.chwl.library.language.LanguageHelper;
import com.example.lib_utils.UiUtils;
import com.google.gson.Gson;
import com.netease.nim.uikit.common.util.log.LogUtil;
import com.netease.nimlib.sdk.NIMSDK;
@@ -236,6 +238,21 @@ public abstract class BaseActivity extends RxAppCompatActivity
}
}
public void initVipCenterBar(String title) {
mTitleBar = findViewById(R.id.title_bar);
if (mTitleBar != null) {
mTitleBar.setTitle(title);
mTitleBar.setImmersive(false);
mTitleBar.setTitleColor(getResources().getColor(R.color.color_FFE3AF));
mTitleBar.setLeftImageResource(R.drawable.vip_center_back_button);
mTitleBar.setBackgroundResource(R.color.transparent);
mTitleBar.setLeftClickListener(v -> onLeftClickListener());
if(UiUtils.INSTANCE.isRtl(context)){
mTitleBar.leftTextViewUpdateScaleXForRTL();
}
}
}
public void initWhiteTitleBar(String title) {
mTitleBar = findViewById(R.id.title_bar);
if (mTitleBar != null) {

View File

@@ -63,6 +63,10 @@ public class TitleBar extends ViewGroup implements View.OnClickListener {
private LayoutInflater mInflater;
public void leftTextViewUpdateScaleXForRTL() {
mLeftText.setScaleX(-1);
}
public TitleBar(Context context) {
super(context);
init(context);

View File

@@ -11,7 +11,15 @@ import com.chwl.app.databinding.ItemMyUserCardWearBinding;
import com.chwl.app.ui.utils.ImageLoadUtils;
import com.chwl.core.decoration.headwear.bean.HeadWearInfo;
import com.chwl.core.decoration.headwear.bean.UserCardWearInfo;
import com.chwl.library.download.DownloadException;
import com.chwl.library.download.DownloadManager;
import com.chwl.library.download.DownloadRequest;
import com.chwl.library.download.DownloadTask;
import com.chwl.library.download.FileDownloadListener;
import com.chwl.library.utils.ResUtil;
import com.chwl.library.utils.PathHelper;
import java.io.File;
/**
* Created by huangmeng1 on 2018/5/11.
@@ -27,7 +35,24 @@ public class MyUserCardWearAdapter extends BaseAdapter<UserCardWearInfo> {
protected void convert(@NonNull BindingViewHolder helper, UserCardWearInfo item) {
super.convert(helper, item);
ItemMyUserCardWearBinding binding = (ItemMyUserCardWearBinding) helper.getBinding();
ImageLoadUtils.loadImage(mContext, item.getPic(), binding.ivUserCardWear);
binding.ivUserCardWearMp4.setLoop(Integer.MAX_VALUE);
String filePath = PathHelper.INSTANCE.generateResourcesFilePath(item.getPic());
DownloadRequest request = DownloadRequest.Companion.build(item.getPic(), filePath, "gift_effect_download", null, 60000L);
DownloadManager.INSTANCE.download(request, new FileDownloadListener() {
@Override
public void onDownloadCompleted(@NonNull DownloadTask task) {
String path = task.getRequest().getPath();
binding.ivUserCardWearMp4.startPlay(new File(path));
}
@Override
public void onDownloadError(@NonNull DownloadException exception) {
ImageLoadUtils.loadImage(mContext, item.getPic(), binding.ivUserCardWear);
}
});
helper.addOnClickListener(R.id.tv_used);
if (item.getLabelType() == HeadWearInfo.LABEL_TYPE_NORMAL) {

View File

@@ -93,18 +93,18 @@ public class MyUserCardWearFragment extends BaseBindingFragment<FrgMyDecorationC
String cardId = headWearInfo.isUsed() ? null : headWearInfo.getCardId();
wearVm.userHeadWear(cardId)
.compose(bindUntilEvent(FragmentEvent.DESTROY))
.doOnError(throwable -> {
toast(throwable.getMessage());
})
.subscribe(s -> {
for (int i = 0; i < shopAdapter.getData().size(); i++) {
shopAdapter.getData().get(i).setUsed(Objects.equals(cardId,shopAdapter.getData().get(i).getCardId()));
}
shopAdapter.notifyDataSetChanged();
//更新用户信息
UserModel.get().updateCurrentUserInfo().subscribe();
});
.compose(bindUntilEvent(FragmentEvent.DESTROY))
.doOnError(throwable -> {
toast(throwable.getMessage());
})
.subscribe(s -> {
for (int i = 0; i < shopAdapter.getData().size(); i++) {
shopAdapter.getData().get(i).setUsed(Objects.equals(cardId,shopAdapter.getData().get(i).getCardId()));
}
shopAdapter.notifyDataSetChanged();
//更新用户信息
UserModel.get().updateCurrentUserInfo().subscribe();
});
}
}

View File

@@ -129,9 +129,9 @@ class ConvertDiamondActivity : BaseViewBindingActivity<ActivityConvertDiamondBin
}
binding.tvConvert.setOnClickListener { view ->
if (binding.edDiamond.text.toString().toLong() < it.minDiamonds) {
if (binding.edGold.text.toString().toLong() < it.minDiamonds) {
toast(getString(R.string.convert_diamonds_01).format(it.minDiamonds))
} else if (binding.edDiamond.text.toString().toLong() > it.maxDiamonds) {
} else if (binding.edGold.text.toString().toLong() > it.maxDiamonds) {
toast(getString(R.string.convert_diamonds_02).format(it.minDiamonds))
} else {
//去掉小数凑整:不管小数是多少,都进一

View File

@@ -13,8 +13,8 @@ class HomeMessageViewModel : BaseViewModel() {
safeLaunch(needLoading = false, onError = {
topPublicChatMessageLiveData.postValue(BeanResult.failed(it))
}) {
val value = PublicChatModel.getTopMessage()
topPublicChatMessageLiveData.postValue(BeanResult.success(value ?: emptyList()))
// val value = PublicChatModel.getTopMessage()
// topPublicChatMessageLiveData.postValue(BeanResult.success(value ?: emptyList()))
}
}

View File

@@ -21,8 +21,8 @@ public class HomeIndicatorAdapter extends CommonNavigatorAdapter {
private final Context mContext;
private final List<? extends CharSequence> mTitleList;
private int textSize = 21;
private float minScale = 0.857f;
private int textSize = 20;
private float minScale = 0.8f;
private boolean showIndicator = true;
private OnItemSelectListener mOnItemSelectListener;
@@ -39,8 +39,8 @@ public class HomeIndicatorAdapter extends CommonNavigatorAdapter {
@Override
public IPagerTitleView getTitleView(Context context, final int i) {
ScaleTransitionPagerTitleView scaleTransitionPagerTitleView = new ScaleTransitionPagerTitleView(context, true);
scaleTransitionPagerTitleView.setNormalColor(ContextCompat.getColor(context, R.color.color_990C1D18));
scaleTransitionPagerTitleView.setSelectedColor(ContextCompat.getColor(context, R.color.color_0C1D18));
scaleTransitionPagerTitleView.setNormalColor(ContextCompat.getColor(context, R.color.color_313131));
scaleTransitionPagerTitleView.setSelectedColor(ContextCompat.getColor(context, R.color.color_313131));
scaleTransitionPagerTitleView.setMinScale(minScale);
scaleTransitionPagerTitleView.setTextSize(textSize);
int padding = UIUtil.dip2px(context, 13);
@@ -62,7 +62,7 @@ public class HomeIndicatorAdapter extends CommonNavigatorAdapter {
indicator.setLineHeight(context.getResources().getDimensionPixelOffset(R.dimen.dp_4));
indicator.setRoundRadius(context.getResources().getDimensionPixelOffset(R.dimen.dp_2));
indicator.setLineWidth(context.getResources().getDimensionPixelOffset(R.dimen.dp_13));
indicator.setColors(context.getResources().getColor(R.color.color_002512));
indicator.setColors(context.getResources().getColor(R.color.color_e29030));
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
// lp.bottomMargin = mBottomMargin;
indicator.setLayoutParams(lp);

View File

@@ -1,58 +0,0 @@
package com.chwl.app.home.adapter
import android.text.style.ImageSpan
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.chad.library.adapter.base.BaseViewHolder
import com.chwl.app.R
import com.chwl.app.ui.utils.loadAvatar
import com.chwl.core.public_chat_hall.bean.PublicChatMessageBean
import com.netease.nim.uikit.api.NimUIKit
import com.netease.nim.uikit.business.session.emoji.MoonUtil
class PublicChatLaneAdapter(private val data: MutableList<PublicChatMessageBean>) :
RecyclerView.Adapter<BaseViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder {
return BaseViewHolder(
LayoutInflater.from(parent.context).inflate(R.layout.public_chat_lane_item, null)
)
}
override fun onBindViewHolder(holder: BaseViewHolder, position: Int) {
val item = getItem(position)
val textView = holder.getView<TextView>(R.id.tv_message)
MoonUtil.identifyFaceExpressionSmall(
NimUIKit.getContext(),
textView,
item?.content ?: "",
ImageSpan.ALIGN_CENTER
)
val avatarView = holder.getView<ImageView>(R.id.iv_avatar)
avatarView.loadAvatar(item?.fromAvatar ?: "")
}
override fun getItemCount(): Int {
return Int.MAX_VALUE
}
fun getRealItemCount(): Int {
return data.size
}
fun setNewData(list: List<PublicChatMessageBean>) {
data.clear()
data.addAll(list)
notifyDataSetChanged()
}
private fun getItem(position: Int): PublicChatMessageBean? {
if (data.isEmpty()) {
return null
}
return data[position % data.size]
}
}

View File

@@ -19,7 +19,6 @@ import com.chwl.app.avroom.adapter.CommonVPAdapter
import com.chwl.app.base.BaseViewBindingFragment
import com.chwl.app.databinding.FragmentContactListBinding
import com.chwl.app.home.HomeMessageViewModel
import com.chwl.app.home.adapter.PublicChatLaneAdapter
import com.chwl.app.home.helper.AutoScrollTask
import com.chwl.app.public_chat.ui.message.PublicChatRoomMessageActivity
import com.chwl.app.support.FragmentVisibleStateHelper
@@ -42,7 +41,6 @@ class ContactsListFragment : BaseViewBindingFragment<FragmentContactListBinding>
MainTabContentView {
private val viewModel: HomeMessageViewModel by activityViewModels()
private val publicChatAdapter = PublicChatLaneAdapter(ArrayList())
private val stateHelper = FragmentVisibleStateHelper(this).start {
onVisibleChanged(it)
@@ -64,7 +62,6 @@ class ContactsListFragment : BaseViewBindingFragment<FragmentContactListBinding>
} else {
2
}
binding.recyclerViewPublicChat.scrollBy(x, 0)
}
override fun init() {
@@ -86,6 +83,8 @@ class ContactsListFragment : BaseViewBindingFragment<FragmentContactListBinding>
tagList.add(getString(R.string.layout_fragment_contact_list_04))
val commonNavigator = CommonNavigator(context)
commonNavigator.setTitleWrapContent(false)
commonNavigator.rightPadding = 20
commonNavigator.leftPadding = 20
val magicIndicatorAdapter = ContactsIndicatorAdapter(context, tagList)
magicIndicatorAdapter.setOnItemSelectListener { position: Int, view: TextView? ->
binding.viewPager.currentItem = position
@@ -159,37 +158,20 @@ class ContactsListFragment : BaseViewBindingFragment<FragmentContactListBinding>
return true
}
})
binding.layoutPublicChat.singleClick {
PublicChatRoomMessageActivity.start(requireContext())
}
binding.recyclerViewPublicChat.setOnTouchListener { v, event ->
gestureDetectorCompat.onTouchEvent(event)
}
binding.recyclerViewPublicChat.layoutManager =
StaggeredGridLayoutManager(2, RecyclerView.HORIZONTAL)
binding.recyclerViewPublicChat.adapter = publicChatAdapter
viewModel.topPublicChatMessageLiveData.observe(this) {
val newList = it.data
if (it.isSuccess && !newList.isNullOrEmpty()) {
publicChatAdapter.setNewData(newList)
switchPublicChatMessageScrollState(stateHelper.isVisible)
}
binding.recyclerViewPublicChat.isVisible = (publicChatAdapter.getRealItemCount() > 0)
}
}
private fun switchPublicChatMessageScrollState(isVisible: Boolean) {
if (isVisible && publicChatAdapter.getRealItemCount() > 0) {
autoScrollTask.start()
} else {
autoScrollTask.stop()
}
// if (isVisible && publicChatAdapter.getRealItemCount() > 0) {
// autoScrollTask.start()
// } else {
// autoScrollTask.stop()
// }
}
private fun onVisibleChanged(isVisible: Boolean) {
switchPublicChatMessageScrollState(isVisible)
if (isVisible) {
viewModel.getTopPublicChatMessageIfNull()
}
// switchPublicChatMessageScrollState(isVisible)
// if (isVisible) {
// viewModel.getTopPublicChatMessageIfNull()
// }
}
}

View File

@@ -56,7 +56,7 @@ class HomeFragment : BaseViewBindingFragment<FragmentHomeBinding>(), View.OnClic
titleList.add(getString(R.string.main_tab_recommend))
titleList.add(getString(R.string.main_me))
val commonNavigator = CommonNavigator(context)
commonNavigator.setTitleWrapContent(false)
commonNavigator.setTitleWrapContent(true)
val magicIndicatorAdapter = HomeIndicatorAdapter(context, titleList)
magicIndicatorAdapter.setOnItemSelectListener { position: Int, view: TextView? ->
binding.viewPager.currentItem = position

View File

@@ -35,7 +35,7 @@ import com.chwl.app.ui.utils.ImageLoadUtils
import com.chwl.app.ui.wallet.WalletActivity
import com.chwl.app.ui.webview.CommonWebViewActivity
import com.chwl.app.view.GenderAgeTextView
import com.chwl.app.vip.VipMainActivity
import com.chwl.app.vip.VipCenterActivity
import com.chwl.app.vip.VipViewModel
import com.chwl.core.auth.AuthModel
import com.chwl.core.initial.InitialModel
@@ -353,7 +353,7 @@ class MeFragment : BaseFragment(), View.OnClickListener {
}
R.id.iv_vip -> {
VipMainActivity.start(mContext)
VipCenterActivity.start(mContext)
//进入贵族中心埋点
val goldWalletInfo = PayModel.get().currentWalletInfo
val map = HashMap<String, Any>(5)

View File

@@ -9,6 +9,7 @@ import com.chwl.app.earn.activity.EarnRecordActivity;
import com.chwl.app.pay.activity.GiveGoldActivity;
import com.chwl.app.ui.feedback.FeedbackActivity;
import com.chwl.app.ui.game_team.record.GameTeamRecordActivity;
import com.chwl.app.vip.VipCenterActivity;
import com.chwl.core.module_hall.hall.bean.H5FamilyInfo;
import com.chwl.core.module_hall.hall.bean.UserClanInfo;
import com.trello.rxlifecycle3.components.support.RxAppCompatActivity;
@@ -38,7 +39,6 @@ import com.chwl.app.ui.pay.ChargeActivity;
import com.chwl.app.ui.setting.ModifyPwdActivity;
import com.chwl.app.ui.user.activity.UserInfoActivity;
import com.chwl.app.ui.webview.CommonWebViewActivity;
import com.chwl.app.vip.VipMainActivity;
import com.chwl.core.DemoCache;
import com.chwl.core.auth.AuthModel;
import com.chwl.core.community.event.SquareTaskEvent;
@@ -216,7 +216,7 @@ public class RouterHandler {
ModifyPwdActivity.start(context, ModifyPwdActivity.LOGIN_PWD);
break;
case RouterType.VIP_MAIN:
VipMainActivity.start(context);
VipCenterActivity.start(context);
break;
case RouterType.CP_INVITE:
CpInviteRecordActivity.Companion.start(context, false);

View File

@@ -79,9 +79,9 @@ public abstract class RecentViewHolder extends RecyclerViewHolder<BaseQuickAdapt
protected void updateBackground(NIMBaseViewHolder holder, RecentContact recent, int position) {
if ((recent.getTag() & RecentContactsFragment.RECENT_TAG_STICKY) == 0) {
holder.getConvertView().setBackgroundResource(R.color.transparent);
// holder.getConvertView().setBackgroundResource(R.drawable.shape_white_10dp_round);
} else {
holder.getConvertView().setBackgroundResource(R.color.transparent);
holder.getConvertView().setBackgroundResource(R.drawable.shape_white_10dp_round);
}
}

View File

@@ -1,6 +1,7 @@
package com.chwl.app.ui.user.adapter;
import android.content.Context;
import android.graphics.Typeface;
import android.view.Gravity;
import android.view.ViewGroup;
import android.widget.FrameLayout;
@@ -14,14 +15,16 @@ import com.chwl.app.ui.widget.magicindicator.buildins.UIUtil;
import com.chwl.app.ui.widget.magicindicator.buildins.commonnavigator.abs.CommonNavigatorAdapter;
import com.chwl.app.ui.widget.magicindicator.buildins.commonnavigator.abs.IPagerIndicator;
import com.chwl.app.ui.widget.magicindicator.buildins.commonnavigator.abs.IPagerTitleView;
import com.chwl.library.language.LanguageHelper;
import com.tencent.qgame.animplayer.mix.Resource;
import java.util.List;
public class ContactsIndicatorAdapter extends CommonNavigatorAdapter {
private final List<? extends CharSequence> mTitleList;
private int textSize = 16;
private float minScale = 1f;
private int textSize = 20;
private float minScale = 0.8f;
private boolean showIndicator = true;
private OnItemSelectListener mOnItemSelectListener;
@@ -37,10 +40,14 @@ public class ContactsIndicatorAdapter extends CommonNavigatorAdapter {
@Override
public IPagerTitleView getTitleView(Context context, final int i) {
ScaleTransitionPagerTitleView scaleTransitionPagerTitleView = new ScaleTransitionPagerTitleView(context, true);
scaleTransitionPagerTitleView.setNormalColor(ContextCompat.getColor(context, R.color.color_84868A));
scaleTransitionPagerTitleView.setSelectedColor(ContextCompat.getColor(context, R.color.color_1E1E1F));
scaleTransitionPagerTitleView.setNormalColor(ContextCompat.getColor(context, R.color.color_313131));
scaleTransitionPagerTitleView.setSelectedColor(ContextCompat.getColor(context, R.color.color_313131));
scaleTransitionPagerTitleView.setMinScale(minScale);
scaleTransitionPagerTitleView.setTextSize(textSize);
if (LanguageHelper.INSTANCE.getCurrentLanguageType().equals("EN")) {
scaleTransitionPagerTitleView.setTextSize(textSize);
} else {
scaleTransitionPagerTitleView.setTextSize(textSize-2);
}
int padding = UIUtil.dip2px(context, 16);
scaleTransitionPagerTitleView.setPadding(padding, 0, padding, 0);
scaleTransitionPagerTitleView.setText(mTitleList.get(i));

View File

@@ -6,11 +6,58 @@ import com.chad.library.adapter.base.BaseViewHolder
import com.chwl.app.R
import com.chwl.app.ui.utils.load
import com.chwl.core.user.bean.MedalBean
import com.chwl.library.download.DownloadManager
import com.chwl.library.download.DownloadRequest
import com.chwl.library.download.DownloadTask
import com.chwl.library.download.FileDownloadListener
import com.chwl.library.utils.PathHelper
import com.tencent.qgame.animplayer.AnimConfig
import com.tencent.qgame.animplayer.AnimView
import com.tencent.qgame.animplayer.inter.IAnimListener
import com.tencent.qgame.animplayer.util.ScaleType
import java.io.File
class UserInfoMedalAdapter :
BaseQuickAdapter<MedalBean, BaseViewHolder>(R.layout.user_info_item_medal) {
override fun convert(helper: BaseViewHolder, item: MedalBean) {
val imageView = helper.getView<ImageView>(R.id.iv_image)
imageView.load(item.picUrl)
item.picUrl?.let {
if (it.replace("\n", "").lowercase().endsWith("mp4")) {
val mp4View = helper.getView<AnimView>(R.id.iv_mp4)
mp4View.setScaleType(ScaleType.FIT_XY)
mp4View.setLoop(Int.MAX_VALUE)
mp4View.setAnimListener(object : IAnimListener {
override fun onFailed(errorType: Int, errorMsg: String?) {
}
override fun onVideoComplete() {
}
override fun onVideoDestroy() {
}
override fun onVideoRender(frameIndex: Int, config: AnimConfig?) {
}
override fun onVideoStart() {
}
})
val filePath = PathHelper.generateResourcesFilePath(it)
val request = DownloadRequest.build(it, filePath, "", null, 600000L)
DownloadManager.download(request, object : FileDownloadListener() {
override fun onDownloadCompleted(task: DownloadTask) {
val path = task.getRequest().getPath()
mp4View.startPlay(File(path))
}
})
} else {
val imageView = helper.getView<ImageView>(R.id.iv_image)
imageView.load(item.picUrl)
}
}
}
}

View File

@@ -0,0 +1,62 @@
package com.chwl.app.ui.utils
import com.opensource.svgaplayer.utils.Pools
import java.lang.ref.SoftReference
import java.util.LinkedList
class SoftPool <T:Any> (private var max:Int) : Pools.Pool<T> {
init {
if (max <= 0){
max = 8
}
}
private var mPool = LinkedList<SoftReference<T>>()
fun acquire(getItemEmpty:()->T):T{
return acquire()?:getItemEmpty()
}
override fun acquire(): T? {
if (mPool.size == 0){
return null
}
while (true){
val item = mPool.poll()?:return null
if (item.get() != null) {
return item.get()
}
}
}
override fun release(instance: T): Boolean {
if (mPool.size > max) {
if (getRealSize() > max) {
return false
}
}
mPool.addFirst(SoftReference(instance))
return true
}
private fun getRealSize() : Int{
val iterator = mPool.listIterator()
while (iterator.hasNext()) {
val item = iterator.next().get()
if (item == null) iterator.remove()
}
return mPool.size
}
fun clear(){
mPool.clear()
}
}

View File

@@ -0,0 +1,180 @@
package com.chwl.app.ui.widget
import android.animation.ObjectAnimator
import android.annotation.SuppressLint
import android.content.Context
import android.os.Build
import android.os.VibrationEffect
import android.os.Vibrator
import android.os.VibratorManager
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.widget.FrameLayout
import androidx.core.view.isGone
import com.chwl.app.databinding.ViewBonsellaJoinAttackButtonBinding
import com.chwl.core.utils.ComboUtil
class BonsellaJoinAttackButtonView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null
) : FrameLayout(context, attrs) {
var onGiftComboEndListener: OnGiftComboEndListener? = null
private var comboNum = 0
private var comboCount = 0
private val objectAnimator: ObjectAnimator by lazy {
ObjectAnimator.ofFloat(mBinding.pvBg, "percent", 100F, 0F).apply {
duration = DOWN_COUNT_TIME
}
}
private val mBinding = ViewBonsellaJoinAttackButtonBinding.inflate(LayoutInflater.from(context), this)
private val vibrator by lazy {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
(context.getSystemService(Context.VIBRATOR_MANAGER_SERVICE) as VibratorManager).defaultVibrator
} else {
context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
}
}
init {
mBinding.ivBtn.isLongClickable = false
mBinding.pvBg.setProgressChangeListener{
if(it == 0f){
isGone = true
comboNum = 0
comboCount = 0
ComboUtil.comboCount = comboCount+1
mBinding.tvNum.text = ""
onGiftComboEndListener?.onGiftComboEnd()
}
}
}
fun onBtnDown(){
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
vibrator.vibrate(VibrationEffect.createOneShot(100L, VibrationEffect.DEFAULT_AMPLITUDE))
}else{
vibrator.vibrate(100)
}
} catch (_: Exception) { }
// mBinding.ivBtn.animate().cancel()
// mBinding.ivBtn.animate()
// .scaleX(0.875f)
// .scaleY(0.875f)
// .setDuration(50)
// .withEndAction {
// onBtnUp()
// }
// .start()
// mBinding.pvBg.animate().cancel()
// mBinding.pvBg.animate()
// .scaleX(0.875f)
// .scaleY(0.875f)
// .setDuration(50)
// .start()
// mBinding.ivBg.animate().cancel()
// mBinding.ivBg.alpha = 0f
// mBinding.ivBg.scaleX = 1f
// mBinding.ivBg.scaleY = 1f
mBinding.svga.stopAnimation()
mBinding.svga.startAnimation()
}
private fun onBtnUp(){
mBinding.ivBtn.animate()
.scaleX(1f)
.scaleY(1f)
.setDuration(50)
.withEndAction { }
.start()
mBinding.pvBg.animate()
.scaleX(1f)
.scaleY(1f)
.setDuration(50)
.start()
mBinding.ivBg.alpha = 1f
mBinding.ivBg.animate()
.alpha(0f)
.scaleX(1.3f)
.scaleY(1.3f)
.start()
}
fun getComboNum():Int{
return comboNum
}
fun isInCombo():Boolean{
return comboNum > 0
}
fun cancel() {
objectAnimator.cancel()
mBinding.pvBg.percent = 0f
}
fun start() {
objectAnimator.start()
}
fun waitStart() {
mBinding.pvBg.percent = 100f
objectAnimator.pause()
}
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
cancel()
mBinding.svga.clear()
objectAnimator.removeAllListeners()
objectAnimator.removeAllUpdateListeners()
}
/**
* 用于更新按钮上的文字
*/
@SuppressLint("SetTextI18n")
fun updateNumber(num: Int) {
comboNum += num
comboCount++
mBinding.tvNum.text = "x$comboCount"
mBinding.tvNum.scaleX = 1.3f
mBinding.tvNum.scaleY = 1.3f
mBinding.tvNum.animate()
.setDuration(100)
.scaleX(1f)
.scaleY(1f)
.start()
ComboUtil.comboCount = comboCount+1
}
fun interface OnGiftComboEndListener {
fun onGiftComboEnd()
}
companion object {
/**
* 倒计时时间,毫秒为单位
*/
const val DOWN_COUNT_TIME = 5 * 1000L
}
fun showView(isVis : Boolean){
if (isVis) {
if (visibility != View.VISIBLE) visibility = View.VISIBLE
}else{
if (visibility == View.VISIBLE) visibility = View.INVISIBLE
}
}
}

View File

@@ -0,0 +1,349 @@
package com.chwl.app.ui.widget
import android.animation.ObjectAnimator
import android.animation.PropertyValuesHolder
import android.annotation.SuppressLint
import android.content.Context
import android.os.Handler
import android.os.Looper
import android.os.Message
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.view.animation.Animation
import android.view.animation.AnimationUtils
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import androidx.appcompat.widget.AppCompatTextView
import androidx.core.view.isGone
import androidx.core.view.isVisible
import com.chwl.app.R
import com.chwl.app.ui.utils.ImageLoadUtils
import com.chwl.app.ui.utils.SoftPool
import com.chwl.core.gift.bean.BonsellaJoinAttack
import com.chwl.core.gift.bean.GiftMultiReceiverInfo
import com.chwl.core.utils.LogUtils
import com.chwl.library.utils.ResUtil
import com.example.lib_utils.UiUtils
import java.util.LinkedList
class BonsellaJoinAttackLayout @JvmOverloads constructor(
context: Context?,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0,
defStyleRes: Int = 0
) : LinearLayout(context, attrs, defStyleAttr, defStyleRes){
private val showingList = LinkedList<BonsellaJoinAttack>()
private val waitingList = LinkedList<BonsellaJoinAttack>()
private val comboMap = linkedMapOf<BonsellaJoinAttack, View>()
private val cacheView = SoftPool<View>(2)
private val inflater = LayoutInflater.from(context)
private val handle = Handler(Looper.getMainLooper()) {
if (it.what == 1) {
viewOut(it.obj as? BonsellaJoinAttack, false)
}
true
}
init {
if(isInEditMode){
inflater.inflate(R.layout.item_bonsella_join_attack_view, this, true)
inflater.inflate(R.layout.item_bonsella_join_attack_view, this, true)
}
orientation = VERTICAL
}
/**
* 创建
*/
private fun getComboChildView(): View {
val view = cacheView.acquire {
inflater.inflate(R.layout.item_bonsella_join_attack_view, this, false)
}.apply {
createViewHolder(this)
isVisible = true
}
return view
}
/**
* add data
*/
fun add(bonsellaJoinAttack: BonsellaJoinAttack?) {
//没有绑定之前不能添加
if (!isAttachedToWindow) {
return
}
if (bonsellaJoinAttack == null) {
return
}
var addToWaiting = true
for (comboInfo in showingList) {
if(comboInfo.sentUserid == bonsellaJoinAttack.sentUserid && comboInfo.giftId == bonsellaJoinAttack.giftId){
comboInfo.giftNumber = bonsellaJoinAttack.giftNumber
comboInfo.comboCount = bonsellaJoinAttack.comboCount
comboInfo.receiverNumber = bonsellaJoinAttack.receiverNumber
updateNum(comboInfo)
addToWaiting = false
}
}
for (comboInfo in waitingList) {
if(comboInfo.sentUserid == bonsellaJoinAttack.sentUserid && comboInfo.giftId == bonsellaJoinAttack.giftId){
comboInfo.giftNumber = bonsellaJoinAttack.giftNumber
comboInfo.comboCount = bonsellaJoinAttack.comboCount
comboInfo.receiverNumber = bonsellaJoinAttack.receiverNumber
addToWaiting = false
}
}
if(addToWaiting){
waitingList.add(bonsellaJoinAttack)
}
showNext()
}
/**
* 更新数量
*/
private fun updateNum(bonsellaJoinAttack: BonsellaJoinAttack) {
val view = comboMap[bonsellaJoinAttack] ?: return
val viewHolder = getViewHolder(view)
viewHolder?.refreshNum(bonsellaJoinAttack, true)
handle.removeMessages(1, bonsellaJoinAttack)
handle.sendMessageDelayed(Message.obtain(handle, 1, bonsellaJoinAttack), COMBO_STAY_TIME * 1000L)
}
/**
* 显示下一个
*/
private fun showNext() {
if(waitingList.isEmpty()){
return
}
val comboChildView = getComboChildView()
addView(comboChildView,0)
val giftComboInfo = waitingList.remove()
showingList.add(giftComboInfo)
comboMap[giftComboInfo] = comboChildView
val viewHolder = getViewHolder(comboChildView)
viewHolder?.showUi(giftComboInfo)
viewAnimationIn(comboChildView)
handle.sendMessageDelayed(Message.obtain(handle, 1, giftComboInfo), COMBO_STAY_TIME * 1000L)
if(showingList.size > MAX_SHOWING){
handle.removeMessages(1, showingList[0])
viewOut(showingList.remove(), true)
return
}
}
/**
* 移除动画
*/
private fun viewOut(bonsellaJoinAttack: BonsellaJoinAttack?, isDirectRemove: Boolean) {
bonsellaJoinAttack ?: return
val comboView = comboMap.remove(bonsellaJoinAttack) ?: return
val runnable = {
val viewHolder = getViewHolder(comboView)
viewHolder?.clear()
if(!isDirectRemove){
showingList.remove(bonsellaJoinAttack)
}
removeView(comboView)
cacheView.release(comboView)
showNext()
}
if(isDirectRemove){
comboView.isGone = true
post(runnable)
}else{
val animOut = AnimationUtils.loadAnimation(context, R.anim.alpha_out)
animOut.setAnimationListener(object : Animation.AnimationListener {
override fun onAnimationStart(animation: Animation?) {
}
override fun onAnimationEnd(animation: Animation?) {
post(runnable)
}
override fun onAnimationRepeat(animation: Animation?) {
}
})
comboView.startAnimation(animOut)
}
}
/**
* 飞入动画
*/
private fun viewAnimationIn(view: View) {
view.alpha = 1f
val animIn = AnimationUtils.loadAnimation(context,if (UiUtils.isRtl(context)) R.anim.left_to_right else R.anim.right_to_left )
// animIn.fillAfter = true
// animIn.isFillEnabled = true
view.startAnimation(animIn)
}
override fun onAttachedToWindow() {
super.onAttachedToWindow()
if(isInEditMode) return
// RoomMsgManager.addCustomMsgListener(this)
}
fun onRoomCustomMsg(giftInfo: GiftMultiReceiverInfo?) {
LogUtils.d(" GiftComboLayout onRoomCustomMsg " )
if (giftInfo==null) return
if (giftInfo.comboCount == 0) return
val comboInfo = BonsellaJoinAttack().apply {
giftId = giftInfo.giftId
sentUserid = giftInfo.uid
sentUserName = giftInfo.nick
sentAvatar = giftInfo.avatar
receiverUserName = giftInfo.targetUsers?.getOrNull(0)?.nick?:""
receiverNumber = giftInfo.targetUsers?.size?: giftInfo.targetUids?.size?: 1
giftNumber = giftInfo.giftNum
giftImgUrl = giftInfo.gift?.giftUrl?:""
comboCount = giftInfo.comboCount
isMulti = giftInfo.isMulti
}
add(comboInfo)
}
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
handle.removeCallbacksAndMessages(null)
// RoomMsgManager.removeCustomMsgListener(this)
}
private fun createViewHolder(view: View) {
getViewHolder(view) ?: ViewHolder(view)
}
private fun getViewHolder(view: View): ViewHolder? {
return view.tag as? ViewHolder
}
private inner class ViewHolder(view: View) {
var tvNumber: AppCompatTextView = view.findViewById(R.id.giftComboNumber)
var ivGift: ImageView = view.findViewById(R.id.giftImg)
var tvNick: TextView = view.findViewById(R.id.sentUserName)
var tvReceiverNick: TextView = view.findViewById(R.id.receiverUserName)
var ivAvatar: ImageView = view.findViewById(R.id.sentUserAvatar)
var ivLayoutBg: ImageView = view.findViewById(R.id.layoutBg)
init {
view.tag = this
}
@SuppressLint("SetTextI18n")
fun showUi(bonsellaJoinAttack: BonsellaJoinAttack) {
if (UiUtils.isRtl(context)){
ivLayoutBg.scaleX = -1f
}
refreshNum(bonsellaJoinAttack)
tvNick.text = bonsellaJoinAttack.sentUserName
if (bonsellaJoinAttack.receiverNumber == 1) {
tvReceiverNick.text = bonsellaJoinAttack.receiverUserName
} else {
if (bonsellaJoinAttack.isMulti) {
tvReceiverNick.text = ResUtil.getString(R.string.Multiplayer)
} else {
tvReceiverNick.text = ResUtil.getString(R.string.All_mic)
}
}
// tvNumber.text = "x${giftComboInfo.giftNumber * giftComboInfo.receiverNumber * giftComboInfo.comboCount}"
ImageLoadUtils.loadImage(ivGift, bonsellaJoinAttack.giftImgUrl)
ImageLoadUtils.loadImage(ivAvatar, bonsellaJoinAttack.sentAvatar)
ivAvatar.tag = bonsellaJoinAttack
}
/**
* 用于刷新数量
*/
@SuppressLint("SetTextI18n")
fun refreshNum(bonsellaJoinAttack: BonsellaJoinAttack, isAnim: Boolean = false) {
val num = bonsellaJoinAttack.giftNumber * bonsellaJoinAttack.receiverNumber * bonsellaJoinAttack.comboCount
if(num == 0){
tvNumber.isVisible = false
return
}
// val old = tvNumber.tag as? Int
// //兼容上一个比下一个数还要大
// if (old != null && old > num) {
// return
// }
tvNumber.isVisible = true
tvNumber.tag = num
tvNumber.text = "x$num"
if (isAnim) {
tvNumber.animate().cancel()
tvNumber.requestLayout()
post {
val scaleUp: ObjectAnimator = ObjectAnimator.ofPropertyValuesHolder(
tvNumber,
PropertyValuesHolder.ofFloat(SCALE_X, 1f, 1.3f, 1f),
PropertyValuesHolder.ofFloat(SCALE_Y, 1f, 1.3f, 1f)
)
scaleUp.setDuration(100)
scaleUp.start()
}
}
}
/**
* 清空UI数据
*/
fun clear() {
LogUtils.d(" ComboView clear -- clear ")
tvNumber.animate().cancel()
tvNumber.scaleX = 1f
tvNumber.scaleY = 1f
tvNumber.tag = 0
ivAvatar.tag = null
}
}
companion object {
/**
* 最大显示个数
*/
const val MAX_SHOWING = 2
/**
* 连击停留时间
*/
const val COMBO_STAY_TIME = 5
}
// override fun onClick(v: View) {
// val giftComboInfo = v.tag as? GiftComboInfo ?: return
// val sendUid = giftComboInfo.senderUid
// if (sendUid == 0L) {
// return
// }
// RoomUserInfoDialog.show(sendUid)
// }
}

View File

@@ -0,0 +1,295 @@
package com.chwl.app.ui.widget
import android.content.Context
import android.graphics.Canvas
import android.graphics.LinearGradient
import android.graphics.Paint
import android.graphics.RectF
import android.graphics.Shader
import android.util.AttributeSet
import android.view.View
import androidx.annotation.Keep
import com.chwl.app.R
import com.chwl.library.utils.SizeUtils
class ColorfulRingProgressView(context: Context, attrs: AttributeSet?) : View(context, attrs) {
private var mPercent = 0f
private var mStrokeWidth = 0f
private var mStartAngle = 0f
private var mFgColorStart = 0xffb900
private var mFgColorEnd = 0xffb900
private var widthDiff = 3
private var mBgColor = -0xa0a0b
private var mShader: LinearGradient? = null
private var mOval = RectF()
private val progressPaint = Paint()
private var mNegative = false //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><E3B5B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>100-0<><30>
private val circlePaint = Paint()
private var progressChangeListener: OnProgressChangeListener? = null
init {
val a = context.theme.obtainStyledAttributes(attrs, R.styleable.ColorfulRingProgressView, 0, 0)
try {
mFgColorEnd = a.getColor(R.styleable.ColorfulRingProgressView_fgColorEnd, 0xffb900)
mFgColorStart = a.getColor(R.styleable.ColorfulRingProgressView_fgColorStart, 0xffb900)
mPercent = a.getFloat(R.styleable.ColorfulRingProgressView_currentPercent, 75f)
mStartAngle = a.getFloat(R.styleable.ColorfulRingProgressView_ringProgress_startAngle, 0f) + 270
mStrokeWidth = a.getDimensionPixelSize(R.styleable.ColorfulRingProgressView_circleStrokeWidth, 21).toFloat()
widthDiff = a.getDimensionPixelSize(R.styleable.ColorfulRingProgressView_circle_width_diff, 3)
mBgColor = a.getColor(R.styleable.ColorfulRingProgressView_circle_bg_color, -0xa0a0b)
mNegative = a.getBoolean(R.styleable.ColorfulRingProgressView_crp_negative, false)
} finally {
a.recycle()
}
progressPaint.isAntiAlias = true
progressPaint.style = Paint.Style.STROKE
progressPaint.strokeWidth = mStrokeWidth
progressPaint.strokeCap = Paint.Cap.ROUND
circlePaint.style = Paint.Style.STROKE
circlePaint.isAntiAlias = true
circlePaint.color = mBgColor
circlePaint.strokeWidth = mStrokeWidth + widthDiff
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
canvas.drawCircle(
(mOval.right + mOval.left) / 2,
(mOval.bottom + mOval.top) / 2,
(mOval.bottom - mOval.top) / 2,
circlePaint
)
progressPaint.setShader(mShader)
if (mNegative) {
canvas.drawArc(mOval, mStartAngle + (100 - mPercent) * 3.6f, 360 - (100 - mPercent) * 3.6f, false, progressPaint)
} else {
canvas.drawArc(mOval, mStartAngle, mPercent * 3.6f, false, progressPaint)
}
}
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
super.onSizeChanged(w, h, oldw, oldh)
updateOval()
mShader = LinearGradient(
mOval.left, mOval.top,
mOval.left, mOval.bottom, mFgColorStart, mFgColorEnd, Shader.TileMode.MIRROR
)
}
@set:Keep
var percent: Float
get() = mPercent
set(mPercent) {
this.mPercent = mPercent
postInvalidate()
if (progressChangeListener != null) {
progressChangeListener?.onProgressChange(mPercent)
}
}
fun setProgressChangeListener(progressChangeListener: OnProgressChangeListener?) {
this.progressChangeListener = progressChangeListener
}
var strokeWidth: Float
get() = mStrokeWidth
set(mStrokeWidth) {
this.mStrokeWidth = mStrokeWidth
progressPaint.strokeWidth = mStrokeWidth
updateOval()
refreshTheLayout()
}
private fun updateOval() {
val xp = paddingLeft + paddingRight
val yp = paddingBottom + paddingTop
mOval = RectF(
paddingLeft + mStrokeWidth, paddingTop + mStrokeWidth,
paddingLeft + (width - xp) - mStrokeWidth,
paddingTop + (height - yp) - mStrokeWidth
)
}
fun setStrokeWidthDp(dp: Float) {
this.mStrokeWidth = SizeUtils.dp2px(context,dp).toFloat()
progressPaint.strokeWidth = mStrokeWidth
updateOval()
refreshTheLayout()
}
private fun refreshTheLayout() {
invalidate()
requestLayout()
}
var fgColorStart: Int
get() = mFgColorStart
set(mFgColorStart) {
this.mFgColorStart = mFgColorStart
mShader = LinearGradient(
mOval.left, mOval.top,
mOval.left, mOval.bottom, mFgColorStart, mFgColorEnd, Shader.TileMode.MIRROR
)
refreshTheLayout()
}
var fgColorEnd: Int
get() = mFgColorEnd
set(mFgColorEnd) {
this.mFgColorEnd = mFgColorEnd
mShader = LinearGradient(
mOval.left, mOval.top,
mOval.left, mOval.bottom, mFgColorStart, mFgColorEnd, Shader.TileMode.MIRROR
)
refreshTheLayout()
}
var startAngle: Float
get() = mStartAngle
set(mStartAngle) {
this.mStartAngle = mStartAngle + 270
refreshTheLayout()
}
fun interface OnProgressChangeListener {
fun onProgressChange(mPercent: Float)
}
}

View File

@@ -43,6 +43,7 @@ import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.BaseViewHolder;
import com.chwl.app.ui.adapter.StarWeekAdapter;
import com.chwl.app.ui.webview.DialogWebViewActivity;
import com.chwl.app.vip.VipCenterActivity;
import com.chwl.core.UriProvider;
import com.chwl.core.gift.bean.LuckyBagNoticeInfo;
import com.chwl.core.gift.bean.SimpleUserInfo;
@@ -74,7 +75,6 @@ import com.chwl.app.ui.widget.magicindicator.buildins.UIUtil;
import com.chwl.app.ui.widget.recyclerview.decoration.VerticalDecoration;
import com.chwl.app.utils.RegexUtil;
import com.chwl.app.utils.SpannableBuilder;
import com.chwl.app.vip.VipMainActivity;
import com.chwl.core.auth.AuthModel;
import com.chwl.core.bean.RoomQueueInfo;
import com.chwl.core.gift.GiftModel;
@@ -602,8 +602,10 @@ public class GiftDialog extends BottomSheetDialog implements View.OnClickListene
private List<GiftTab> updateTabs() {
List<GiftTab> tabInfoList = new ArrayList<>();
for (TagsInfo info: GiftModel.get().getTabList()) {
tabInfoList.add(new GiftTab(swithGiftTypeToTabType(info), info.tagName(), info.tagName()));
if (GiftModel.get().getTabList() != null) {
for (TagsInfo info: GiftModel.get().getTabList()) {
tabInfoList.add(new GiftTab(swithGiftTypeToTabType(info), info.tagName(), info.tagName()));
}
}
return tabInfoList;
}
@@ -1467,7 +1469,7 @@ public class GiftDialog extends BottomSheetDialog implements View.OnClickListene
showEasyPopup();
break;
case R.id.iv_open_noble:
VipMainActivity.start(context);
VipCenterActivity.start(context);
//进入贵族中心埋点
HashMap<String, Object> map = new HashMap<>(5);
map.put(IReportConstants.PAYPAGE_TYPE, IReportConstants.THREE);
@@ -1775,4 +1777,8 @@ public class GiftDialog extends BottomSheetDialog implements View.OnClickListene
void onFail();
}
public void sendGift(){
sendGiftButton.performClick();
}
}

View File

@@ -4,13 +4,16 @@ import static com.chwl.core.im.custom.bean.CustomAttachment.CUSTOM_MSG_DRAGON_BA
import static com.chwl.core.im.custom.bean.CustomAttachment.CUSTOM_MSG_DRAGON_BAR_CANCEL;
import static com.chwl.core.manager.RoomEvent.DRAGON_BAR_CANCEL;
import static com.chwl.library.utils.ResUtil.getString;
import static com.netease.nim.uikit.common.util.log.LogUtil.log;
import android.annotation.SuppressLint;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.media.Image;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
@@ -21,6 +24,8 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatDialog;
import androidx.appcompat.widget.AppCompatImageView;
import androidx.recyclerview.widget.GridLayoutManager;
@@ -28,6 +33,13 @@ import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.chwl.app.utils.AvatarHelper;
import com.chwl.core.vip.bean.UserVipInfo;
import com.chwl.library.download.DownloadException;
import com.chwl.library.download.DownloadManager;
import com.chwl.library.download.DownloadRequest;
import com.chwl.library.download.DownloadTask;
import com.chwl.library.download.FileDownloadListener;
import com.chwl.library.utils.PathHelper;
import com.chwl.library.widget.SVGAView;
import com.google.android.flexbox.FlexboxLayout;
import com.netease.nim.uikit.common.util.sys.ScreenUtil;
@@ -92,11 +104,16 @@ import com.chwl.library.net.rxnet.callback.CallBack;
import com.chwl.library.utils.ListUtils;
import com.chwl.library.utils.SingleToastUtil;
import com.chwl.library.utils.config.BasicConfig;
import com.tencent.qgame.animplayer.AnimConfig;
import com.tencent.qgame.animplayer.AnimView;
import com.tencent.qgame.animplayer.inter.IAnimListener;
import com.tencent.qgame.animplayer.util.ScaleType;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@@ -141,6 +158,7 @@ public class UserInfoDialog extends AppCompatDialog implements View.OnClickListe
private AppCompatImageView mIvUserLevel;
private AppCompatImageView mIvUserCharm;
private ImageView ivUserCardWear;
private AnimView ivUserCardWearMP4;
private TextView tvFamilyNameLabel;
private TextView tvFamilyName;
private FlexboxLayout flexbox;
@@ -258,6 +276,42 @@ public class UserInfoDialog extends AppCompatDialog implements View.OnClickListe
mIvUserCharm = findViewById(R.id.iv_user_charm);
ivUserCardWear = findViewById(R.id.iv_user_card_wear);
ivUserCardWearMP4 = findViewById(R.id.iv_user_card_wear_mp4);
ivUserCardWearMP4.setScaleType(ScaleType.CENTER_CROP);
ivUserCardWearMP4.setLoop(Integer.MAX_VALUE);
ivUserCardWearMP4.setAnimListener(new IAnimListener() {
@Override
public boolean onVideoConfigReady(@NonNull AnimConfig animConfig) {
return true;
}
@Override
public void onVideoStart() {
log( "onVideoStart: ");
}
@Override
public void onVideoRender(int i, @Nullable AnimConfig animConfig) {
}
@Override
public void onVideoComplete() {
log( "onVideoComplete: ");
}
@Override
public void onVideoDestroy() {
}
@Override
public void onFailed(int i, @Nullable String s) {
}
});
tvFamilyNameLabel = (TextView) findViewById(R.id.tv_family_name_label);
tvFamilyName = (TextView) findViewById(R.id.tv_family_name);
tvSelectHim = findViewById(R.id.tv_select_him);
@@ -543,9 +597,11 @@ public class UserInfoDialog extends AppCompatDialog implements View.OnClickListe
//资料卡装扮
if (!TextUtils.isEmpty(userInfo.getUserInfoCardPic())) {
ImageLoadUtils.loadImage(context, userInfo.getUserInfoCardPic(), ivUserCardWear);
drawVAPEffect(userInfo.getUserInfoCardPic());
// drawVAPEffect("https://image.pekolive.com/v7.mp4");
} else {
ivUserCardWear.setImageDrawable(null);
ivUserCardWearMP4.setVisibility(View.GONE);
}
if (null != findHimView) {
@@ -602,6 +658,23 @@ public class UserInfoDialog extends AppCompatDialog implements View.OnClickListe
}
}
private void drawVAPEffect(String url) {
String filePath = PathHelper.INSTANCE.generateResourcesFilePath(url);
DownloadRequest request = DownloadRequest.Companion.build(url, filePath, "gift_effect_download", null, 60000L);
DownloadManager.INSTANCE.download(request, new FileDownloadListener() {
@Override
public void onDownloadCompleted(@NonNull DownloadTask task) {
String path = task.getRequest().getPath();
ivUserCardWearMP4.startPlay(new File(path));
}
@Override
public void onDownloadError(@NonNull DownloadException exception) {
ImageLoadUtils.loadImage(context, userInfo.getUserInfoCardPic(), ivUserCardWear);
}
});
}
private void copyName() {
try {
ClipboardManager cm = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
@@ -677,7 +750,8 @@ public class UserInfoDialog extends AppCompatDialog implements View.OnClickListe
private void updateNobleView() {
// 防止访问数据库和网络同时刷新出现图标跳动
NobleInfo nobleInfo = userInfo.getNobleInfo();
// NobleInfo nobleInfo = userInfo.getNobleInfo();
UserVipInfo vipInfo = userInfo.getUserVipInfoVO();
HeadWearInfo userHeadwear = userInfo.getUserHeadwear();
boolean havaHead = false;
// 设置普通人
@@ -688,31 +762,46 @@ public class UserInfoDialog extends AppCompatDialog implements View.OnClickListe
AvatarHelper.loadAvatarFrame(ivAvatarHeadWear, avatarFrame, userHeadwear.getType());
}
}
if (nobleInfo == null || TextUtils.isEmpty(nobleInfo.getCardBg())) {
//如果没贵族信息,就加载头像作为背景
if (vipInfo != null && !vipInfo.getUserCardBG().isEmpty()) {
// findViewById(R.id.transition_mask).setVisibility(View.GONE);
ivAvatarBg.setScaleType(ImageView.ScaleType.MATRIX);
ImageLoadUtils.loadImage(
context,
vipInfo.getUserCardBG().replace("\n",""),
ivAvatarBg,
R.drawable.default_avatar
);
} else {
if (avatarBg == null || !avatarBg.equals(userInfo.getAvatar())) {
avatarBg = userInfo.getAvatar();
ImageLoadUtils.loadImageWithBlur(context, userInfo.getAvatar(), ivAvatarBg, 10, 1);
}
return;
}
// 卡片背景
if (!TextUtils.isEmpty(nobleInfo.getCardBg()) && !topBg.equals(nobleInfo.getCardBg())) {
topBg = nobleInfo.getCardBg();
NobleUtil.loadResource(nobleInfo.getCardBg(), ivAvatarBg, R.drawable.bg_user_info_dialog_top);
}
if (!TextUtils.isEmpty(nobleInfo.getHeadWear())) {
// 头饰
if (!havaHead) {
NobleUtil.loadResource(nobleInfo.getHeadWear(), ivAvatarHeadWear);
}
}
if (!TextUtils.isEmpty(nobleInfo.getBadge())) {
// 勋章
ivBadge.setVisibility(View.VISIBLE);
NobleUtil.loadResource(nobleInfo.getBadge(), ivBadge);
}
// if (nobleInfo == null || TextUtils.isEmpty(nobleInfo.getCardBg())) {
// //如果没贵族信息,就加载头像作为背景
// if (avatarBg == null || !avatarBg.equals(userInfo.getAvatar())) {
// avatarBg = userInfo.getAvatar();
// ImageLoadUtils.loadImageWithBlur(context, userInfo.getAvatar(), ivAvatarBg, 10, 1);
// }
// return;
// }
// // 卡片背景
// if (!TextUtils.isEmpty(nobleInfo.getCardBg()) && !topBg.equals(nobleInfo.getCardBg())) {
// topBg = nobleInfo.getCardBg();
// NobleUtil.loadResource(nobleInfo.getCardBg(), ivAvatarBg, R.drawable.bg_user_info_dialog_top);
// }
// if (!TextUtils.isEmpty(nobleInfo.getHeadWear())) {
// // 头饰
// if (!havaHead) {
// NobleUtil.loadResource(nobleInfo.getHeadWear(), ivAvatarHeadWear);
// }
// }
// if (!TextUtils.isEmpty(nobleInfo.getBadge())) {
// // 勋章
// ivBadge.setVisibility(View.VISIBLE);
// NobleUtil.loadResource(nobleInfo.getBadge(), ivBadge);
// }
}

View File

@@ -51,8 +51,7 @@ class AllServiceGiftLevelDialog : BaseDialog {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
requestWindowFeature(Window.FEATURE_NO_TITLE)
val inflate =
LayoutInflater.from(context).inflate(R.layout.dialog_gift_all_service_level, null)
val inflate = LayoutInflater.from(context).inflate(R.layout.dialog_gift_all_service_level, null)
setContentView(inflate.rootView)
setCancelable(true)
setCanceledOnTouchOutside(true)

View File

@@ -16,12 +16,12 @@ import android.widget.TextView;
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;
import com.chwl.app.vip.VipCenterActivity;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.chwl.app.R;
import com.chwl.library.common.util.Utils;
import com.chwl.app.common.widget.dialog.DialogManager;
import com.chwl.app.vip.VipMainActivity;
import com.chwl.core.market_verify.MarketVerifyModel;
import com.chwl.core.room.event.FaceIsReadyEvent;
import com.chwl.core.room.face.DynamicFaceModel;
@@ -309,7 +309,7 @@ public class DynamicFaceDialog extends BottomSheetDialog
tvNormalTab.setSelected(true);
}
} else if (v.getId() == R.id.iv_open_noble) {
VipMainActivity.start(context);
VipCenterActivity.start(context);
}
}

View File

@@ -16,7 +16,7 @@ import com.chwl.app.ui.widget.magicindicator.buildins.commonnavigator.abs.IMeasu
* 博客: http://hackware.lucode.net
* Created by hackware on 2016/6/26.
*/
public class SimplePagerTitleView extends TextView implements IMeasurablePagerTitleView {
public class SimplePagerTitleView extends androidx.appcompat.widget.AppCompatTextView implements IMeasurablePagerTitleView {
protected int mSelectedColor;
protected int mNormalColor;

View File

@@ -0,0 +1,81 @@
package com.chwl.app.utils;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.animation.ValueAnimator;
import android.view.View;
import android.view.animation.Animation;
public class GiftAnimUtil {
public static void showAnimation(View view) {
// 透明度从0到1
ObjectAnimator fadeIn = ObjectAnimator.ofFloat(view, "alpha", 1f, 1f);
fadeIn.setDuration(1000);
// 尺寸从0%到100%
ObjectAnimator scaleUp = ObjectAnimator.ofPropertyValuesHolder(
view,
PropertyValuesHolder.ofFloat(View.SCALE_X, 0f, 1.2f,1f),
PropertyValuesHolder.ofFloat(View.SCALE_Y, 0f, 1.2f,1f)
);
scaleUp.setDuration(1000);
// 组合动画
AnimatorSet appearSet = new AnimatorSet();
appearSet.playTogether(fadeIn, scaleUp);
// // 设置动画结束监听器
// appearSet.addListener(new AnimatorListenerAdapter() {
// @Override
// public void onAnimationEnd(Animator animation) {
// // 显示动画结束后触发扩展动画
// expandAnimation(view);
// }
// });
// 开始显示动画
appearSet.start();
}
public static void expandAnimation(View view) {
// 尺寸从100%到120%
ObjectAnimator scaleExpand = ObjectAnimator.ofPropertyValuesHolder(
view,
PropertyValuesHolder.ofFloat(View.SCALE_X, 1f, 1.2f,1f),
PropertyValuesHolder.ofFloat(View.SCALE_Y, 1f, 1.2f,1f)
);
scaleExpand.setDuration(500);
// 循环执行3秒
// scaleExpand.setRepeatCount(1);
// scaleExpand.setRepeatMode(ValueAnimator.RESTART);
// scaleExpand.setStartDelay(3000); // 确保在3秒后开始重复
// 设置动画结束监听器
// scaleExpand.addListener(new AnimatorListenerAdapter() {
// @Override
// public void onAnimationEnd(Animator animation) {
// // 扩展动画结束后触发退出动画
// fadeOutAnimation(view);
// }
// });
// 开始扩展动画
scaleExpand.start();
}
public static void fadeOutAnimation(View view) {
// 透明度从1到0
ObjectAnimator fadeOut = ObjectAnimator.ofFloat(view, "alpha", 1f, 0f);
fadeOut.setDuration(500);
// 开始退出动画
fadeOut.start();
}
}

View File

@@ -0,0 +1,108 @@
package com.chwl.app.utils
import java.math.RoundingMode
import java.text.DecimalFormat
import java.text.DecimalFormatSymbols
import java.util.Locale
import kotlin.math.roundToLong
/**
* @Author Vance
* Date2023/12/05 0005 13:59
*/
object NumberUtils {
private val df = DecimalFormat("0.##", DecimalFormatSymbols.getInstance(Locale.US))
private val df2 = DecimalFormat("###,##0.##", DecimalFormatSymbols.getInstance(Locale.US))
@JvmStatic
fun format(num:Long):String{
return format(num.toDouble())
}
@JvmStatic
fun format(num:Int):String{
return format(num.toLong())
}
@JvmStatic
fun format(num:Double):String{
val longValue = num.roundToLong()
return if(num < 10000){
if(num - num.toLong() > 0){
num.toString()
}else {
longValue.toString()
}
}else if(longValue < 1000000){
format(longValue, "K")
}else if(longValue < 1000000000){
format(longValue/1000, "M")
}else
format(longValue/1000000, "B")
}
@JvmStatic
fun format(numOfK:Long, suffix:String, roundUp:Boolean = true):String{
df.roundingMode = if(roundUp) RoundingMode.HALF_UP else RoundingMode.DOWN
return df.format(numOfK/1000.0)+suffix
}
/**
* 用逗号分隔
*/
@JvmStatic
@JvmOverloads
fun formatCommaSplit(number:Double, roundUp:Boolean = true):String {
df.roundingMode = if(roundUp) RoundingMode.HALF_UP else RoundingMode.DOWN
return df2.format(number)
}
@JvmStatic
fun formatCommaSplit(number:Long):String {
return df2.format(number)
}
@JvmStatic
@JvmOverloads
fun parseLong(str:String?, def:Long = 0):Long{
if(str.isNullOrEmpty()){
return def
}
return try {
str.toLong()
} catch (e: Exception) {
return def
}
}
@JvmStatic
@JvmOverloads
fun parseInt(str:String?, def:Int = 0):Int{
if(str.isNullOrEmpty()){
return def
}
return try {
str.toInt()
} catch (e: Exception) {
return def
}
}
@JvmStatic
@JvmOverloads
fun parseDouble(str:String?, def:Double = 0.0):Double{
if(str.isNullOrEmpty()){
return def
}
return try {
str.toDouble()
} catch (e: Exception) {
return def
}
}
}

View File

@@ -0,0 +1,62 @@
package com.chwl.app.utils
import androidx.core.util.Pools.Pool
import java.lang.ref.WeakReference
import java.util.LinkedList
/**
* @Author Vance
* Date2023/12/22 0022 14:26
*/
class WeakPool<T : Any>(private var maxPoolSize: Int):Pool<T> {
init {
if(maxPoolSize <= 0){
maxPoolSize = 8
}
}
private var mPool = LinkedList<WeakReference<T>>()
fun acquire(getIfEmpty :()->T): T {
return acquire() ?: getIfEmpty()
}
override fun acquire(): T? {
if (mPool.size == 0) {
return null
}
while (true){
val item = mPool.poll() ?: return null
if(item.get() != null){
return item.get()
}
}
}
override fun release(instance: T): Boolean {
if(mPool.size > maxPoolSize){
if(getRealSize() > maxPoolSize){
return false
}
}
mPool.addFirst(WeakReference(instance))
return true
}
private fun getRealSize():Int{
val iterator = mPool.listIterator()
while (iterator.hasNext()){
val item = iterator.next().get()
if(item == null){
iterator.remove()
}
}
return mPool.size
}
fun clear(){
mPool.clear()
}
}

View File

@@ -0,0 +1,502 @@
package com.chwl.app.vip
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.util.Log
import android.view.View
import android.widget.TextView
import androidx.activity.viewModels
import androidx.core.view.isVisible
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.chwl.app.R
import com.chwl.app.base.BaseViewBindingActivity
import com.chwl.app.base.TitleBar
import com.chwl.app.common.EmptyViewHelper
import com.chwl.app.databinding.ActivityVipCenterBinding
import com.chwl.app.ui.pay.ChargeActivity
import com.chwl.app.ui.utils.RVDelegate
import com.chwl.app.ui.webview.CommonWebViewActivity
import com.chwl.app.vip.adapter.OnItemClickListener
import com.chwl.app.vip.adapter.VipAuthAdapter
import com.chwl.app.vip.adapter.VipCenterBannerAdapter
import com.chwl.app.vip.adapter.VipCenterIdentificationsAdapter
import com.chwl.app.vip.adapter.VipMagicIndicatorAdapter
import com.chwl.app.vip.adapter.VipRebateAdapter
import com.chwl.app.vip.dialog.SelectPayTypeDialog
import com.chwl.app.vip.dialog.VipAuthDetailsDialog
import com.chwl.core.UriProvider
import com.chwl.core.pay.PayModel
import com.chwl.core.pay.bean.ChargeBean
import com.chwl.core.utils.extension.toast
import com.chwl.core.vip.bean.VipAuthInfo
import com.chwl.core.vip.bean.VipInfo
import com.example.lib_utils.AppUtils
import com.example.lib_utils.UiUtils
import com.example.matisse.internal.utils.UIUtils
import com.example.module_base.support.billing.IBillingService
import com.example.module_base.support.billing.IProductDetails
import com.example.module_base.support.billing.IPurchase
import com.netease.nim.uikit.StatusBarUtil
import com.youth.banner.Banner
import com.youth.banner.adapter.BannerImageAdapter
import com.youth.banner.holder.BannerImageHolder
import com.youth.banner.indicator.CircleIndicator
import com.youth.banner.transformer.AlphaPageTransformer
import com.youth.banner.transformer.DepthPageTransformer
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.greenrobot.eventbus.EventBus
import com.youth.banner.listener.OnPageChangeListener
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import java.text.SimpleDateFormat
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
import java.util.Calendar
import java.util.Locale
class VipCenterActivity : BaseViewBindingActivity<ActivityVipCenterBinding>(),
VipMagicIndicatorAdapter.OnItemSelectListener, OnItemClickListener, IBillingService.Listener {
private val authAdapter = VipAuthAdapter() // 用户权限
private val vipViewModel: VipViewModel by viewModels()
private var chargeList: List<ChargeBean>? = null
private var authInfoList: List<VipAuthInfo>? = null
private val rebateAdapter = VipRebateAdapter()
private var currentChargeInfo: ChargeBean? = null
private lateinit var rvDelegate: RVDelegate<VipAuthInfo>
private lateinit var banner:Banner<VipInfo, VipCenterBannerAdapter>
private lateinit var recyclerView: RecyclerView
private lateinit var vipIdentificationsAdapter: VipCenterIdentificationsAdapter
private var currentIndex = 0
companion object {
@JvmStatic
fun start(context: Context) {
val starter = Intent(context, VipCenterActivity::class.java)
context.startActivity(starter)
}
private const val BIND_CODE_GOLD = 200
private const val TAG = "VipCenterActivity"
}
@SuppressLint("SetTextI18N")
override fun init() {
EventBus.getDefault().register(this)
initVipCenterBar(getString(R.string.vip_center))
updateVipCenterBar()
initView()
initObserve()
rvDelegate = RVDelegate.Builder<VipAuthInfo>()
.setLayoutManager(GridLayoutManager(this, 3))
.setRecyclerView(binding.recyclerViewBottom)
.setEmptyView(
EmptyViewHelper.createEmptyTextView(
context,
getString(R.string.me_no_search_results)
)
)
.setAdapter(authAdapter)
.build()
handleAuthAdapter()
handleViewModel()
handleBinding()
requestChargeList{
loadChargeList(it)
}
}
private fun initView() {
banner = findViewById(R.id.banner_view)
banner.setBannerGalleryEffect(20, 20, 15)
banner.addOnPageChangeListener(object : OnPageChangeListener {
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
// 页面滑动中
}
override fun onPageSelected(position: Int) {
// 页面被选中position 已更新
currentIndex = position
vipViewModel.onItemSelect(position)
refreshBottomArea()
}
override fun onPageScrollStateChanged(state: Int) {
// 页面滚动状态改变
}
})
recyclerView = findViewById(R.id.recycler_view)
recyclerView.layoutManager = GridLayoutManager(this, 2)
}
private fun updateVipCenterBar() {
mTitleBar = findViewById(R.id.title_bar)
// if (mTitleBar != null) {
// mTitleBar.addAction(object : TitleBar.ImageAction(R.drawable.vip_center_help_button) {
// override fun performAction(view: View) {
// CommonWebViewActivity.start(
// this@VipCenterActivity,
// UriProvider.getVipHelpUrl())
// }
// })
// }
}
private fun handleAuthAdapter() {
authAdapter.setOnItemClickListener { _, _, position ->
authAdapter.getItem(position)?.let {
VipAuthDetailsDialog.newInstance(it.descPic, it.authName, it.authIntro).show(this)
}
}
}
private fun handleBinding() {
binding.layoutOpenVip.setOnClickListener {
checkBuyVip {
buyVip()
}
}
binding.recyclerViewBottom.isNestedScrollingEnabled = false
}
@SuppressLint("NotifyDataSetChanged")
private fun handleViewModel() {
vipViewModel.getVipPageInfo()
vipViewModel.loadingLiveData.observe(this) {
if (it == true) {
dialogManager.showProgressDialog(this)
} else {
dialogManager.dismissDialog()
}
}
vipViewModel.authInfosLiveData.observe(this) {
// ArrayList[VipAuthInfo] // 全部特权列表
it?.let {
val filteredList = it.filter { authInfo ->
authInfo.authType == 4 || authInfo.authType == 6 || authInfo.authType == 10 || authInfo.authType == 14 || authInfo.authType == 15 || authInfo.authType == 12 || authInfo.authType == 13
}
authInfoList = filteredList
authAdapter.setNewData(filteredList)
vipIdentificationsAdapter = VipCenterIdentificationsAdapter(this, it, this)
recyclerView.adapter = vipIdentificationsAdapter
}
// authAdapter.setNewData(it)
// it?.let {
// vipIdentificationsAdapter = VipCenterIdentificationsAdapter(this, it, this)
// recyclerView.adapter = vipIdentificationsAdapter
// }
}
vipViewModel.pageLiveData.observe(this) {
it?.let { // 当前显示的 index
// TODO 处理轮播组件 index 更新
currentIndex = it
}
}
vipViewModel.vipInfosLiveData.observe(this) {
it?.let { // ArrayList[VipInfo] 每个等级的 VIP 内容
// TODO 初始化轮播组件
}
}
vipViewModel.myVipInfoLiveData.observe(this) {
val adapter = vipViewModel.vipInfosLiveData.value?.let { it1 ->
VipCenterBannerAdapter(this,
it1, it)
}
banner.setAdapter(adapter, false)
it?.let {
// lifecycleScope.launch {
// delay(500)
banner.setCurrentItem(it.vipLevel-1)
// }
if (it.ownAuthTypes?.contains(13) == true && mTitleBar.actionCount == 1) {
mTitleBar.addAction(object : TitleBar.ImageAction(R.drawable.ic_vip_setting) {
override fun performAction(view: View?) {
VipSettingActivity.start(this@VipCenterActivity)
}
}, 0)
}
} ?: run {
// binding.layoutLevelInfo.isVisible = false
// binding.layoutLevelProgress.isVisible = false
binding.slAuth.isVisible = true
// binding.tvNotOpen.text = getString(R.string.me_no_aristocracy_yet)
}
}
vipViewModel.currVipInfoLiveData.observe(this) {
it?.let { // VipInfo
if (it.comingSoon == 2) {
/// 处理敬请期待情况, 补充显示 SVGA
binding.slAuth.isVisible = false
// binding.bannerView.isVisible = false
binding.layoutBottomPanel.isVisible = false
} else {
val myVipInfo = vipViewModel.myVipInfoLiveData.value
// TODO 根据当前显示的 VIP 信息更新 UI
authAdapter.setVipInfo(it)
authAdapter.notifyDataSetChanged()
handleIdentificationAreaContent(it)
vipIdentificationsAdapter.setVipInfo(it)
refreshBottomArea()
}
} ?: run {
getString(R.string.me_failed_to_get_aristocrat_data).toast()
}
}
}
override fun onItemClick(position: Int) {
authAdapter.getItem(position)?.let {
VipAuthDetailsDialog.newInstance(it.descPic, it.authName, it.authIntro).show(this)
}
}
private fun handleIdentificationAreaContent(vipInfo: VipInfo) {
val exclusivePrivilegesTitle = findViewById<TextView>(R.id.center_title_2)
var count = 0
authInfoList?.map { info ->
if (vipInfo?.ownAuthTypes?.contains(info.authType) == true) {
count ++
}
}
"${getString(R.string.vip_center_4)}\n(${count}/${authInfoList?.size})".also {
binding.centerTitle2.text = it
}
// exclusivePrivilegesTitle.text = R.string.vip_center_4.toString()
}
@SuppressLint("CheckResult")
private fun requestChargeList(call: (List<ChargeBean>) -> Unit) {
PayModel.get().vipList
.compose(bindToLifecycle())
.subscribe(
{
call.invoke(it)
}, {
it.printStackTrace()
}
)
}
private fun initObserve(){
lifecycleScope.launch(Dispatchers.Main) {
vipViewModel.getVipRebateSuccessFlow.collect {
rebateAdapter.notifyItemRangeChanged(0, rebateAdapter.itemCount, true)
}
}
}
private fun loadChargeList(list: List<ChargeBean>) {
this.chargeList = list
refreshBottomArea()
}
private fun checkBuyVip(block: () -> Unit) {
val myVipInfo = vipViewModel.myVipInfoLiveData.value
val currentVipInfo = vipViewModel.vipInfosLiveData.value?.get(currentIndex)
if (currentVipInfo != null &&
myVipInfo != null &&
currentVipInfo.vipLevel > myVipInfo.vipLevel) {
val message = context.getString(R.string.vip_buy_tips).format(
myVipInfo.vipName,currentVipInfo.vipName
)
dialogManager.showOkCancelDialog(message,
context.getString(R.string.miniworld_activity_mwteamroommessageact_07),
context.getString(R.string.miniworld_activity_mwteamroommessageact_08),
true
) { block.invoke() }
} else {
block.invoke()
}
}
private fun buyVip() {
val currentVipInfo = vipViewModel.vipInfosLiveData.value?.get(currentIndex)
currentVipInfo?.let {
val googleUnavailable = ((currentChargeInfo?.productDetails?.getOneTimePurchaseOfferDetails()
?.getPriceAmountMicros()
?: "0") == "0")
var text =
currentChargeInfo?.productDetails?.getOneTimePurchaseOfferDetails()?.getFormattedPrice()
if (text.isNullOrEmpty()) {
text = it.buyAmount.toString()
}
SelectPayTypeDialog.newInstance(
text,
!googleUnavailable,
it.buyAmount
)
.apply {
setOnDiamondChargeClick {
vipViewModel.openVipWithDiamond(
currentChargeInfo?.getProdDesc()?.toIntOrNull() ?: -1
)
}
setOnGoogleChargeClick {
if (googleUnavailable) {
toast(getString(R.string.Recharge_failure))
return@setOnGoogleChargeClick
}
currentChargeInfo?.let { charge ->
buyProduct(charge.productDetails)
}
}
setOnChargeClick {
ChargeActivity.start(this@VipCenterActivity)
}
}
.show(context)
}
}
/*购买商品*/
@SuppressLint("CheckResult")
fun buyProduct(productDetails: IProductDetails?) {
if (productDetails != null) {
Log.d(VipCenterActivity.TAG, "BuyProduct:" + productDetails.getProductId())
// PayModel.get().placeOrder(productDetails.getProductId())
// .compose(bindToLifecycle())
// .subscribe(
// { recordId: PayRecordId ->
// billingManager?.initiatePurchaseFlow(
// productDetails,
// recordId.recordId
// )
// }
// ) { throwable: Throwable ->
// SingleToastUtil.showToast(
// throwable.message
// )
// }
} else {
Log.w(VipCenterActivity.TAG, "skuDetails ==null")
}
}
private fun refreshBottomArea() {
val currentPageVipInfo = vipViewModel.vipInfosLiveData.value?.get(currentIndex)
currentPageVipInfo?.let {
currentChargeInfo = chargeList?.firstOrNull {
it.prodDesc?.toIntOrNull() == currentPageVipInfo.vipLevel
}
if (it.buyAmount == 0) {
binding.tvNoticeText.visibility = View.VISIBLE
binding.tvAdditionalText.visibility = View.GONE
binding.tvOpenVip.visibility = View.GONE
binding.layoutOpenVip.visibility = View.GONE
binding.tvIcon.visibility = View.GONE
getString(R.string.vip_center_9).format(
currentPageVipInfo.vipLevel
).also { binding.tvNoticeText.text = it }
} else {
var myVipIsHighLevel = false
val myVipInfo = vipViewModel.myVipInfoLiveData.value
myVipInfo?.let {
myVipIsHighLevel = myVipInfo.vipLevel >= currentPageVipInfo.vipLevel
}
binding.tvNoticeText.visibility = View.GONE
binding.tvAdditionalText.visibility = View.VISIBLE
binding.tvOpenVip.visibility = View.VISIBLE
binding.layoutOpenVip.visibility = View.VISIBLE
binding.tvIcon.visibility = View.VISIBLE
"${it.buyAmount} ${
getString(R.string.vip_center_5).format(
" / 30"
)
}".also { binding.tvOpenVip.text = it }
val calendar = Calendar.getInstance()
calendar.add(Calendar.DAY_OF_YEAR, 30)
val dateFormat = SimpleDateFormat("yyyy/MM/dd 00:00", Locale.getDefault())
val formattedDate = dateFormat.format(calendar.time)
val result = "$formattedDate ${getString(R.string.vip_center_6)}"
binding.tvAdditionalText.text = result
}
}
}
private fun refreshOpenVipState() {
val currentVipInfo = vipViewModel.currVipInfoLiveData.value
val myVipInfo = vipViewModel.myVipInfoLiveData.value
if (currentVipInfo != null) {
currentChargeInfo = chargeList?.firstOrNull {
it.prodDesc?.toIntOrNull() == currentVipInfo.vipLevel
}
if (currentChargeInfo != null){
"${vipViewModel.myVipInfoLiveData.value?.buyAmount} ${
getString(R.string.vip_center_5).format(
" / 30"
)
}".also { binding.tvOpenVip.text = it }
}
val calendar = Calendar.getInstance()
calendar.add(Calendar.DAY_OF_YEAR, 30)
val dateFormat = SimpleDateFormat("yyyy/MM/dd 00:00", Locale.getDefault())
val formattedDate = dateFormat.format(calendar.time)
val result = "$formattedDate ${getString(R.string.vip_center_6)}"
binding.tvAdditionalText.text = result
} else {
currentChargeInfo = null
// binding.layoutOpenVip.isVisible = false
}
// if (binding.layoutOpenVip.isVisible && binding.layoutLevelProgress.isVisible) {
// binding.layoutBottomPanel.setBackgroundDrawable(binding.layoutLevelProgress.background)
// } else {
// binding.layoutBottomPanel.setBackgroundDrawable(null)
// }
}
override fun onItemSelect(position: Int, view: TextView?) {
TODO("Not yet implemented")
}
override fun onBillingClientSetupFinished() {
TODO("Not yet implemented")
}
override fun onPurchasesUpdated(purchases: List<IPurchase>) {
TODO("Not yet implemented")
}
override fun onConsumeFinished(token: String?, result: Int) {
TODO("Not yet implemented")
}
override fun onFailedHandle(result: Int) {
TODO("Not yet implemented")
}
override fun needSteepStateBar() = true
override fun setStatusBar() {
super.setStatusBar()
StatusBarUtil.transparencyBar(this)
}
}

View File

@@ -1,622 +0,0 @@
package com.chwl.app.vip
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.util.Log
import android.view.View
import android.widget.LinearLayout
import android.widget.TextView
import androidx.activity.viewModels
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.view.children
import androidx.core.view.isInvisible
import androidx.core.view.isVisible
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.GridLayoutManager
import com.example.module_base.support.billing.IBillingResult
import com.example.module_base.support.billing.IBillingService
import com.example.module_base.support.billing.IProductDetails
import com.example.module_base.support.billing.IPurchase
import com.example.module_base.support.google.IGoogleService
import com.netease.nim.uikit.StatusBarUtil
import com.netease.nim.uikit.common.util.sys.TimeUtil
import com.opensource.svgaplayer.SVGADrawable
import com.opensource.svgaplayer.SVGAImageView
import com.opensource.svgaplayer.SVGAParser
import com.opensource.svgaplayer.SVGAVideoEntity
import com.chwl.app.R
import com.chwl.app.base.BaseViewBindingActivity
import com.chwl.app.base.TitleBar
import com.chwl.app.common.EmptyViewHelper
import com.chwl.app.databinding.ActivityVipMainBinding
import com.chwl.app.ui.pay.ChargeActivity
import com.chwl.app.ui.setting.ModifyPwdActivity
import com.chwl.app.ui.utils.RVDelegate
import com.chwl.app.ui.webview.CommonWebViewActivity
import com.chwl.app.ui.widget.magicindicator.buildins.commonnavigator.CommonNavigator
import com.chwl.app.vip.adapter.VipAuthAdapter
import com.chwl.app.vip.adapter.VipMagicIndicatorAdapter
import com.chwl.app.vip.adapter.VipRebateAdapter
import com.chwl.app.vip.dialog.SelectPayTypeDialog
import com.chwl.app.vip.dialog.VipAuthDetailsDialog
import com.chwl.app.vip.dialog.VipRemainTimeDialog
import com.chwl.core.UriProvider
import com.chwl.core.pay.PayModel
import com.chwl.core.pay.bean.ChargeBean
import com.chwl.core.pay.bean.PayRecordId
import com.chwl.core.utils.net.IgnoreException
import com.chwl.core.vip.bean.VipAuthInfo
import com.chwl.core.vip.bean.VipInfo
import com.chwl.core.utils.extension.toast
import com.chwl.core.vip.VipOpenEvent
import com.chwl.library.utils.SingleToastUtil
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import java.net.MalformedURLException
import java.net.URL
class VipMainActivity : BaseViewBindingActivity<ActivityVipMainBinding>(),
VipMagicIndicatorAdapter.OnItemSelectListener, IBillingService.Listener {
companion object {
@JvmStatic
fun start(context: Context) {
val starter = Intent(context, VipMainActivity::class.java)
context.startActivity(starter)
}
private const val BIND_CODE_GOLD = 200
private const val TAG = "VipMainActivity"
}
private val authAdapter = VipAuthAdapter()
private lateinit var rvDelegate: RVDelegate<VipAuthInfo>
private val vipViewModel: VipViewModel by viewModels()
private var billingManager: IBillingService? = null
private var currentChargeInfo: ChargeBean? = null
private var chargeList: List<ChargeBean>? = null
private val rebateAdapter = VipRebateAdapter()
@SuppressLint("SetTextI18n")
override fun init() {
EventBus.getDefault().register(this)
initWhiteTitleBar(getString(R.string.vip_center))
mTitleBar.addAction(object : TitleBar.ImageAction(R.drawable.ic_vip_help) {
override fun performAction(view: View) {
CommonWebViewActivity.start(this@VipMainActivity, UriProvider.getVipHelpUrl())
}
})
initView()
initObserve()
binding.ivRankList.setOnClickListener {
CommonWebViewActivity.start(this@VipMainActivity, UriProvider.getRankListUrl())
}
binding.ivTimeHelp.setOnClickListener {
VipRemainTimeDialog.newInstance().show(this)
}
rvDelegate = RVDelegate.Builder<VipAuthInfo>()
.setLayoutManager(GridLayoutManager(this, 3))
.setRecyclerView(binding.recyclerView)
.setEmptyView(
EmptyViewHelper.createEmptyTextView(
context,
getString(R.string.me_no_search_results)
)
)
.setAdapter(authAdapter)
.build()
binding.recyclerView.isNestedScrollingEnabled = false
authAdapter.setOnItemClickListener { _, _, position ->
authAdapter.getItem(position)?.let {
VipAuthDetailsDialog.newInstance(it.descPic, it.authName, it.authIntro).show(this)
}
}
vipViewModel.getVipPageInfo()
vipViewModel.loadingLiveData.observe(this) {
if (it == true) {
dialogManager.showProgressDialog(this)
} else {
dialogManager.dismissDialog()
}
}
vipViewModel.authInfosLiveData.observe(this) {
authAdapter.setNewData(it)
}
vipViewModel.vipInfosLiveData.observe(this) {
it?.let {
initTitleTab(it)
}
}
vipViewModel.myVipInfoLiveData.observe(this) {
it?.let {
binding.layoutLevelInfo.isVisible = true
binding.layoutLevelProgress.isVisible = true
binding.tvNotOpen.text =
"${getString(R.string.me_current_power_value)}${it.currScore}"
binding.tvCurrValue.text = "${getString(R.string.me_current)}${it.currScore}"
binding.tvCurrLevelName.text = it.vipName
binding.tvKeepValue.text = "${getString(R.string.me_grading)}${it.levelKeepScore}"
if (it.isMaxLevel) {
binding.llNextLevelDesc.isVisible = false
binding.tvMaxLevelHint.isVisible = true
binding.tvUpValue.isVisible = false
} else {
binding.llNextLevelDesc.isVisible = true
binding.tvMaxLevelHint.isVisible = false
binding.tvUpValue.isVisible = true
binding.tvNextLevelName.text = it.nextVipName
binding.tvUpValue.text = "${getString(R.string.me_upgrade)}${it.levelUpScore}"
binding.tvUpgradeValue.text = "${it.levelUpScore - it.currScore}"
}
binding.tvResidueTime.text = TimeUtil.getElapseTimeForVip(it.remainSeconds)
binding.seekBar.max = it.levelUpScore
binding.seekBar.progress = Math.min(it.currScore, it.levelUpScore)
val currValueParams =
binding.tvCurrValue.layoutParams as ConstraintLayout.LayoutParams
currValueParams.horizontalBias =
Math.min(it.currScore.toFloat() / it.levelUpScore, 1f)
binding.tvCurrValue.layoutParams = currValueParams
val keepParams =
binding.ivKeepIndicator.layoutParams as ConstraintLayout.LayoutParams
keepParams.horizontalBias = it.levelKeepScore.toFloat() / it.levelUpScore
binding.ivKeepIndicator.layoutParams = keepParams
if (it.ownAuthTypes?.contains(13) == true && mTitleBar.actionCount == 1) {
mTitleBar.addAction(object : TitleBar.ImageAction(R.drawable.ic_vip_setting) {
override fun performAction(view: View) {
VipSettingActivity.start(this@VipMainActivity)
}
}, 0)
}
} ?: run {
binding.layoutLevelInfo.isVisible = false
binding.layoutLevelProgress.isVisible = false
binding.slAuth.isVisible = true
binding.tvNotOpen.text = getString(R.string.me_no_aristocracy_yet)
}
}
vipViewModel.currVipInfoLiveData.observe(this) {
it?.let {
if (it.comingSoon == 2) {
binding.llNotOpen.isVisible = true
binding.slAuth.isVisible = false
binding.layoutBottomPanel.isVisible = false
loadSVGA(binding.ivNotOpenIcon, it.vipLogo)
} else {
binding.slAuth.isVisible = true
binding.llNotOpen.isVisible = false
binding.layoutBottomPanel.isVisible = true
val myVipInfo = vipViewModel.myVipInfoLiveData.value
binding.ivMyLevel.isInvisible = it.vipLevel != myVipInfo?.vipLevel
binding.tvNotOpen.isInvisible =
!(it.vipLevel == myVipInfo?.vipLevel || myVipInfo == null)
loadSVGA(binding.ivVipIcon, it.vipLogo)
binding.tvAuthNum.text =
"${it.ownAuthTypes?.size ?: 0}/${vipViewModel.authInfosLiveData.value?.size ?: 0}"
authAdapter.setVipInfo(it)
authAdapter.notifyDataSetChanged()
loadRebateData(it)
refreshOpenVipState()
}
} ?: run {
getString(R.string.me_failed_to_get_aristocrat_data).toast()
binding.llNotOpen.isVisible = false
binding.slAuth.isVisible = false
}
}
vipViewModel.pageLiveData.observe(this) {
it?.let {
binding.magicIndicator.onPageSelected(it)
}
}
binding.layoutOpenVip.setOnClickListener {
checkBuyVip {
buyVip()
}
}
requestChargeList{
loadChargeList(it)
}
initBilling()
}
private fun initBilling() {
billingManager = IGoogleService.newBillingService(this,this)
}
override fun initWhiteTitleBar(title: String?) {
mTitleBar = findViewById(R.id.title_bar)
if (mTitleBar != null) {
mTitleBar.setTitle(title)
mTitleBar.setImmersive(false)
mTitleBar.setTitleColor(resources.getColor(R.color.white))
mTitleBar.setLeftImageResource(R.drawable.arrow_left_white)
mTitleBar.setBackgroundResource(R.color.transparent)
mTitleBar.setLeftClickListener { onLeftClickListener() }
}
}
/**
* 初始化推荐和派对tab
*/
private fun initTitleTab(vipInfos: List<VipInfo>) {
val commonNavigator = CommonNavigator(context)
commonNavigator.isEnablePivotScroll = true
commonNavigator.isFollowTouch = false
val magicIndicatorAdapter =
VipMagicIndicatorAdapter(
context,
vipInfos
)
magicIndicatorAdapter.setOnItemSelectListener(this)
commonNavigator.adapter = magicIndicatorAdapter
binding.magicIndicator.navigator = commonNavigator
commonNavigator.titleContainer.showDividers = LinearLayout.SHOW_DIVIDER_MIDDLE
}
private fun loadSVGA(svgaImageView: SVGAImageView, svgaUrl: String) {
try {
SVGAParser.shareParser()
.decodeFromURL(URL(svgaUrl), object : SVGAParser.ParseCompletion {
override fun onComplete(videoItem: SVGAVideoEntity) {
val drawable = SVGADrawable(videoItem)
svgaImageView.setImageDrawable(drawable)
svgaImageView.startAnimation()
}
override fun onError() {
}
})
} catch (e: MalformedURLException) {
}
}
@SuppressLint("SetTextI18n")
override fun onItemSelect(position: Int, view: TextView?) {
vipViewModel.onItemSelect(position)
}
@Subscribe(threadMode = ThreadMode.MAIN)
fun onVipOpenEvent(vipOpenEvent: VipOpenEvent) {
getString(R.string.me_opening_of_the_aristocracy_successful).toast()
vipViewModel.getVipPageInfo()
}
override fun needSteepStateBar() = true
override fun setStatusBar() {
super.setStatusBar()
StatusBarUtil.transparencyBar(this)
}
/*客户端设置成功回调*/
@SuppressLint("CheckResult", "SetTextI18n")
override fun onBillingClientSetupFinished() {
Log.i(TAG, "onBillingClientSetupFinished")
val call: ((List<ChargeBean>) -> Unit) = { list ->
loadChargeList(list)
val productKeys = ArrayList<String>()
list.forEach {
productKeys.add(it.getChargeProdId())
}
billingManager?.querySkuDetailsAsync(productKeys,
object : IBillingService.ProductDetailsResponseListener {
override fun onProductDetailsResponse(
billingResult: IBillingResult,
productDetails: List<IProductDetails>
) {
if (!billingResult.isResponseOk()) {
Log.w(
TAG,
"Unsuccessful query for Error code: " + billingResult.getResponseCode()
)
} else if (productDetails.isNotEmpty()) {
for (item in list) {
for (skuDetails in productDetails) {
if (skuDetails.getProductId() == item.getChargeProdId()) {
item.productDetails = skuDetails
break
}
}
}
loadChargeList(list)
}
}
})
}
val list = chargeList
if (list.isNullOrEmpty()) {
requestChargeList{
call.invoke(it)
}
} else {
call.invoke(list)
}
}
@SuppressLint("CheckResult")
private fun requestChargeList(call: (List<ChargeBean>) -> Unit) {
PayModel.get().vipList
.compose(bindToLifecycle())
.subscribe(
{
call.invoke(it)
}, {
it.printStackTrace()
}
)
}
/*商品更新回调*/
@SuppressLint("CheckResult")
override fun onPurchasesUpdated(purchases: List<IPurchase>) {
for (purchase in purchases) {
if (purchase.isPurchasedState() &&
purchase.getAccountIdentifiers() != null
) {
PayModel.get().verifyOrder(
purchase.getAccountIdentifiers()!!.getObfuscatedAccountId(),
purchase.getProducts().firstOrNull(),
purchase.getPackageName(),
purchase.getPurchaseToken()
)
.compose(bindToLifecycle())
.subscribe(
{ token: String ->
//L.i("token=" + token);
billingManager?.consumeAsync(token)
// var skuDetails: IProductDetails? = null
// if (googleChargeBean?.getChargeProdId() == purchase.getProducts()
// .firstOrNull()
// ) {
// skuDetails = googleChargeBean?.productDetails
// }
// if (skuDetails != null) {
// val eventValue: MutableMap<String, Any> =
// HashMap()
// eventValue[AFInAppEventParameterName.CONTENT_TYPE] = "Gold"
// eventValue[AFInAppEventParameterName.QUANTITY] = 1
// eventValue[AFInAppEventParameterName.CONTENT_ID] =
// purchase.getOrderId()!!
// if (skuDetails.getOneTimePurchaseOfferDetails() != null) {
// eventValue[AFInAppEventParameterName.REVENUE] =
// skuDetails.getOneTimePurchaseOfferDetails()
// ?.getPriceAmountMicros()!! / 1000000f
// eventValue["Price"] =
// skuDetails.getOneTimePurchaseOfferDetails()
// ?.getFormattedPrice()!!
// eventValue[AFInAppEventParameterName.CURRENCY] =
// skuDetails.getOneTimePurchaseOfferDetails()
// ?.getPriceCurrencyCode()!!
// }
// AppsFlyerLib.getInstance().logEvent(
// applicationContext,
// AFInAppEventType.PURCHASE,
// eventValue
// )
// }
}
) { throwable: Throwable ->
if (throwable !is IgnoreException) {
SingleToastUtil.showToast(throwable.message)
}
}
}
}
Log.i(TAG, "onPurchasesUpdated")
}
override fun onConsumeFinished(token: String?, result: Int) {
}
override fun onFailedHandle(result: Int) {
}
/*购买商品*/
@SuppressLint("CheckResult")
fun buyProduct(productDetails: IProductDetails?) {
if (productDetails != null) {
Log.d(TAG, "BuyProduct:" + productDetails.getProductId())
PayModel.get().placeOrder(productDetails.getProductId())
.compose(bindToLifecycle())
.subscribe(
{ recordId: PayRecordId ->
billingManager?.initiatePurchaseFlow(
productDetails,
recordId.recordId
)
}
) { throwable: Throwable ->
SingleToastUtil.showToast(
throwable.message
)
}
} else {
Log.w(TAG, "skuDetails ==null")
}
}
override fun onResume() {
super.onResume()
if (billingManager?.isServiceConnected() == true) {
billingManager?.onQueryPurchases()
}
}
override fun onDestroy() {
super.onDestroy()
EventBus.getDefault().unregister(this)
billingManager?.destroy()
currentChargeInfo = null
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
dialogManager.dismissDialog()
if (resultCode != RESULT_OK) {
return
}
if (requestCode == BIND_CODE_GOLD) {
ModifyPwdActivity.start(this, ModifyPwdActivity.FOGERT_PAY_PWD)
}
}
private fun initView() {
binding.tvTabPrivilege.setOnClickListener {
showPrivilegeTab()
}
binding.tvTabRebate.setOnClickListener {
showRebateTab()
}
rebateAdapter.onGetListener = {
vipViewModel.getVipRebate(it)
}
binding.rvRebate.isNestedScrollingEnabled = false
binding.rvRebate.adapter = rebateAdapter
}
private fun initObserve(){
lifecycleScope.launch(Dispatchers.Main) {
vipViewModel.getVipRebateSuccessFlow.collect {
rebateAdapter.notifyItemRangeChanged(0, rebateAdapter.itemCount, true)
}
}
}
private fun showPrivilegeTab() {
binding.layoutRebate.isInvisible = true
binding.groupPrivilege.isInvisible = false
binding.tvTabPrivilege.setBackgroundResource(R.drawable.vip_bg_tab_selected)
binding.tvTabRebate.setBackgroundResource(R.drawable.vip_bg_tab_unselected)
}
private fun showRebateTab() {
binding.groupPrivilege.isInvisible = true
binding.layoutRebate.isInvisible = false
binding.tvTabPrivilege.setBackgroundResource(R.drawable.vip_bg_tab_unselected)
binding.tvTabRebate.setBackgroundResource(R.drawable.vip_bg_tab_selected)
}
private fun loadChargeList(list: List<ChargeBean>) {
this.chargeList = list
refreshOpenVipState()
}
private fun loadRebateData(info: VipInfo) {
binding.tvTableLevelName.text = info.vipName
binding.tvRebateTips1.text =
context.getString(R.string.vip_buy_tips_format).format(info.vipName)
rebateAdapter.setNewData(info.returnProfits)
val isNormalStatus = info.isRebate()
binding.layoutRebate.children.forEach {
if(it == binding.tvRebateDisableStatus){
it.isVisible = !isNormalStatus
}else{
it.isVisible = isNormalStatus
}
}
}
private fun refreshOpenVipState() {
val currentVipInfo = vipViewModel.currVipInfoLiveData.value
val myVipInfo = vipViewModel.myVipInfoLiveData.value
if (currentVipInfo != null) {
currentChargeInfo = chargeList?.firstOrNull {
it.prodDesc?.toIntOrNull() == currentVipInfo.vipLevel
}
if (currentChargeInfo != null && (myVipInfo == null || myVipInfo.vipLevel < currentVipInfo.vipLevel)) {
binding.tvOpenVip.text =
"${currentChargeInfo?.getMoney()} ${
getString(R.string.vip_buy_format).format(
currentVipInfo.vipName
)
}"
binding.layoutOpenVip.isVisible = true
} else {
binding.layoutOpenVip.isVisible = false
}
} else {
currentChargeInfo = null
binding.layoutOpenVip.isVisible = false
}
if (binding.layoutOpenVip.isVisible && binding.layoutLevelProgress.isVisible) {
binding.layoutBottomPanel.setBackgroundDrawable(binding.layoutLevelProgress.background)
} else {
binding.layoutBottomPanel.setBackgroundDrawable(null)
}
}
private fun checkBuyVip(block: () -> Unit) {
val myVipInfo = vipViewModel.myVipInfoLiveData.value
val currentVipInfo = vipViewModel.currVipInfoLiveData.value
if (currentVipInfo != null && myVipInfo != null && currentVipInfo.vipLevel > myVipInfo.vipLevel) {
val message = context.getString(R.string.vip_buy_tips).format(
myVipInfo.vipName,currentVipInfo.vipName
)
dialogManager.showOkCancelDialog(message,
context.getString(R.string.miniworld_activity_mwteamroommessageact_07),
context.getString(R.string.miniworld_activity_mwteamroommessageact_08),
true
) { block.invoke() }
} else {
block.invoke()
}
}
private fun buyVip() {
val googleUnavailable = ((currentChargeInfo?.productDetails?.getOneTimePurchaseOfferDetails()
?.getPriceAmountMicros()
?: "0") == "0")
var text =
currentChargeInfo?.productDetails?.getOneTimePurchaseOfferDetails()?.getFormattedPrice()
if (text.isNullOrEmpty()) {
text = ((currentChargeInfo?.money ?: 0.0) * 1000).toInt().toString()
}
SelectPayTypeDialog.newInstance(
text,
!googleUnavailable,
currentChargeInfo?.getMoney() ?: 0.0
)
.apply {
setOnDiamondChargeClick {
vipViewModel.openVipWithDiamond(
currentChargeInfo?.getProdDesc()?.toIntOrNull() ?: -1
)
}
setOnGoogleChargeClick {
if (googleUnavailable) {
toast(getString(R.string.Recharge_failure))
return@setOnGoogleChargeClick
}
currentChargeInfo?.let { charge ->
buyProduct(charge.productDetails)
}
}
setOnChargeClick {
ChargeActivity.start(this@VipMainActivity)
}
}
.show(context)
}
}

View File

@@ -22,6 +22,6 @@ class VipAuthAdapter :
helper.setText(R.id.tv_auth_name, item.authName)
helper.getView<ImageView>(R.id.iv_auth_icon).load(item.authIcon)
helper.itemView.alpha =
if (vipInfo?.ownAuthTypes?.contains(item.authType) == true) 1f else 0.5f
if (vipInfo?.ownAuthTypes?.contains(item.authType) == true) 1f else 0.7f
}
}

View File

@@ -0,0 +1,151 @@
package com.chwl.app.vip.adapter
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.chwl.app.R
import com.chwl.app.ui.utils.loadAnim
import com.chwl.core.vip.bean.VipInfo
import com.chwl.library.download.DownloadException
import com.chwl.library.download.DownloadManager.download
import com.chwl.library.download.DownloadRequest.Companion.build
import com.chwl.library.download.DownloadTask
import com.chwl.library.download.FileDownloadListener
import com.chwl.library.utils.PathHelper.generateResourcesFilePath
import com.chwl.library.utils.ResUtil.getString
import com.tencent.qgame.animplayer.AnimConfig
import com.tencent.qgame.animplayer.AnimView
import com.tencent.qgame.animplayer.inter.IAnimListener
import com.tencent.qgame.animplayer.util.ScaleType
import com.youth.banner.adapter.BannerAdapter
import java.io.File
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale
class VipCenterBannerAdapter(
private val context: Context,
private val vipInfos: List<VipInfo>,
private val myVipInfo: VipInfo?
) : BannerAdapter<VipInfo, VipCenterBannerAdapter.BannerViewHolder>(vipInfos) {
private val DOWNLOAD_TAG = "gift_effect_download"
override fun onCreateHolder(parent: ViewGroup, viewType: Int): BannerViewHolder {
val view = LayoutInflater.from(context).inflate(
R.layout.banner_vip_center_custom,
parent,
false)
return BannerViewHolder(view)
}
override fun onBindView(holder: BannerViewHolder, data: VipInfo, position: Int, size: Int) {
holder.dueText.visibility = View.GONE
myVipInfo?.let {
if (it.vipLevel == data.vipLevel) {
val calendar = Calendar.getInstance()
calendar.add(Calendar.SECOND, it.remainSeconds)
val dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
val formattedDate = dateFormat.format(calendar.time)
val result = "${getString(R.string.vip_center_2)}$formattedDate"
holder.dueText.text = result
holder.dueText.visibility = View.VISIBLE
} else if (it.vipLevel < data.vipLevel) {
holder.dueText.text = getString(R.string.vip_center_8)
holder.dueText.visibility = View.VISIBLE
} else {
holder.dueText.visibility = View.GONE
}
}
when(position) {
0-> {
holder.dueText.setTextColor(context.resources.getColor(R.color.color_3A4D14))
holder.imgBackground.setImageResource(R.drawable.vip_center_level_1)
}
1-> {
holder.dueText.setTextColor(context.resources.getColor(R.color.color_4D143A))
holder.imgBackground.setImageResource(R.drawable.vip_center_level_2)
}
2-> {
holder.dueText.setTextColor(context.resources.getColor(R.color.color_4D2C14))
holder.imgBackground.setImageResource(R.drawable.vip_center_level_3)
}
3-> {
holder.dueText.setTextColor(context.resources.getColor(R.color.color_44144D))
holder.imgBackground.setImageResource(R.drawable.vip_center_level_4)
}
4-> {
holder.dueText.setTextColor(context.resources.getColor(R.color.color_1C344D))
holder.imgBackground.setImageResource(R.drawable.vip_center_level_5)
}
5-> {
holder.dueText.setTextColor(context.resources.getColor(R.color.color_1C4D35))
holder.imgBackground.setImageResource(R.drawable.vip_center_level_6)
}
6-> {
holder.dueText.setTextColor(context.resources.getColor(R.color.color_44144D))
holder.imgBackground.setImageResource(R.drawable.vip_center_level_7)
}
7-> {
holder.dueText.setTextColor(context.resources.getColor(R.color.color_4D371C))
holder.imgBackground.setImageResource(R.drawable.vip_center_level_8)
}
8-> {
holder.dueText.setTextColor(context.resources.getColor(R.color.color_4D1C1C))
holder.imgBackground.setImageResource(R.drawable.vip_center_level_9)
}
}
holder.vapAnimView.setScaleType(ScaleType.FIT_XY)
holder.vapAnimView.setLoop(Int.MAX_VALUE)
holder.vapAnimView.setAnimListener(object : IAnimListener {
override fun onFailed(errorType: Int, errorMsg: String?) {
println(errorMsg)
}
override fun onVideoComplete() {
println("complete")
}
override fun onVideoDestroy() {
println("destory")
}
override fun onVideoRender(frameIndex: Int, config: AnimConfig?) {
println("rendering")
}
override fun onVideoStart() {
println("start")
}
})
val filePath = generateResourcesFilePath(data.vipLogo)
val request = build(data.vipLogo, filePath, DOWNLOAD_TAG, null, 60000L)
download(request, object : FileDownloadListener() {
override fun onDownloadCompleted(task: DownloadTask) {
val path = task.getRequest().getPath()
holder.vapAnimView.startPlay(File(path))
}
override fun onDownloadError(exception: DownloadException) {
exception.printStackTrace()
}
})
}
inner class BannerViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val imgBackground: ImageView = view.findViewById(R.id.img_background)
// val svgaImage: SVGAImageView = view.findViewById(R.id.iv_vip_icon)
val vapAnimView: AnimView = view.findViewById(R.id.vap_anim_view)
val dueText: TextView = view.findViewById(R.id.due_date_textview)
}
}

View File

@@ -0,0 +1,156 @@
package com.chwl.app.vip.adapter
import android.annotation.SuppressLint
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.chwl.app.R
import com.chwl.core.vip.bean.VipAuthInfo
import com.chwl.core.vip.bean.VipInfo
interface OnItemClickListener {
fun onItemClick(position: Int)
}
class VipCenterIdentificationsAdapter(
private val context: Context,
private val items: List<VipAuthInfo>,
private val listener: OnItemClickListener
) : RecyclerView.Adapter<VipCenterIdentificationsAdapter.ItemViewHolder>() {
private var vipInfo: VipInfo? = null
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): VipCenterIdentificationsAdapter.ItemViewHolder {
val view = LayoutInflater.from(context).inflate(R.layout.vip_center_idnetifications_layout, parent, false)
return ItemViewHolder(view)
}
override fun onBindViewHolder(
holder: VipCenterIdentificationsAdapter.ItemViewHolder,
position: Int
) {
val filteredList = items.filter {
it.authType == 1 || it.authType == 5 || it.authType == 8 || it.authType ==
11 || it.authType == 12
}
val item = filteredList[position]
vipInfo?.let {
holder.titleTextView.text = item.authName
// val lv = it.vipLevel
// var resourceName = "null"
when (position) {
0 -> {
when (it.vipLevel) {
1 -> holder.contentImageView.setImageResource(R.drawable.vip_center_identification_vipidentity_lv1)
2 -> holder.contentImageView.setImageResource(R.drawable.vip_center_identification_vipidentity_lv2)
3 -> holder.contentImageView.setImageResource(R.drawable.vip_center_identification_vipidentity_lv3)
4 -> holder.contentImageView.setImageResource(R.drawable.vip_center_identification_vipidentity_lv4)
5 -> holder.contentImageView.setImageResource(R.drawable.vip_center_identification_vipidentity_lv5)
6 -> holder.contentImageView.setImageResource(R.drawable.vip_center_identification_vipidentity_lv6)
7 -> holder.contentImageView.setImageResource(R.drawable.vip_center_identification_vipidentity_lv7)
8 -> holder.contentImageView.setImageResource(R.drawable.vip_center_identification_vipidentity_lv8)
9 -> holder.contentImageView.setImageResource(R.drawable.vip_center_identification_vipidentity_lv9)
}
// resourceName = "vip_center_identification_vipidentity_lv$lv"
}
1 -> {
// resourceName = "vip_center_identification_roomcard_lv$lv"
when (it.vipLevel) {
1 -> holder.contentImageView.setImageResource(R.drawable.vip_center_identification_roomcard_lv1)
2 -> holder.contentImageView.setImageResource(R.drawable.vip_center_identification_roomcard_lv2)
3 -> holder.contentImageView.setImageResource(R.drawable.vip_center_identification_roomcard_lv3)
4 -> holder.contentImageView.setImageResource(R.drawable.vip_center_identification_roomcard_lv4)
5 -> holder.contentImageView.setImageResource(R.drawable.vip_center_identification_roomcard_lv5)
6 -> holder.contentImageView.setImageResource(R.drawable.vip_center_identification_roomcard_lv6)
7 -> holder.contentImageView.setImageResource(R.drawable.vip_center_identification_roomcard_lv7)
8 -> holder.contentImageView.setImageResource(R.drawable.vip_center_identification_roomcard_lv8)
9 -> holder.contentImageView.setImageResource(R.drawable.vip_center_identification_roomcard_lv9)
}
}
2 -> {
// resourceName = "vip_center_identification_mic_lv$lv"
when (it.vipLevel) {
3 -> holder.contentImageView.setImageResource(R.drawable.vip_center_identification_mic_lv3)
4 -> holder.contentImageView.setImageResource(R.drawable.vip_center_identification_mic_lv4)
5 -> holder.contentImageView.setImageResource(R.drawable.vip_center_identification_mic_lv5)
6 -> holder.contentImageView.setImageResource(R.drawable.vip_center_identification_mic_lv6)
7 -> holder.contentImageView.setImageResource(R.drawable.vip_center_identification_mic_lv7)
8 -> holder.contentImageView.setImageResource(R.drawable.vip_center_identification_mic_lv8)
9 -> holder.contentImageView.setImageResource(R.drawable.vip_center_identification_mic_lv9)
}
}
3 -> {
// resourceName = "vip_center_identification_bubble_lv$lv"
when (it.vipLevel) {
4 -> holder.contentImageView.setImageResource(R.drawable.vip_center_identification_bubble_lv4)
5 -> holder.contentImageView.setImageResource(R.drawable.vip_center_identification_bubble_lv5)
6 -> holder.contentImageView.setImageResource(R.drawable.vip_center_identification_bubble_lv6)
7 -> holder.contentImageView.setImageResource(R.drawable.vip_center_identification_bubble_lv7)
8 -> holder.contentImageView.setImageResource(R.drawable.vip_center_identification_bubble_lv8)
9 -> holder.contentImageView.setImageResource(R.drawable.vip_center_identification_bubble_lv9)
}
}
4 -> {
// resourceName = "vip_center_identification_entry_lv$lv"
when (it.vipLevel) {
4 -> holder.contentImageView.setImageResource(R.drawable.vip_center_identification_entry_lv4)
5 -> holder.contentImageView.setImageResource(R.drawable.vip_center_identification_entry_lv5)
6 -> holder.contentImageView.setImageResource(R.drawable.vip_center_identification_entry_lv6)
7 -> holder.contentImageView.setImageResource(R.drawable.vip_center_identification_entry_lv7)
8 -> holder.contentImageView.setImageResource(R.drawable.vip_center_identification_entry_lv8)
9 -> holder.contentImageView.setImageResource(R.drawable.vip_center_identification_entry_lv9)
}
}
}
// val resourceId = context.resources
// .getIdentifier(resourceName, "drawable", context.packageName)
// holder.contentImageView.setImageResource(resourceId)
}
val screenWidth = context.resources.displayMetrics.widthPixels
val itemWidth = (screenWidth * 160)/375
val layoutParams = holder.itemView.layoutParams
layoutParams.width = itemWidth
holder.itemView.layoutParams = layoutParams
// holder.itemView.setOnClickListener {
// listener.onItemClick(position)
// }
}
override fun getItemCount(): Int {
return vipInfo?.let {
when (it.vipLevel) {
1, 2 -> 2
3 -> 3
else -> 5
}
} ?: 0 // items.size
}
@SuppressLint("NotifyDataSetChanged")
fun setVipInfo(vipInfo: VipInfo?) {
this.vipInfo = vipInfo
this.notifyDataSetChanged()
}
inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val contentImageView: ImageView = view.findViewById(R.id.item_image)
val titleTextView: TextView = view.findViewById(R.id.item_title)
}
}

View File

@@ -51,9 +51,9 @@ class SelectPayTypeDialog : BaseDialogFragment<DialogSelectPayTypeBinding>() {
fun newInstance(
descText: String,
showGoogleCharge: Boolean = false,
money: Double = 0.0
money: Int = 0
): SelectPayTypeDialog {
return newInstance(descText, (money * 1000).toLong(), showGoogleCharge)
return newInstance(descText, money.toLong(), showGoogleCharge)
}

View File

@@ -12,6 +12,14 @@ import com.chwl.app.base.BaseDialogFragment
import com.chwl.app.databinding.DialogVipUpgradeBinding
import com.chwl.app.vip.VipViewModel
import com.chwl.core.vip.bean.VipInfo
import com.chwl.library.download.DownloadException
import com.chwl.library.download.DownloadManager.download
import com.chwl.library.download.DownloadRequest
import com.chwl.library.download.DownloadRequest.Companion
import com.chwl.library.download.DownloadTask
import com.chwl.library.download.FileDownloadListener
import com.chwl.library.utils.PathHelper.generateResourcesFilePath
import java.io.File
import java.net.MalformedURLException
import java.net.URL
@@ -53,23 +61,38 @@ class VipUpgradeDialog : BaseDialogFragment<DialogVipUpgradeBinding>() {
}
binding?.tvVipUplevel?.setOnClickListener { dismissAllowingStateLoss() }
binding?.tvVipOrigin?.setOnClickListener { vm.saveOriginDisguise() }
try {
SVGAParser.shareParser()
.decodeFromURL(URL(vipInfo.vipLogo), object : SVGAParser.ParseCompletion {
override fun onComplete(videoItem: SVGAVideoEntity) {
val drawable = SVGADrawable(videoItem)
if (isViewLoaded) {
_binding?.ivVipIcon?.setImageDrawable(drawable)
_binding?.ivVipIcon?.startAnimation()
}
}
binding?.ivVipIconMp4?.setLoop(Int.MAX_VALUE)
override fun onError() {
}
})
} catch (e: MalformedURLException) {
val filePath = generateResourcesFilePath(vipInfo.vipLogo)
val request = DownloadRequest.build(vipInfo.vipLogo, filePath, "gift_effect_download", null, 60000L)
download(request, object : FileDownloadListener() {
override fun onDownloadCompleted(task: DownloadTask) {
val path = task.getRequest().getPath()
binding?.ivVipIconMp4?.startPlay(File(path))
}
}
override fun onDownloadError(exception: DownloadException) {
exception.printStackTrace()
}
})
// try {
// SVGAParser.shareParser()
// .decodeFromURL(URL(vipInfo.vipLogo), object : SVGAParser.ParseCompletion {
// override fun onComplete(videoItem: SVGAVideoEntity) {
// val drawable = SVGADrawable(videoItem)
// if (isViewLoaded) {
// _binding?.ivVipIcon?.setImageDrawable(drawable)
// _binding?.ivVipIcon?.startAnimation()
// }
// }
//
// override fun onError() {
// }
// })
// } catch (e: MalformedURLException) {
//
// }
binding?.tvLevelDesc?.text = getString(R.string.level_up_wear_dress_tips_format).format(vipInfo.vipName)
}
}

View File

@@ -2,7 +2,7 @@
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<alpha
android:duration="500"
android:duration="200"
android:fromAlpha="1.0"
android:toAlpha="0" />
</set>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="100"
android:fromXDelta="-100%p"
android:toXDelta="0"/>
</set>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="100"
android:fromXDelta="100%p"
android:toXDelta="0"/>
</set>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<scale
android:duration="500"
android:fromXScale="1.3"
android:fromYScale="1.3"
android:toXScale="1"
android:toYScale="1"/>
</set>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 487 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 946 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

After

Width:  |  Height:  |  Size: 404 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 267 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 248 KiB

Some files were not shown because too many files have changed in this diff Show More