Merge branch 'v2.2.0/red_package' into v2.2.0/dev
# Conflicts: # gradle.properties
@@ -17,6 +17,7 @@ import androidx.multidex.MultiDex;
|
||||
|
||||
import com.bumptech.glide.request.target.ViewTarget;
|
||||
import com.coorchice.library.utils.LogUtils;
|
||||
import com.facebook.stetho.Stetho;
|
||||
import com.hjq.toast.ToastUtils;
|
||||
import com.mob.MobSDK;
|
||||
import com.mob.moblink.MobLink;
|
||||
@@ -64,6 +65,7 @@ import com.yizhuan.xchat_android_core.im.custom.bean.OpenSignInAttachment;
|
||||
import com.yizhuan.xchat_android_core.initial.InitialModel;
|
||||
import com.yizhuan.xchat_android_core.interceptor.NoParamsInterceptor;
|
||||
import com.yizhuan.xchat_android_core.interceptor.ParamsInterceptor;
|
||||
import com.yizhuan.xchat_android_core.interceptor.TimeSyncInterceptor;
|
||||
import com.yizhuan.xchat_android_core.manager.IMMessageManager;
|
||||
import com.yizhuan.xchat_android_core.manager.IMSystemMsgManager;
|
||||
import com.yizhuan.xchat_android_core.market_verify.MarketVerifyModel;
|
||||
@@ -252,6 +254,7 @@ public class XChatApplication extends BaseApp {
|
||||
//fixed: Glide Exception:"You must not call setTag() on a view Glide is targeting"
|
||||
ViewTarget.setTagId(R.id.tag_glide);
|
||||
|
||||
initStetho(context);
|
||||
init(channel);
|
||||
|
||||
//生命周期监听
|
||||
@@ -405,6 +408,7 @@ public class XChatApplication extends BaseApp {
|
||||
.setBaseUrl(url)
|
||||
.addInterceptors(new ParamsInterceptor(httpParams))
|
||||
.addInterceptors(new NoParamsInterceptor())//注意:拦截器的添加顺序,请求的拦截顺序
|
||||
.addInterceptors(new TimeSyncInterceptor())
|
||||
.certificates()
|
||||
.build();
|
||||
//单例的model 初始化
|
||||
@@ -543,4 +547,18 @@ public class XChatApplication extends BaseApp {
|
||||
unregisterActivityLifecycleCallbacks(lifeCycleHelper);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化Stetho(网络调试)
|
||||
*/
|
||||
private static void initStetho(Context context) {
|
||||
if (Env.isDebug()) {
|
||||
Stetho.initialize(
|
||||
Stetho.newInitializerBuilder(context)
|
||||
.enableDumpapp(Stetho.defaultDumperPluginsProvider(context))
|
||||
.enableWebKitInspector(Stetho.defaultInspectorModulesProvider(context))
|
||||
.build()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -16,6 +16,7 @@ import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUS
|
||||
import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MSG_SUB_ROOM_PK_NOTIFY;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -38,6 +39,7 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import androidx.viewpager2.widget.ViewPager2;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
@@ -65,7 +67,7 @@ import com.yizhuan.erban.avroom.fragment.HomePartyFragment;
|
||||
import com.yizhuan.erban.avroom.fragment.InputPwdDialogFragment;
|
||||
import com.yizhuan.erban.avroom.presenter.AvRoomPresenter;
|
||||
import com.yizhuan.erban.avroom.presenter.HomePartyPresenter;
|
||||
import com.yizhuan.erban.avroom.redpackage.RedPackageOpenDialog;
|
||||
import com.yizhuan.erban.avroom.redpackage.RedPackageHandler;
|
||||
import com.yizhuan.erban.avroom.view.IAvRoomView;
|
||||
import com.yizhuan.erban.avroom.widget.VerticalViewPagerAdapter;
|
||||
import com.yizhuan.erban.base.BaseMvpActivity;
|
||||
@@ -128,7 +130,6 @@ import com.yizhuan.xchat_android_core.patriarch.event.CloseMinRoomEvent;
|
||||
import com.yizhuan.xchat_android_core.patriarch.event.ImPushMsgPmLimitTimeEvent;
|
||||
import com.yizhuan.xchat_android_core.patriarch.event.PmDismissAllLimitDialogEvent;
|
||||
import com.yizhuan.xchat_android_core.patriarch.exception.PmRoomLimitException;
|
||||
import com.yizhuan.xchat_android_core.redpackage.RedPackageModel;
|
||||
import com.yizhuan.xchat_android_core.redpackage.RedPackageNotifyInfo;
|
||||
import com.yizhuan.xchat_android_core.room.anotherroompk.ShowGiftDialogEvent;
|
||||
import com.yizhuan.xchat_android_core.room.bean.RoomInfo;
|
||||
@@ -140,6 +141,8 @@ import com.yizhuan.xchat_android_core.room.event.RoomTaskTipsEvent;
|
||||
import com.yizhuan.xchat_android_core.room.pk.event.PKStateEvent;
|
||||
import com.yizhuan.xchat_android_core.super_admin.util.SAdminOptUtil;
|
||||
import com.yizhuan.xchat_android_core.super_admin.util.SuperAdminUtil;
|
||||
import com.yizhuan.xchat_android_core.support.room.RoomContext;
|
||||
import com.yizhuan.xchat_android_core.support.room.RoomView;
|
||||
import com.yizhuan.xchat_android_core.treasurefairy.FairyMsgInfoBean;
|
||||
import com.yizhuan.xchat_android_core.user.UserModel;
|
||||
import com.yizhuan.xchat_android_core.user.bean.FirstChargeInfo;
|
||||
@@ -160,10 +163,7 @@ import org.greenrobot.eventbus.ThreadMode;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@@ -180,7 +180,7 @@ import io.reactivex.disposables.Disposable;
|
||||
*/
|
||||
@CreatePresenter(AvRoomPresenter.class)
|
||||
public class AVRoomActivity extends BaseMvpActivity<IAvRoomView, AvRoomPresenter>
|
||||
implements View.OnClickListener, IAvRoomView {
|
||||
implements View.OnClickListener, IAvRoomView, RoomView {
|
||||
|
||||
public static final int FROM_TYPE_NORMAL = 0;
|
||||
public static final int FROM_TYPE_RECOMMEND = 1;
|
||||
@@ -218,7 +218,6 @@ public class AVRoomActivity extends BaseMvpActivity<IAvRoomView, AvRoomPresenter
|
||||
private RoomInfo mRoomInfo;
|
||||
private ImageView ivHeadWear;
|
||||
private MonsterDialog monsterDialog;
|
||||
private List<RedPackageOpenDialog> openDialogs;
|
||||
private ViewPager2 viewpager;
|
||||
private VerticalViewPagerAdapter mAdapter;
|
||||
/*********************************显示全服礼物***************************************/
|
||||
@@ -511,7 +510,6 @@ public class AVRoomActivity extends BaseMvpActivity<IAvRoomView, AvRoomPresenter
|
||||
if (giftList != null) {
|
||||
giftList.clear();
|
||||
}
|
||||
if (!isResume) showRedPackage(AvRoomDataManager.get().mCurrentRoomInfo);
|
||||
isResume = true;
|
||||
}
|
||||
|
||||
@@ -616,9 +614,6 @@ public class AVRoomActivity extends BaseMvpActivity<IAvRoomView, AvRoomPresenter
|
||||
case RoomEvent.MY_SELF_KICK_OUT_ROOM_BY_S_ADMIN:
|
||||
toBack(true);
|
||||
break;
|
||||
case RoomEvent.RECEIVE_RED_PACKAGE:
|
||||
showRedPackage(AvRoomDataManager.get().mCurrentRoomInfo);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
@@ -680,6 +675,17 @@ public class AVRoomActivity extends BaseMvpActivity<IAvRoomView, AvRoomPresenter
|
||||
RxBus.get().post(new ShowGiftDialogEvent().setGiftId(giftId));
|
||||
giftId = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO 临时方案:后续逐步完善整个房间的RoomContext替换计划
|
||||
* PS:目前房间进入的逻辑有些凌乱,没有明确的生命周期,看代码逻辑,无论是第一次还是再次进入都会走这里,所以在这里绑定View
|
||||
*/
|
||||
getRoomContext().onViewAttach(this);
|
||||
|
||||
/**
|
||||
* 每次View重新创建(意味着可能在房间外点了红包),就重新尝试加载红包并展示
|
||||
*/
|
||||
tryShowSourceRedPackage();
|
||||
}
|
||||
|
||||
private void showLiveFinishView(long uid) {
|
||||
@@ -716,42 +722,25 @@ public class AVRoomActivity extends BaseMvpActivity<IAvRoomView, AvRoomPresenter
|
||||
AvRoomDataManager.get().release();
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
private void showRedPackage(RoomInfo roomInfo) {
|
||||
if (roomInfo == null) return;
|
||||
RedPackageNotifyInfo inRoomNotifyInfo = (RedPackageNotifyInfo) getIntent().getSerializableExtra("notifyInfo");
|
||||
Map<String, Long> redMap = DemoCache.readRedPackage();
|
||||
RedPackageModel.INSTANCE.getRedPackage(roomInfo.getUid())
|
||||
.compose(bindToLifecycle())
|
||||
.doFinally(() -> {
|
||||
if (inRoomNotifyInfo != null && (redMap == null || !redMap.containsKey(inRoomNotifyInfo.getRedEnvelopeId()))) {
|
||||
showRedPackageOpenDialog(inRoomNotifyInfo);
|
||||
}
|
||||
})
|
||||
.filter(notifyInfo -> inRoomNotifyInfo == null || !notifyInfo.getRedEnvelopeId().equals(inRoomNotifyInfo.getRedEnvelopeId()))
|
||||
.subscribe(this::showRedPackageOpenDialog);
|
||||
}
|
||||
|
||||
private void showRedPackageOpenDialog(RedPackageNotifyInfo notifyInfo) {
|
||||
if (!isResume) return;
|
||||
if (openDialogs == null) {
|
||||
openDialogs = new ArrayList<>();
|
||||
}
|
||||
RedPackageOpenDialog openDialog = RedPackageOpenDialog.Companion.newInstance(notifyInfo);
|
||||
openDialog.show(this);
|
||||
if (openDialog.getDialog() != null) {
|
||||
openDialog.getDialog().setOnDismissListener(dialog -> openDialogs.remove(openDialog));
|
||||
}
|
||||
openDialogs.add(openDialog);
|
||||
if (openDialogs.size() >= SHOW_RED_DIALOG_MAX) {
|
||||
openDialogs.get(SHOW_RED_DIALOG_MAX - 1).dismissAllowingStateLoss();
|
||||
/**
|
||||
* 尝试展示来源红包(在房间外点击红包入口进入房间时)
|
||||
*/
|
||||
private void tryShowSourceRedPackage() {
|
||||
try {
|
||||
RedPackageNotifyInfo inRoomNotifyInfo = (RedPackageNotifyInfo) getIntent().getSerializableExtra("notifyInfo");
|
||||
if (inRoomNotifyInfo != null) {
|
||||
RedPackageHandler handler = getRoomContext().findAbility(RedPackageHandler.class.getSimpleName());
|
||||
if (handler != null) {
|
||||
long id = Long.parseLong(inRoomNotifyInfo.getRedEnvelopeId());
|
||||
handler.tryShowRedPackage(id);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void dismissRedPackageDialog() {
|
||||
if (openDialogs != null) {
|
||||
openDialogs.clear();
|
||||
}
|
||||
if (mCurrentFragment != null) {
|
||||
mCurrentFragment.dismissSendRedPackageDialog();
|
||||
}
|
||||
@@ -1076,7 +1065,6 @@ public class AVRoomActivity extends BaseMvpActivity<IAvRoomView, AvRoomPresenter
|
||||
DemoCache.readNewUserChargeGift() == 0) {
|
||||
DemoCache.saveNewUserChargeGift(1);
|
||||
}
|
||||
showRedPackage(AvRoomDataManager.get().mCurrentRoomInfo);
|
||||
dismissLoadingDialog();
|
||||
}
|
||||
|
||||
@@ -1401,6 +1389,24 @@ public class AVRoomActivity extends BaseMvpActivity<IAvRoomView, AvRoomPresenter
|
||||
getLimitEnterRoomHelper().handleThisContext(this, event.getData(), true, this::handlePmExitRoom);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Activity getActivity() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public RoomContext getRoomContext() {
|
||||
return RoomContext.Companion.get();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public LifecycleOwner getLifecycleOwner() {
|
||||
return this;
|
||||
}
|
||||
|
||||
private static class GiftBroadcastObserver implements Observer<BroadcastMessage> {
|
||||
private WeakReference<AVRoomActivity> mReference;
|
||||
|
||||
@@ -1433,5 +1439,4 @@ public class AVRoomActivity extends BaseMvpActivity<IAvRoomView, AvRoomPresenter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,19 @@
|
||||
package com.yizhuan.erban.avroom.core
|
||||
|
||||
import com.yizhuan.erban.avroom.redpackage.RedPackageHandler
|
||||
import com.yizhuan.xchat_android_core.support.room.RoomAbility
|
||||
import com.yizhuan.xchat_android_core.support.room.RoomContext
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/10/26 15:41
|
||||
* Desc:语音房
|
||||
* @param roomId roomUid
|
||||
**/
|
||||
class AudioRoomContext(roomId: Long) : RoomContext(roomId) {
|
||||
|
||||
override fun loadAbility(list: MutableMap<String, RoomAbility>) {
|
||||
super.loadAbility(list)
|
||||
// 红包处理器
|
||||
list[RedPackageHandler::class.java.simpleName] = RedPackageHandler()
|
||||
}
|
||||
}
|
@@ -352,7 +352,6 @@ public class RoomOperationDialog extends BottomSheetDialog {
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -21,6 +21,9 @@ import android.widget.RelativeLayout
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.CallSuper
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.lifecycle.withResumed
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.chad.library.adapter.base.BaseQuickAdapter
|
||||
@@ -46,7 +49,7 @@ import com.yizhuan.erban.avroom.dialog.RoomFreeGiftDialog
|
||||
import com.yizhuan.erban.avroom.dialog.RoomOperationDialog
|
||||
import com.yizhuan.erban.avroom.firstcharge.FirstChargeDialog
|
||||
import com.yizhuan.erban.avroom.presenter.BaseRoomPresenter
|
||||
import com.yizhuan.erban.avroom.redpackage.RedPackageSendDialog
|
||||
import com.yizhuan.erban.avroom.redpackage.send.RedPackageSendDialog2
|
||||
import com.yizhuan.erban.avroom.room_album.RoomAlbumModel
|
||||
import com.yizhuan.erban.avroom.view.IBaseRoomView
|
||||
import com.yizhuan.erban.avroom.widget.BottomView
|
||||
@@ -84,6 +87,7 @@ import com.yizhuan.xchat_android_core.gift.bean.GiftInfo
|
||||
import com.yizhuan.xchat_android_core.gift.event.RoomFreeGiftEvent
|
||||
import com.yizhuan.xchat_android_core.helper.AtProxy
|
||||
import com.yizhuan.xchat_android_core.home.bean.BannerInfo
|
||||
import com.yizhuan.xchat_android_core.home.event.OpenRoomMessageInputEvent
|
||||
import com.yizhuan.xchat_android_core.im.custom.bean.RoomFollowOwnerAttachment
|
||||
import com.yizhuan.xchat_android_core.im.custom.bean.RoomFollowOwnerAttachment2
|
||||
import com.yizhuan.xchat_android_core.manager.AudioEngineManager
|
||||
@@ -104,6 +108,8 @@ import com.yizhuan.xchat_android_core.share.bean.SessionType
|
||||
import com.yizhuan.xchat_android_core.super_admin.SaConstant
|
||||
import com.yizhuan.xchat_android_core.super_admin.model.SuperAdminModel
|
||||
import com.yizhuan.xchat_android_core.super_admin.util.SuperAdminUtil
|
||||
import com.yizhuan.xchat_android_core.support.room.RoomView
|
||||
import com.yizhuan.xchat_android_core.support.room.RoomWidget
|
||||
import com.yizhuan.xchat_android_core.user.UserModel
|
||||
import com.yizhuan.xchat_android_core.user.bean.BaseInfo
|
||||
import com.yizhuan.xchat_android_core.user.bean.UserInfo
|
||||
@@ -116,6 +122,7 @@ import com.yizhuan.xchat_android_library.rxbus.RxBus
|
||||
import com.yizhuan.xchat_android_library.utils.*
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.Disposable
|
||||
import kotlinx.coroutines.launch
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode
|
||||
@@ -130,7 +137,8 @@ import org.greenrobot.eventbus.ThreadMode
|
||||
*/
|
||||
open class BaseRoomFragment<V : IBaseRoomView?, P : BaseRoomPresenter<V>?> :
|
||||
BaseMvpFragment<V?, P?>(),
|
||||
View.OnClickListener, OnGiftDialogBtnClickListener, IBaseRoomView, OnMicroItemClickListener {
|
||||
View.OnClickListener, OnGiftDialogBtnClickListener, IBaseRoomView, OnMicroItemClickListener,
|
||||
RoomView {
|
||||
private var myUid: Long = 0
|
||||
protected lateinit var messageView: MessageView
|
||||
protected lateinit var bottomView: BottomView
|
||||
@@ -162,7 +170,7 @@ open class BaseRoomFragment<V : IBaseRoomView?, P : BaseRoomPresenter<V>?> :
|
||||
* 是否開啟禮物值顯示
|
||||
*/
|
||||
private var showGiftValue = false
|
||||
private var redPackageSendDialog: RedPackageSendDialog? = null
|
||||
private var redPackageSendDialog: RedPackageSendDialog2? = null
|
||||
private val mOnSoftKeyBoardChangeListener: OnSoftKeyBoardChangeListener =
|
||||
object : OnSoftKeyBoardChangeListener {
|
||||
override fun keyBoardShow(height: Int) {
|
||||
@@ -179,6 +187,8 @@ open class BaseRoomFragment<V : IBaseRoomView?, P : BaseRoomPresenter<V>?> :
|
||||
|
||||
private var atProxy: AtProxy? = null
|
||||
|
||||
// 房间小组件
|
||||
private var widgets: HashMap<String, RoomWidget> = HashMap()
|
||||
|
||||
@CallSuper
|
||||
override fun onFindViews() {
|
||||
@@ -238,6 +248,7 @@ open class BaseRoomFragment<V : IBaseRoomView?, P : BaseRoomPresenter<V>?> :
|
||||
@SuppressLint("CheckResult")
|
||||
@CallSuper
|
||||
override fun initiate() {
|
||||
initWidget()
|
||||
//如果不需要開麥,並且還沒有權限的情況下,重置狀態為需要去打開麥克風
|
||||
myUid = AuthModel.get().currentUid
|
||||
isCloseScreen = AvRoomDataManager.get().isCloseScreen
|
||||
@@ -637,6 +648,7 @@ open class BaseRoomFragment<V : IBaseRoomView?, P : BaseRoomPresenter<V>?> :
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
releaseView()
|
||||
unregisterWidgets()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
@@ -1273,10 +1285,7 @@ open class BaseRoomFragment<V : IBaseRoomView?, P : BaseRoomPresenter<V>?> :
|
||||
}
|
||||
|
||||
override fun onSendMsgBtnClick() {
|
||||
inputLayout.visibility = View.VISIBLE
|
||||
inputEdit.isFocusableInTouchMode = true
|
||||
inputEdit.requestFocus()
|
||||
KeyBoardUtils.showKeyBoard(context, inputEdit)
|
||||
openMessageInput(null)
|
||||
}
|
||||
|
||||
override fun onSendGiftBtnClick() {
|
||||
@@ -1292,7 +1301,10 @@ open class BaseRoomFragment<V : IBaseRoomView?, P : BaseRoomPresenter<V>?> :
|
||||
override fun onMoreBtnClick() {
|
||||
val dialog = RoomOperationDialog(mContext)
|
||||
dialog.setOnActionListener {
|
||||
redPackageSendDialog = RedPackageSendDialog()
|
||||
redPackageSendDialog = RedPackageSendDialog2()
|
||||
redPackageSendDialog?.setOnDismissListener {
|
||||
redPackageSendDialog = null
|
||||
}
|
||||
redPackageSendDialog?.show(activity)
|
||||
}
|
||||
dialog.show()
|
||||
@@ -1302,4 +1314,55 @@ open class BaseRoomFragment<V : IBaseRoomView?, P : BaseRoomPresenter<V>?> :
|
||||
RoomMsgActivity.start(mContext)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册组件
|
||||
*/
|
||||
protected fun registerWidget(name: String, widget: RoomWidget) {
|
||||
widgets.put(name, widget)
|
||||
widget.onStart(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消注册组件
|
||||
*/
|
||||
protected fun unregisterWidgets() {
|
||||
widgets.values.forEach {
|
||||
it.onStop()
|
||||
}
|
||||
widgets.clear()
|
||||
}
|
||||
|
||||
override fun getLifecycleOwner(): LifecycleOwner {
|
||||
return this
|
||||
}
|
||||
|
||||
open fun initWidget() {
|
||||
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
open fun onOpenRoomMessageInputEvent(event: OpenRoomMessageInputEvent) {
|
||||
lifecycleScope.launch {
|
||||
lifecycle.withResumed {
|
||||
view?.postDelayed({
|
||||
openMessageInput(event.text)
|
||||
}, 500)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开公屏输入
|
||||
*/
|
||||
fun openMessageInput(text: String?) {
|
||||
inputLayout.visibility = View.VISIBLE
|
||||
if (text != null) {
|
||||
inputEdit.setText(text)
|
||||
inputEdit.setSelection(inputEdit.length())
|
||||
}
|
||||
inputEdit.isFocusableInTouchMode = true
|
||||
inputEdit.requestFocus()
|
||||
KeyBoardUtils.showKeyBoard(context, inputEdit)
|
||||
}
|
||||
}
|
@@ -26,6 +26,7 @@ import com.yizhuan.erban.avroom.dialog.PKScoreBoardDialog;
|
||||
import com.yizhuan.erban.avroom.firstcharge.FirstChargePrizeDialog;
|
||||
import com.yizhuan.erban.avroom.giftvalue.GiftValueDialogUiHelper;
|
||||
import com.yizhuan.erban.avroom.presenter.HomePartyPresenter;
|
||||
import com.yizhuan.erban.avroom.redpackage.RedPackageWidget;
|
||||
import com.yizhuan.erban.avroom.view.IHomePartyView;
|
||||
import com.yizhuan.erban.avroom.widget.PKBoardView;
|
||||
import com.yizhuan.erban.base.BaseMvpActivity;
|
||||
@@ -133,6 +134,12 @@ public class HomePartyRoomFragment extends BaseRoomFragment<IHomePartyView, Home
|
||||
bottomView.setBottomViewListener(new PartyRoomBottomViewWrapper());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initWidget() {
|
||||
super.initWidget();
|
||||
registerWidget(RedPackageWidget.class.getSimpleName(), gameBinding.redPackageWidget);
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
@Override
|
||||
public void initiate() {
|
||||
@@ -526,6 +533,11 @@ public class HomePartyRoomFragment extends BaseRoomFragment<IHomePartyView, Home
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
gameBinding.redPackageWidget.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
@@ -808,7 +820,6 @@ public class HomePartyRoomFragment extends BaseRoomFragment<IHomePartyView, Home
|
||||
} else {
|
||||
gameBinding.ivTreasureBoxCp.setVisibility(View.GONE);
|
||||
gameBinding.ivTreasureBox.setVisibility(View.VISIBLE);
|
||||
|
||||
GlideApp.with(BasicConfig.INSTANCE.getAppContext())
|
||||
.load(GoldBoxHelper.getBoxIcon())
|
||||
.error(R.drawable.icon_room_treasure_box)
|
||||
|
@@ -261,5 +261,4 @@ class SingleRoomFragment : BaseRoomFragment<ISingleRoomView?, SingleRoomPresente
|
||||
event.firstChargeRewardList
|
||||
).openDialog()
|
||||
}
|
||||
|
||||
}
|
@@ -20,6 +20,8 @@ import com.netease.nimlib.sdk.chatroom.model.EnterChatRoomResultData;
|
||||
import com.netease.nimlib.sdk.util.Entry;
|
||||
import com.yizhuan.erban.R;
|
||||
import com.yizhuan.erban.avroom.activity.AVRoomActivity;
|
||||
import com.yizhuan.erban.avroom.core.AudioRoomContext;
|
||||
import com.yizhuan.xchat_android_core.support.room.RoomContext;
|
||||
import com.yizhuan.erban.avroom.view.IAvRoomView;
|
||||
import com.yizhuan.erban.base.BaseMvpPresenter;
|
||||
import com.yizhuan.xchat_android_core.Constants;
|
||||
@@ -128,6 +130,8 @@ public class AvRoomPresenter extends BaseMvpPresenter<IAvRoomView> {
|
||||
.subscribe(roomQueueInfoSparseArray -> {
|
||||
long uid = AuthModel.get().getCurrentUid();
|
||||
AudioEngineManager.get().startRtcEngine(uid, roomInfo.getAudioSdkType());
|
||||
// TODO 临时方案:后续逐步完善整个房间的RoomContext替换计划
|
||||
new AudioRoomContext(roomInfo.getUid()).run();
|
||||
if (getMvpView() != null) {
|
||||
getMvpView().enterRoomSuccess();
|
||||
}
|
||||
|
@@ -0,0 +1,125 @@
|
||||
package com.yizhuan.erban.avroom.redpackage
|
||||
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.yizhuan.erban.avroom.redpackage.open.RedPackageOpenDialog2
|
||||
import com.yizhuan.xchat_android_core.im.custom.bean.RedPackageAttachment
|
||||
import com.yizhuan.xchat_android_core.manager.IMNetEaseManager
|
||||
import com.yizhuan.xchat_android_core.manager.RoomEvent
|
||||
import com.yizhuan.xchat_android_core.redpackage.RedPackageModel
|
||||
import com.yizhuan.xchat_android_core.redpackage.RedPackageNotifyInfo
|
||||
import com.yizhuan.xchat_android_core.support.room.RoomContext
|
||||
import com.yizhuan.xchat_android_core.support.room.RoomHandler
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/10/26 11:26
|
||||
* Desc:红包处理器
|
||||
**/
|
||||
class RedPackageHandler : RoomHandler() {
|
||||
|
||||
// 入口图标-数据
|
||||
val iconLiveData: MutableLiveData<RedPackageNotifyInfo?> = MutableLiveData()
|
||||
|
||||
override fun onStart(context: RoomContext) {
|
||||
super.onStart(context)
|
||||
registerSignaling()
|
||||
}
|
||||
|
||||
override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
|
||||
super.onStateChanged(source, event)
|
||||
if (event == Lifecycle.Event.ON_RESUME) {
|
||||
requestLatestRoomRedPackage()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 尝试展示红包
|
||||
* PS:目前这个方法仅为了解决:通过房间外的红包入口进入房间后,需要查询该红包,展示出来。
|
||||
*/
|
||||
fun tryShowRedPackage(redPackageId: Long) {
|
||||
val disposable = RedPackageModel.getRedPackage(redPackageId)
|
||||
.compose(bindToLifecycle())
|
||||
.subscribe({ item ->
|
||||
if (item.state != 3 && item.state != 6 && item.state != 4) {
|
||||
roomView?.getActivity().let {
|
||||
RedPackageOpenDialog2.newInstance(item).show(it)
|
||||
}
|
||||
}
|
||||
}, {})
|
||||
}
|
||||
|
||||
/**
|
||||
* 监听房间信令
|
||||
*/
|
||||
private fun registerSignaling() {
|
||||
// TODO 临时方案:不应在这里直接监听IM,后续会统一分发出口
|
||||
// 信令来源:新/旧版的厅内红包,非全服红包
|
||||
IMNetEaseManager.get().chatRoomEventObservable
|
||||
.compose<RoomEvent>(bindToLifecycle<RoomEvent>())
|
||||
.filter {
|
||||
it?.event == RoomEvent.RECEIVE_RED_PACKAGE && it?.chatRoomMessage?.attachment is RedPackageAttachment
|
||||
}.map {
|
||||
(it.chatRoomMessage.attachment as RedPackageAttachment).getRedPackageNotifyInfo()
|
||||
}
|
||||
.subscribe { data: RedPackageNotifyInfo ->
|
||||
handleRoomRedPackage(data, true)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找最新的厅内红包(新/旧版的厅内红包,非全服红包)
|
||||
*/
|
||||
private fun requestLatestRoomRedPackage() {
|
||||
logD("requestLatestRoomRedPackage()")
|
||||
val roomId = roomContext?.roomId ?: return
|
||||
logD("requestLatestRoomRedPackage() roomId:$roomId")
|
||||
RedPackageModel.getLatestRoomRedPackage(roomId)
|
||||
.compose(bindToLifecycle())
|
||||
.subscribe({ data ->
|
||||
logD("requestLatestRoomRedPackage() data:$data")
|
||||
handleRoomRedPackage(data, false)
|
||||
}, {})
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理厅内红包,非全服红包
|
||||
* @param isSignaling 是否来自信令?
|
||||
*/
|
||||
private fun handleRoomRedPackage(data: RedPackageNotifyInfo, isSignaling: Boolean) {
|
||||
tryShowOpenDialog(data, isSignaling)
|
||||
updateIcon(data)
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新红包入口图标
|
||||
*/
|
||||
private fun updateIcon(data: RedPackageNotifyInfo?) {
|
||||
iconLiveData.postValue(data)
|
||||
}
|
||||
|
||||
/**
|
||||
* 尝试展示红包领取弹窗
|
||||
*/
|
||||
private fun tryShowOpenDialog(data: RedPackageNotifyInfo, isSignaling: Boolean) {
|
||||
val activity = roomView?.getActivity() ?: return
|
||||
if (activity.isFinishing) {
|
||||
return
|
||||
}
|
||||
if (!isSignaling) {
|
||||
return
|
||||
}
|
||||
if (data.kind == 0 || (data.kind == 1 && data.validityType == 0)) {
|
||||
//【旧版本-厅内红包:kind=0】、【新版本-厅内无门槛-立即生效红包:kind=1&validityType=0】
|
||||
RedPackageOpenDialog2.newInstance(data).show(activity)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求刷新Icon(数据已过期)
|
||||
*/
|
||||
fun requestRefreshIcon() {
|
||||
// updateIcon(null)
|
||||
requestLatestRoomRedPackage()
|
||||
}
|
||||
}
|
@@ -77,18 +77,17 @@ class RedPackageOpenDialog : BaseDialog<DialogRedPackageOpenBinding>() {
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
private fun startRedPacketAnim(v: View) {
|
||||
RedPackageModel.openRedPackage(redPackageNotifyInfo.redEnvelopeId)
|
||||
RedPackageModel.openRedPackage(redPackageNotifyInfo.redEnvelopeId.toLong())
|
||||
.subscribe({
|
||||
redPackageInfo = it
|
||||
if (mObjectAnimator?.isRunning == false) {
|
||||
openRedPackage()
|
||||
}
|
||||
}
|
||||
, {
|
||||
binding?.ivOpen?.isEnabled = true
|
||||
mObjectAnimator?.cancel()
|
||||
SingleToastUtil.showToast(it.message)
|
||||
})
|
||||
}, {
|
||||
binding?.ivOpen?.isEnabled = true
|
||||
mObjectAnimator?.cancel()
|
||||
SingleToastUtil.showToast(it.message)
|
||||
})
|
||||
|
||||
mObjectAnimator = ObjectAnimator.ofFloat(v, "rotationY", 0f, 360f)
|
||||
mObjectAnimator?.let {
|
||||
@@ -120,31 +119,45 @@ class RedPackageOpenDialog : BaseDialog<DialogRedPackageOpenBinding>() {
|
||||
binding?.clOpened?.visibility = View.VISIBLE
|
||||
binding?.clRed?.visibility = View.GONE
|
||||
binding?.tvNicknameOpened?.text = redPackageNotifyInfo.sendUserNick
|
||||
ImageLoadUtils.loadAvatar(context, redPackageNotifyInfo.sendUserAvatar, binding?.ivAvatarOpened)
|
||||
ImageLoadUtils.loadAvatar(
|
||||
context,
|
||||
redPackageNotifyInfo.sendUserAvatar,
|
||||
binding?.ivAvatarOpened
|
||||
)
|
||||
packageInfo.redEnvelopeVO?.apply {
|
||||
binding?.tvContentOpened?.text = message
|
||||
when (packageInfo.redEnvelopeState) {
|
||||
SUCCESS -> {
|
||||
packageInfo.redEnvelopeItemVOs?.firstOrNull { item -> item.userVO.uid == UserUtils.getUserUid() }?.let {
|
||||
it.redEnvelopeGiftItemVOs?.apply {
|
||||
if (!isEmpty()) {
|
||||
val adapter = RedPackageGiftAdapter(R.layout.item_red_package_gift_top)
|
||||
binding?.rvGift?.visibility = View.VISIBLE
|
||||
binding?.tvDiamondNum?.visibility = View.GONE
|
||||
binding?.rvGift?.layoutManager = LinearLayoutManager(context, RecyclerView.HORIZONTAL, false)
|
||||
binding?.rvGift?.adapter = adapter
|
||||
adapter.setNewData(this)
|
||||
binding?.tvTips?.setTextColor(Color.WHITE)
|
||||
binding?.tvTips?.text = MessageView.SpannableBuilder(binding?.tvTips)
|
||||
.append(ResUtil.getString(R.string.avroom_redpackage_redpackageopendialog_03))
|
||||
.append(it.amount, ForegroundColorSpan(Color.parseColor("#FDCD00")))
|
||||
.append(ResUtil.getString(R.string.avroom_redpackage_redpackageopendialog_04))
|
||||
.build()
|
||||
packageInfo.redEnvelopeItemVOs?.firstOrNull { item -> item.userVO.uid == UserUtils.getUserUid() }
|
||||
?.let {
|
||||
it.redEnvelopeGiftItemVOs?.apply {
|
||||
if (!isEmpty()) {
|
||||
val adapter =
|
||||
RedPackageGiftAdapter(R.layout.item_red_package_gift_top)
|
||||
binding?.rvGift?.visibility = View.VISIBLE
|
||||
binding?.tvDiamondNum?.visibility = View.GONE
|
||||
binding?.rvGift?.layoutManager = LinearLayoutManager(
|
||||
context,
|
||||
RecyclerView.HORIZONTAL,
|
||||
false
|
||||
)
|
||||
binding?.rvGift?.adapter = adapter
|
||||
adapter.setNewData(this)
|
||||
binding?.tvTips?.setTextColor(Color.WHITE)
|
||||
binding?.tvTips?.text =
|
||||
MessageView.SpannableBuilder(binding?.tvTips)
|
||||
.append(ResUtil.getString(R.string.avroom_redpackage_redpackageopendialog_03))
|
||||
.append(
|
||||
it.amount,
|
||||
ForegroundColorSpan(Color.parseColor("#FDCD00"))
|
||||
)
|
||||
.append(ResUtil.getString(R.string.avroom_redpackage_redpackageopendialog_04))
|
||||
.build()
|
||||
}
|
||||
}
|
||||
binding?.tvDiamondNum?.text = it.amount.substringBefore(".")
|
||||
}
|
||||
binding?.tvDiamondNum?.text = it.amount.substringBefore(".")
|
||||
}
|
||||
if (!AvRoomDataManager.get().isRoomFans){
|
||||
if (!AvRoomDataManager.get().isRoomFans) {
|
||||
AvRoomDataManager.get().roomUid.let {
|
||||
CollectionRoomModel.get().followRoom("1", it)
|
||||
.subscribe { _: String? ->
|
||||
@@ -154,6 +167,7 @@ class RedPackageOpenDialog : BaseDialog<DialogRedPackageOpenBinding>() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TIME_OUT, REMAIN_ZERO, TIME_OUT_BACK -> {
|
||||
binding?.clOpened?.setBackgroundResource(R.drawable.room_red_package_get_bg)
|
||||
binding?.tvDiamondNum?.visibility = View.GONE
|
||||
|
@@ -28,6 +28,7 @@ import com.yizhuan.xchat_android_core.pay.PayModel
|
||||
import com.yizhuan.xchat_android_core.pay.event.UpdateWalletInfoEvent
|
||||
import com.yizhuan.xchat_android_core.redpackage.*
|
||||
import com.yizhuan.xchat_android_core.user.UserModel
|
||||
import com.yizhuan.xchat_android_core.utils.LogUtils
|
||||
import com.yizhuan.xchat_android_core.utils.toIntOrDef
|
||||
import com.yizhuan.xchat_android_library.annatation.ActLayoutRes
|
||||
import com.yizhuan.xchat_android_library.common.util.DeviceUtil
|
||||
@@ -219,23 +220,24 @@ class RedPackageSendDialog : BaseDialog<DialogRedPackageSendBinding>(), GridPass
|
||||
override fun onTextChanged(psw: String) {
|
||||
val password = passWordFragment?.password?.password ?: ""
|
||||
if (password.length == 6) {
|
||||
dialogManager.showProgressDialog(context)
|
||||
RedPackageModel.sendRedPackage(binding?.editGoldNum?.text.toString(),
|
||||
binding?.editRedText?.text.toString().ifEmpty { "恭喜發財,大吉大利!" },
|
||||
binding?.editRedNum?.text.toString(),
|
||||
AvRoomDataManager.get().mCurrentRoomInfo?.uid.toString(), getRedType(), DESUtils.DESAndBase64(password))
|
||||
.doOnError {
|
||||
dialogManager.dismissDialog()
|
||||
SingleToastUtil.showToast(it.message)
|
||||
passWordFragment?.password?.clearPassword()
|
||||
}
|
||||
.subscribe { _ ->
|
||||
PayModel.get().getWalletInfo(AuthModel.get().currentUid).subscribe()
|
||||
dialogManager.dismissDialog()
|
||||
SingleToastUtil.showToast("發送成功")
|
||||
passWordFragment?.dismissAllowingStateLoss()
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
LogUtils.d("onTextChanged() editGoldNum:${binding?.editGoldNum?.text.toString()} NUM:${binding?.editRedNum?.text.toString()}")
|
||||
// dialogManager.showProgressDialog(context)
|
||||
// RedPackageModel.sendRedPackage(binding?.editGoldNum?.text.toString(),
|
||||
// binding?.editRedText?.text.toString().ifEmpty { "恭喜發財,大吉大利!" },
|
||||
// binding?.editRedNum?.text.toString(),
|
||||
// AvRoomDataManager.get().mCurrentRoomInfo?.uid.toString(), getRedType(), DESUtils.DESAndBase64(password))
|
||||
// .doOnError {
|
||||
// dialogManager.dismissDialog()
|
||||
// SingleToastUtil.showToast(it.message)
|
||||
// passWordFragment?.password?.clearPassword()
|
||||
// }
|
||||
// .subscribe { _ ->
|
||||
// PayModel.get().getWalletInfo(AuthModel.get().currentUid).subscribe()
|
||||
// dialogManager.dismissDialog()
|
||||
// SingleToastUtil.showToast("發送成功")
|
||||
// passWordFragment?.dismissAllowingStateLoss()
|
||||
// dismissAllowingStateLoss()
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -0,0 +1,243 @@
|
||||
package com.yizhuan.erban.avroom.redpackage
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.util.TypedValue
|
||||
import android.view.LayoutInflater
|
||||
import android.widget.TextView
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.lifecycle.Observer
|
||||
import com.chuhai.utils.ServiceTime
|
||||
import com.chuhai.utils.ktx.singleClick
|
||||
import com.yizhuan.erban.R
|
||||
import com.yizhuan.erban.avroom.redpackage.open.RedPackageOpenDialog2
|
||||
import com.yizhuan.erban.common.widget.dialog.DialogManager
|
||||
import com.yizhuan.xchat_android_core.redpackage.RedPackageModel
|
||||
import com.yizhuan.xchat_android_core.redpackage.RedPackageNotifyInfo
|
||||
import com.yizhuan.xchat_android_core.support.room.RoomContext
|
||||
import com.yizhuan.xchat_android_core.support.room.RoomView
|
||||
import com.yizhuan.xchat_android_core.support.room.RoomWidget
|
||||
import com.yizhuan.xchat_android_library.utils.SingleToastUtil
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import io.reactivex.disposables.Disposable
|
||||
import okhttp3.internal.toLongOrDefault
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.TimeZone
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/10/24 16:37
|
||||
* Desc:房间内的红包入口
|
||||
**/
|
||||
class RedPackageWidget : ConstraintLayout, RoomWidget {
|
||||
private var roomView: RoomView? = null
|
||||
private var textView: TextView? = null
|
||||
private var numView: TextView? = null
|
||||
private var countDownDisposable: Disposable? = null
|
||||
private var data: RedPackageNotifyInfo? = null
|
||||
private val redPackageHandler: RedPackageHandler?
|
||||
get() = RoomContext.get()
|
||||
?.findAbility<RedPackageHandler>(RedPackageHandler::class.java.simpleName)
|
||||
|
||||
// 临时这样实现,后续优化进度弹窗
|
||||
private var dialogManager: DialogManager? = null
|
||||
|
||||
// 倒计时格式(分:秒)
|
||||
private val mmssFormat by lazy(LazyThreadSafetyMode.NONE) {
|
||||
SimpleDateFormat("mm:ss").apply {
|
||||
timeZone = TimeZone.getTimeZone("GMT+00:00")
|
||||
}
|
||||
}
|
||||
|
||||
// 为了获取到RoomContext
|
||||
private val contextObserver = object : Observer<RoomContext?> {
|
||||
override fun onChanged(value: RoomContext?) {
|
||||
if (value != null) {
|
||||
RoomContext.contextLiveData.removeObserver(this)
|
||||
val view = this@RedPackageWidget.roomView
|
||||
if (view != null) {
|
||||
init(view)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val compositeDisposable = CompositeDisposable()
|
||||
|
||||
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 {
|
||||
// 默认不可见
|
||||
this.isVisible = false
|
||||
LayoutInflater.from(context)
|
||||
.inflate(R.layout.red_package_widget, this, true)
|
||||
textView = findViewById(R.id.tv_text)
|
||||
numView = findViewById(R.id.tv_num)
|
||||
this.setBackgroundResource(R.drawable.red_package_widget_bg)
|
||||
singleClick {
|
||||
data?.let {
|
||||
tryShowRedPackage(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始倒计时
|
||||
* @param time 开抢时间
|
||||
*/
|
||||
private fun startCountDown(time: Long) {
|
||||
val count = time - ServiceTime.time
|
||||
if (count <= 0) {
|
||||
switchUI(false)
|
||||
return
|
||||
}
|
||||
countDownDisposable =
|
||||
Observable.intervalRange(0, count / 1000, 0, 1000L, TimeUnit.MILLISECONDS)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.doOnNext {
|
||||
val gap = time - ServiceTime.time
|
||||
if (gap >= 0) {
|
||||
textView?.text = mmssFormat.format(gap)
|
||||
}
|
||||
}
|
||||
.doOnComplete {
|
||||
switchUI(false)
|
||||
}
|
||||
.subscribe()
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换UI
|
||||
* @param isCountDown 是否倒计时模式?否则为可抢红包模式
|
||||
*/
|
||||
private fun switchUI(isCountDown: Boolean) {
|
||||
if (isCountDown) {
|
||||
textView?.setBackgroundResource(R.drawable.shape_99292929_8)
|
||||
textView?.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 10f)
|
||||
} else {
|
||||
textView?.setBackgroundResource(R.drawable.red_package_widget_bg_text)
|
||||
textView?.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 9f)
|
||||
textView?.setText(R.string.red_package_widget_get)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStart(roomView: RoomView) {
|
||||
this.roomView = roomView
|
||||
roomView.getActivity()?.let {
|
||||
this.dialogManager = DialogManager(it)
|
||||
this.dialogManager?.setCanceledOnClickOutside(false)
|
||||
}
|
||||
// TODO #临时方案 因为目前View的生命周期比RoomContext还早,暂时这样拿到Context
|
||||
val context = RoomContext.contextLiveData.value
|
||||
if (context == null) {
|
||||
RoomContext.contextLiveData.observeForever(contextObserver)
|
||||
} else {
|
||||
init(roomView)
|
||||
}
|
||||
}
|
||||
|
||||
private fun init(roomView: RoomView) {
|
||||
val lifecycleOwner = roomView.getLifecycleOwner()
|
||||
redPackageHandler?.iconLiveData?.observe(lifecycleOwner) {
|
||||
loadData(it)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新数据
|
||||
*/
|
||||
private fun loadData(data: RedPackageNotifyInfo?) {
|
||||
logD("loadData() data:$data")
|
||||
this.data = data
|
||||
stopCountDown()
|
||||
if (data != null) {
|
||||
val num = data.redEnvelopeNum
|
||||
if (num > 0) {
|
||||
if (num > 99) {
|
||||
numView?.text = "99+"
|
||||
} else {
|
||||
numView?.text = num.toString()
|
||||
}
|
||||
numView?.isVisible = true
|
||||
} else {
|
||||
numView?.isVisible = false
|
||||
}
|
||||
if (data.validityType == 1) {
|
||||
// 限时生效
|
||||
switchUI(true)
|
||||
startCountDown(data.beginTime)
|
||||
} else {
|
||||
// 立即生效
|
||||
switchUI(false)
|
||||
}
|
||||
this.isVisible = true
|
||||
} else {
|
||||
this.isVisible = false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 尝试展示红包
|
||||
*/
|
||||
private fun tryShowRedPackage(data: RedPackageNotifyInfo) {
|
||||
dialogManager?.context?.let {
|
||||
dialogManager?.showProgressDialog(it, false)
|
||||
}
|
||||
val disposable = RedPackageModel.getRedPackage(data.redEnvelopeId.toLongOrDefault(0))
|
||||
.subscribe({ item ->
|
||||
dialogManager?.dismissDialog()
|
||||
when (item.state) {
|
||||
3 -> {
|
||||
redPackageHandler?.requestRefreshIcon()
|
||||
SingleToastUtil.showToast(R.string.red_package_result_empty_tips)
|
||||
}
|
||||
|
||||
6 -> {
|
||||
redPackageHandler?.requestRefreshIcon()
|
||||
SingleToastUtil.showToast(R.string.red_package_disabled_tips)
|
||||
}
|
||||
|
||||
else -> {
|
||||
roomView?.getActivity().let {
|
||||
RedPackageOpenDialog2.newInstance(item).show(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}, {
|
||||
SingleToastUtil.showToast(it.message)
|
||||
dialogManager?.dismissDialog()
|
||||
})
|
||||
compositeDisposable.add(disposable)
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
compositeDisposable.dispose()
|
||||
RoomContext.contextLiveData.removeObserver(contextObserver)
|
||||
stopCountDown()
|
||||
this.dialogManager?.dismissDialog()
|
||||
this.dialogManager = null
|
||||
this.roomView = null
|
||||
}
|
||||
|
||||
private fun stopCountDown() {
|
||||
if (countDownDisposable?.isDisposed == false) {
|
||||
countDownDisposable?.dispose()
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,502 @@
|
||||
package com.yizhuan.erban.avroom.redpackage.open
|
||||
|
||||
|
||||
import android.animation.Animator
|
||||
import android.animation.AnimatorListenerAdapter
|
||||
import android.animation.ObjectAnimator
|
||||
import android.animation.ValueAnimator
|
||||
import android.annotation.SuppressLint
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.WindowManager
|
||||
import android.view.animation.AccelerateDecelerateInterpolator
|
||||
import androidx.core.view.isVisible
|
||||
import com.chuhai.utils.ServiceTime
|
||||
import com.chuhai.utils.ktx.getColorById
|
||||
import com.chuhai.utils.ktx.singleClick
|
||||
import com.chuhai.utils.ktx.toStringRes
|
||||
import com.chuhai.utils.log.ILog
|
||||
import com.chuhai.utils.spannable.spannableBuilder
|
||||
import com.trello.rxlifecycle3.android.FragmentEvent
|
||||
import com.yizhuan.erban.R
|
||||
import com.yizhuan.erban.base.BaseDialog
|
||||
import com.yizhuan.erban.databinding.RedPackageOpenDialogBinding
|
||||
import com.yizhuan.erban.ui.utils.loadAvatar
|
||||
import com.yizhuan.erban.ui.widget.UserInfoDialog
|
||||
import com.yizhuan.xchat_android_core.auth.AuthModel
|
||||
import com.yizhuan.xchat_android_core.home.event.FollowRoomEvent
|
||||
import com.yizhuan.xchat_android_core.home.event.OpenRoomMessageInputEvent
|
||||
import com.yizhuan.xchat_android_core.home.event.ShareRoomEvent
|
||||
import com.yizhuan.xchat_android_core.home.model.CollectionRoomModel
|
||||
import com.yizhuan.xchat_android_core.manager.AvRoomDataManager
|
||||
import com.yizhuan.xchat_android_core.pay.PayModel
|
||||
import com.yizhuan.xchat_android_core.redpackage.*
|
||||
import com.yizhuan.xchat_android_core.support.config.Constants
|
||||
import com.yizhuan.xchat_android_library.annatation.ActLayoutRes
|
||||
import com.yizhuan.xchat_android_library.utils.SingleToastUtil
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.Disposable
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.TimeZone
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/10/24 10:14
|
||||
* Desc:领取红包
|
||||
**/
|
||||
@ActLayoutRes(R.layout.red_package_open_dialog)
|
||||
class RedPackageOpenDialog2 : BaseDialog<RedPackageOpenDialogBinding>(), ILog {
|
||||
|
||||
private var btnAnimator: ObjectAnimator? = null
|
||||
|
||||
private var countDownDisposable: Disposable? = null
|
||||
|
||||
// 倒计时格式(分:秒)
|
||||
private val mmssFormat by lazy(LazyThreadSafetyMode.NONE) {
|
||||
SimpleDateFormat("mm:ss").apply {
|
||||
timeZone = TimeZone.getTimeZone("GMT+00:00")
|
||||
}
|
||||
}
|
||||
|
||||
private val data by lazy(LazyThreadSafetyMode.NONE) {
|
||||
arguments?.getSerializable(Constants.KEY_INTENT) as? RedPackageData
|
||||
}
|
||||
|
||||
// 打开红包的结果
|
||||
private var openResultRunnable: (() -> Unit)? = null
|
||||
|
||||
// 按钮动画是否有效(至少转过了一周期)
|
||||
private var isValidOfBtnAnimator: Boolean = false
|
||||
|
||||
// 按钮执行函数
|
||||
private var btnRunnable: (() -> Unit)? = null
|
||||
|
||||
// 打开红包接口请求中
|
||||
private var opening = false
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* 此入口来源仅限:【全服红包信令】、【厅内无门槛-立即生效红包信令】
|
||||
*/
|
||||
fun newInstance(data: RedPackageNotifyInfo): RedPackageOpenDialog2 {
|
||||
/**
|
||||
* 收到这两种信令直接展示即可,无需再次请求接口查询状态,
|
||||
* 但由于信令和接口查询的数据格式不一致,所以这里做下转换,达到逻辑共用
|
||||
*/
|
||||
val item = RedPackageData(
|
||||
amount = null,
|
||||
avatar = data.sendUserAvatar,
|
||||
beginTime = data.beginTime,
|
||||
commissionAmount = null,
|
||||
createTime = null,
|
||||
duration = null,
|
||||
endTime = null,
|
||||
finish = true,
|
||||
id = data.redEnvelopeId.toLongOrNull(),
|
||||
kind = data.kind,
|
||||
message = data.redEnvelopeMessage,
|
||||
nick = data.sendUserNick,
|
||||
num = null,
|
||||
originalAmount = null,
|
||||
position = null,
|
||||
roomTitle = null,
|
||||
roomUid = data.roomUid,
|
||||
//红包状态 1 开抢中 2 过时 3 抢光了 4 抢到了 5 将要开始 6 超时已退还
|
||||
state = null,
|
||||
type = null,
|
||||
updateTime = null,
|
||||
userId = null,
|
||||
validityType = data.validityType,
|
||||
result = null
|
||||
)
|
||||
return newInstance(item)
|
||||
}
|
||||
|
||||
fun newInstance(data: RedPackageData): RedPackageOpenDialog2 {
|
||||
return RedPackageOpenDialog2().apply {
|
||||
arguments = Bundle().apply {
|
||||
putSerializable(Constants.KEY_INTENT, data)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
width = WindowManager.LayoutParams.MATCH_PARENT
|
||||
height = WindowManager.LayoutParams.WRAP_CONTENT
|
||||
super.onStart()
|
||||
}
|
||||
|
||||
override fun init() {
|
||||
val data = this.data
|
||||
if (data == null) {
|
||||
dismissAllowingStateLoss()
|
||||
return
|
||||
}
|
||||
dialog?.setCanceledOnTouchOutside(false)
|
||||
|
||||
binding.ivClose.singleClick {
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
|
||||
binding.layoutBtn.singleClick {
|
||||
btnRunnable?.invoke()
|
||||
}
|
||||
loadData(data)
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载红包数据
|
||||
*/
|
||||
private fun loadData(data: RedPackageData) {
|
||||
//红包状态 1 开抢中 2 过时 3 抢光了 4 抢到了 5 将要开始 6 超时已退还
|
||||
if (data.state == 4) {
|
||||
loadResult(data.result)
|
||||
} else {
|
||||
// else简单理解为可领取状态,正常情况下在RedPackageWidget点击时有异常状态过滤
|
||||
loadOpen(data)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载可领取数据
|
||||
*/
|
||||
private fun loadOpen(data: RedPackageData) {
|
||||
switchResultViewVisible(false)
|
||||
switchOpenViewVisible(true)
|
||||
binding.ivSendAvatar.loadAvatar(data.avatar)
|
||||
binding.tvSendName.text = data.nick
|
||||
loadTips(data)
|
||||
loadBtnState(data)
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载红包提示
|
||||
*/
|
||||
private fun loadTips(data: RedPackageData) {
|
||||
binding.tvOpenTips.isVisible = false
|
||||
when (data.kind) {
|
||||
2 -> {
|
||||
binding.tvOpenTips.spannableBuilder()
|
||||
.appendText(
|
||||
text = R.string.red_package_open_tips_follow.toStringRes(),
|
||||
textColor = getColorById(R.color.color_FFF87A)
|
||||
)
|
||||
.appendText(text = R.string.red_package_open_tips_msg_end.toStringRes()).apply()
|
||||
binding.tvOpenTips.isVisible = true
|
||||
}
|
||||
|
||||
3 -> {
|
||||
binding.tvOpenTips.spannableBuilder()
|
||||
.appendText(
|
||||
text = R.string.red_package_open_tips_share.toStringRes(),
|
||||
textColor = getColorById(R.color.color_FFF87A)
|
||||
)
|
||||
.appendText(text = R.string.red_package_open_tips_msg_end.toStringRes()).apply()
|
||||
binding.tvOpenTips.isVisible = true
|
||||
}
|
||||
|
||||
4 -> {
|
||||
binding.tvOpenTips.spannableBuilder()
|
||||
.appendText(text = R.string.red_package_open_tips_msg1.toStringRes())
|
||||
.appendText(
|
||||
text = data.message ?: "",
|
||||
textColor = getColorById(R.color.color_FFF87A)
|
||||
)
|
||||
.appendText(text = R.string.red_package_open_tips_msg_end.toStringRes()).apply()
|
||||
binding.tvOpenTips.isVisible = true
|
||||
}
|
||||
|
||||
else -> {
|
||||
loadTips(data.message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载按钮状态
|
||||
*/
|
||||
private fun loadBtnState(data: RedPackageData) {
|
||||
binding.groupBtnTime.isVisible = false
|
||||
binding.ivBtnGet.isVisible = false
|
||||
binding.tvBtnMsg.isVisible = false
|
||||
btnRunnable = null
|
||||
|
||||
val gap = (data.beginTime ?: 0) - ServiceTime.time
|
||||
// 开始了?
|
||||
val started = gap < 0
|
||||
if (data.kind == 0) {
|
||||
// 旧厅内红包or全服红包
|
||||
switchToOpenState()
|
||||
return
|
||||
}
|
||||
if (data.kind == 1 || data.finish == true) {
|
||||
if (started) {
|
||||
switchToOpenState()
|
||||
} else {
|
||||
startCountDown(data.beginTime ?: 0)
|
||||
}
|
||||
} else {
|
||||
binding.tvBtnMsg.isVisible = true
|
||||
if (started) {
|
||||
binding.tvBtnMsg.setText(R.string.red_package_open_btn_no)
|
||||
btnRunnable = {
|
||||
SingleToastUtil.showToast(R.string.red_package_open_no_tips)
|
||||
}
|
||||
} else {
|
||||
when (data.kind) {
|
||||
2 -> {
|
||||
binding.tvBtnMsg.setText(R.string.red_package_open_btn_follow)
|
||||
btnRunnable = {
|
||||
dismissAllowingStateLoss()
|
||||
showUserDialog(data.userId)
|
||||
}
|
||||
}
|
||||
|
||||
3 -> {
|
||||
binding.tvBtnMsg.setText(R.string.red_package_open_btn_share)
|
||||
btnRunnable = {
|
||||
dismissAllowingStateLoss()
|
||||
EventBus.getDefault().post(ShareRoomEvent())
|
||||
}
|
||||
}
|
||||
|
||||
4 -> {
|
||||
binding.tvBtnMsg.setText(R.string.red_package_open_btn_msg)
|
||||
btnRunnable = {
|
||||
dismissAllowingStateLoss()
|
||||
EventBus.getDefault().post(OpenRoomMessageInputEvent(data.message))
|
||||
}
|
||||
}
|
||||
|
||||
else -> {
|
||||
binding.tvBtnMsg.text = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始倒计时
|
||||
* @param time 开抢时间
|
||||
*/
|
||||
private fun startCountDown(time: Long) {
|
||||
stopCountDown()
|
||||
val count = time - ServiceTime.time
|
||||
if (count <= 0) {
|
||||
switchToOpenState()
|
||||
return
|
||||
}
|
||||
binding.groupBtnTime.isVisible = true
|
||||
countDownDisposable =
|
||||
Observable.intervalRange(0, count / 1000, 0, 1000L, TimeUnit.MILLISECONDS)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.doOnNext {
|
||||
val gap = time - ServiceTime.time
|
||||
if (gap >= 0) {
|
||||
binding.tvBtnTime.text = mmssFormat.format(gap)
|
||||
}
|
||||
}
|
||||
.doOnComplete {
|
||||
switchToOpenState()
|
||||
}
|
||||
.subscribe()
|
||||
}
|
||||
|
||||
|
||||
private fun stopCountDown() {
|
||||
if (countDownDisposable?.isDisposed == false) {
|
||||
countDownDisposable?.dispose()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 切换为可抢状态
|
||||
*/
|
||||
private fun switchToOpenState() {
|
||||
binding.tvBtnMsg.isVisible = false
|
||||
binding.groupBtnTime.isVisible = false
|
||||
binding.ivBtnGet.isVisible = true
|
||||
btnRunnable = {
|
||||
if (!opening) {
|
||||
this.data?.let {
|
||||
openRedPackage(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadTips(msg: String?) {
|
||||
if (msg.isNullOrEmpty()) {
|
||||
binding.tvOpenTips.isVisible = false
|
||||
} else {
|
||||
binding.tvOpenTips.text = msg
|
||||
binding.tvOpenTips.isVisible = true
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开红包
|
||||
*/
|
||||
private fun openRedPackage(data: RedPackageData) {
|
||||
opening = true
|
||||
openResultRunnable = null
|
||||
startRedPacketAnim(binding.layoutBtn)
|
||||
val d = RedPackageModel.openRedPackage(data.id ?: 0)
|
||||
.compose(bindUntilEvent(FragmentEvent.DESTROY_VIEW)).subscribe({
|
||||
if (isValidOfBtnAnimator) {
|
||||
btnAnimator?.cancel()
|
||||
onOpenSuccess(it)
|
||||
} else {
|
||||
openResultRunnable = {
|
||||
onOpenSuccess(it)
|
||||
}
|
||||
}
|
||||
}, {
|
||||
if (isValidOfBtnAnimator) {
|
||||
btnAnimator?.cancel()
|
||||
onOpenFail(it)
|
||||
} else {
|
||||
openResultRunnable = {
|
||||
onOpenFail(it)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载结果
|
||||
*/
|
||||
private fun loadResult(data: RedPackageInfo?) {
|
||||
binding.layoutContent.setBackgroundResource(R.drawable.red_package_result_bg)
|
||||
switchOpenViewVisible(false)
|
||||
switchResultViewVisible(true)
|
||||
binding.groupResultMoney.isVisible = false
|
||||
binding.tvResultEmptyTips.isVisible = false
|
||||
binding.ivResultSendAvatar.loadAvatar(data?.redEnvelopeVO?.userVO?.avatar)
|
||||
binding.tvResultSendName.text = data?.redEnvelopeVO?.userVO?.nick ?: ""
|
||||
val name = data?.redEnvelopeVO?.userVO?.nick ?: ""
|
||||
if (name.length > 8) {
|
||||
binding.tvResultSendName.text = name?.take(8) + "..的紅包"
|
||||
} else {
|
||||
binding.tvResultSendName.text = name + "的紅包"
|
||||
}
|
||||
binding.tvMessage.text = data?.redEnvelopeVO?.message
|
||||
binding.tvCount.text = R.string.red_package_result_count_format.toStringRes()
|
||||
.format(data?.redEnvelopeVO?.pickNum ?: 0, data?.redEnvelopeVO?.totalNum ?: 0)
|
||||
|
||||
val adapter = RedPackageResultAdapter()
|
||||
binding.recyclerView.adapter = adapter
|
||||
adapter.setNewData(data?.redEnvelopeItemVOs)
|
||||
|
||||
when (data?.redEnvelopeState) {
|
||||
RedEnvelopeState.SUCCESS -> {
|
||||
binding.tvMoney.text = data.currentUserAmount.toString().substringBefore(".")
|
||||
binding.groupResultMoney.isVisible = true
|
||||
}
|
||||
|
||||
RedEnvelopeState.TIME_OUT, RedEnvelopeState.REMAIN_ZERO, RedEnvelopeState.TIME_OUT_BACK -> {
|
||||
binding.tvResultEmptyTips.isVisible = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开红包响应成功
|
||||
* @param data 结果
|
||||
*/
|
||||
private fun onOpenSuccess(data: RedPackageInfo) {
|
||||
loadResult(data)
|
||||
when (data.redEnvelopeState) {
|
||||
RedEnvelopeState.SUCCESS -> {
|
||||
// 下面这段是延续老代码保留的
|
||||
if (!AvRoomDataManager.get().isRoomFans) {
|
||||
AvRoomDataManager.get().roomUid.let {
|
||||
CollectionRoomModel.get().followRoom("1", it)
|
||||
.subscribe { _: String? ->
|
||||
AvRoomDataManager.get().isRoomFans = true
|
||||
EventBus.getDefault().post(FollowRoomEvent())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
PayModel.get().getWalletInfo(AuthModel.get().currentUid).subscribe()
|
||||
opening = false
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开红包响应失败
|
||||
*/
|
||||
private fun onOpenFail(throwable: Throwable) {
|
||||
switchToOpenState()
|
||||
btnAnimator?.cancel()
|
||||
SingleToastUtil.showToast(throwable.message)
|
||||
opening = false
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
private fun startRedPacketAnim(v: View) {
|
||||
if (btnAnimator?.isRunning == true) {
|
||||
btnAnimator?.cancel()
|
||||
}
|
||||
isValidOfBtnAnimator = false
|
||||
btnAnimator = ObjectAnimator.ofFloat(v, "rotationY", 0f, 360f)
|
||||
btnAnimator?.let {
|
||||
it.duration = 1500
|
||||
it.repeatCount = ValueAnimator.INFINITE
|
||||
it.repeatMode = ValueAnimator.RESTART
|
||||
it.interpolator = AccelerateDecelerateInterpolator()
|
||||
it.addListener(object : AnimatorListenerAdapter() {
|
||||
override fun onAnimationRepeat(animation: Animator) {
|
||||
super.onAnimationRepeat(animation)
|
||||
isValidOfBtnAnimator = true
|
||||
if (openResultRunnable != null) {
|
||||
animation.cancel()
|
||||
openResultRunnable?.invoke()
|
||||
}
|
||||
}
|
||||
})
|
||||
it.start()
|
||||
}
|
||||
}
|
||||
|
||||
private fun switchResultViewVisible(isVisible: Boolean) {
|
||||
binding.groupResult.isVisible = isVisible
|
||||
binding.groupResultMoney.isVisible = isVisible
|
||||
binding.tvResultEmptyTips.isVisible = isVisible
|
||||
}
|
||||
|
||||
private fun switchOpenViewVisible(isVisible: Boolean) {
|
||||
binding.groupOpen.isVisible = isVisible
|
||||
binding.tvOpenTips.isVisible = isVisible
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
btnAnimator?.cancel()
|
||||
btnAnimator = null
|
||||
stopCountDown()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
|
||||
private fun showUserDialog(uid: Long?) {
|
||||
if (uid == null) {
|
||||
return
|
||||
}
|
||||
activity?.let {
|
||||
UserInfoDialog.showNewUserInfoDialog(
|
||||
activity,
|
||||
uid
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,46 @@
|
||||
package com.yizhuan.erban.avroom.redpackage.open
|
||||
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import androidx.core.view.isVisible
|
||||
import com.chad.library.adapter.base.BaseQuickAdapter
|
||||
import com.chad.library.adapter.base.BaseViewHolder
|
||||
import com.yizhuan.erban.R
|
||||
import com.yizhuan.erban.ui.utils.loadAvatar
|
||||
import com.yizhuan.erban.utils.UserUtils
|
||||
import com.yizhuan.xchat_android_core.redpackage.RedEnvelopeItemVO
|
||||
import com.yizhuan.xchat_android_core.utils.subAndReplaceDot
|
||||
import com.yizhuan.xchat_android_library.utils.ResUtil
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/10/27 20:24
|
||||
* Desc:红包领取结果
|
||||
**/
|
||||
class RedPackageResultAdapter :
|
||||
BaseQuickAdapter<RedEnvelopeItemVO, BaseViewHolder>(R.layout.red_package_open_item_result) {
|
||||
private val dateFormat = SimpleDateFormat(
|
||||
ResUtil.getString(R.string.avroom_redpackage_redpackageopenadapter_01),
|
||||
Locale.CHINA
|
||||
)
|
||||
|
||||
override fun convert(helper: BaseViewHolder, item: RedEnvelopeItemVO) {
|
||||
helper.getView<ImageView>(R.id.iv_avatar).loadAvatar(item.userVO.avatar)
|
||||
val isSelf = item.userVO.uid == UserUtils.getUserUid()
|
||||
helper.setText(
|
||||
R.id.tv_name,
|
||||
if (isSelf) ResUtil.getString(R.string.avroom_redpackage_redpackageopenadapter_02) else item.userVO.nick.subAndReplaceDot(
|
||||
6
|
||||
)
|
||||
)
|
||||
helper.setText(R.id.tv_money, item.amount.substringBefore("."))
|
||||
try {
|
||||
helper.setText(R.id.tv_time, dateFormat.format(item.createTime))
|
||||
} catch (e: Exception) {
|
||||
helper.setText(R.id.tv_time, "")
|
||||
}
|
||||
helper.getView<View>(R.id.v_line).isVisible = helper.bindingAdapterPosition != itemCount - 1
|
||||
}
|
||||
}
|
@@ -0,0 +1,263 @@
|
||||
package com.yizhuan.erban.avroom.redpackage.send
|
||||
|
||||
import android.graphics.Color
|
||||
import androidx.core.view.isVisible
|
||||
import com.chuhai.utils.ktx.addDisableFilter
|
||||
import com.chuhai.utils.ktx.getColorById
|
||||
import com.chuhai.utils.ktx.singleClick
|
||||
import com.yizhuan.erban.R
|
||||
import com.yizhuan.erban.base.BaseBindingFragment
|
||||
import com.yizhuan.erban.databinding.RedPackagePrivateFragmentBinding
|
||||
import com.yizhuan.erban.pay.password.GiveGoldPassWordFragment
|
||||
import com.yizhuan.erban.pay.widget.GridPasswordNoFocusView
|
||||
import com.yizhuan.erban.ui.setting.ModifyPwdActivity
|
||||
import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil
|
||||
import com.yizhuan.erban.ui.widget.recyclerview.decoration.ColorDecoration
|
||||
import com.yizhuan.xchat_android_core.auth.AuthModel
|
||||
import com.yizhuan.xchat_android_core.initial.InitialModel
|
||||
import com.yizhuan.xchat_android_core.manager.AvRoomDataManager
|
||||
import com.yizhuan.xchat_android_core.pay.PayModel
|
||||
import com.yizhuan.xchat_android_core.redpackage.RedPackageModel
|
||||
import com.yizhuan.xchat_android_core.user.UserModel
|
||||
import com.yizhuan.xchat_android_core.utils.toIntOrDef
|
||||
import com.yizhuan.xchat_android_library.annatation.ActLayoutRes
|
||||
import com.yizhuan.xchat_android_library.utils.ResUtil
|
||||
import com.yizhuan.xchat_android_library.utils.SingleToastUtil
|
||||
import com.yizhuan.xchat_android_library.utils.codec.DESUtils
|
||||
import okhttp3.internal.toLongOrDefault
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/10/23 12:14
|
||||
* Desc: 厅内红包
|
||||
**/
|
||||
@ActLayoutRes(R.layout.red_package_private_fragment)
|
||||
class PrivateRedPackageEditorFragment : BaseBindingFragment<RedPackagePrivateFragmentBinding>() {
|
||||
|
||||
private var passWordFragment: GiveGoldPassWordFragment? = null
|
||||
|
||||
private var typeAdapter: RedPackageTypeItemAdapter? = null
|
||||
|
||||
// 生效时间类型 0 立即生效 1 限时生效
|
||||
private var timeType = 0
|
||||
override fun initiate() {
|
||||
mBinding.etText.addDisableFilter(" ", "\n")
|
||||
initTypeView()
|
||||
updateTimeView(true)
|
||||
}
|
||||
|
||||
override fun onSetListener() {
|
||||
super.onSetListener()
|
||||
mBinding.tvNow.singleClick {
|
||||
updateTimeView(true)
|
||||
}
|
||||
mBinding.tvDelay.singleClick {
|
||||
updateTimeView(false)
|
||||
}
|
||||
mBinding.tvSend.singleClick {
|
||||
checkSend()
|
||||
}
|
||||
}
|
||||
|
||||
private fun initTypeView() {
|
||||
mBinding.recyclerView.addItemDecoration(
|
||||
ColorDecoration(
|
||||
Color.TRANSPARENT, UIUtil.dip2px(context, 6.0), 0, false
|
||||
)
|
||||
)
|
||||
val list = ArrayList<RedPackageTypeItemAdapter.ItemData>()
|
||||
list.add(
|
||||
RedPackageTypeItemAdapter.ItemData(
|
||||
1,
|
||||
R.string.red_package_type_unlimited_name,
|
||||
R.string.red_package_type_unlimited_tips
|
||||
)
|
||||
)
|
||||
list.add(
|
||||
RedPackageTypeItemAdapter.ItemData(
|
||||
2,
|
||||
R.string.red_package_type_follow_name,
|
||||
R.string.red_package_type_follow_tips
|
||||
)
|
||||
)
|
||||
list.add(
|
||||
RedPackageTypeItemAdapter.ItemData(
|
||||
3,
|
||||
R.string.red_package_type_share_name,
|
||||
R.string.red_package_type_share_tips
|
||||
)
|
||||
)
|
||||
list.add(
|
||||
RedPackageTypeItemAdapter.ItemData(
|
||||
4,
|
||||
R.string.red_package_type_msg_name,
|
||||
R.string.red_package_type_msg_tips
|
||||
)
|
||||
)
|
||||
val adapter = RedPackageTypeItemAdapter(list)
|
||||
typeAdapter = adapter
|
||||
adapter.setOnItemClickListener { _, view, position ->
|
||||
adapter.select(position)
|
||||
updateTypeView(adapter.getSelect()?.type)
|
||||
}
|
||||
mBinding.recyclerView.adapter = adapter
|
||||
// 默认选择第一个
|
||||
adapter.select(0)
|
||||
updateTypeView(adapter.getSelect()?.type)
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新红包类型对应的视图
|
||||
*/
|
||||
private fun updateTypeView(type: Int?) {
|
||||
when (type) {
|
||||
1 -> {
|
||||
mBinding.tvNow.isVisible = true
|
||||
mBinding.tvDelay.isVisible = true
|
||||
mBinding.etText.isVisible = false
|
||||
}
|
||||
|
||||
4 -> {
|
||||
mBinding.tvNow.isVisible = false
|
||||
mBinding.tvDelay.isVisible = false
|
||||
mBinding.etText.isVisible = true
|
||||
}
|
||||
|
||||
else -> {
|
||||
mBinding.tvNow.isVisible = false
|
||||
mBinding.tvDelay.isVisible = false
|
||||
mBinding.etText.isVisible = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新时间选项
|
||||
*/
|
||||
private fun updateTimeView(nowOrDelay: Boolean) {
|
||||
if (nowOrDelay) {
|
||||
timeType = 0
|
||||
mBinding.tvNow.setBackgroundResource(R.drawable.red_package_bg_type_selected)
|
||||
mBinding.tvDelay.setBackgroundResource(R.drawable.shape_f8f8fa_8)
|
||||
mBinding.tvNow.setTextColor(mBinding.root.context.getColorById(R.color.color_FF285C))
|
||||
mBinding.tvDelay.setTextColor(mBinding.root.context.getColorById(R.color.color_767585))
|
||||
} else {
|
||||
timeType = 1
|
||||
mBinding.tvNow.setBackgroundResource(R.drawable.shape_f8f8fa_8)
|
||||
mBinding.tvDelay.setBackgroundResource(R.drawable.red_package_bg_type_selected)
|
||||
mBinding.tvNow.setTextColor(mBinding.root.context.getColorById(R.color.color_767585))
|
||||
mBinding.tvDelay.setTextColor(mBinding.root.context.getColorById(R.color.color_FF285C))
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkSend() {
|
||||
val initInfo = InitialModel.get().cacheInitInfo
|
||||
if (initInfo == null) {
|
||||
SingleToastUtil.showToast(ResUtil.getString(R.string.avroom_redpackage_redpackagesenddialog_01))
|
||||
return
|
||||
}
|
||||
val typeItem = typeAdapter?.getSelect()
|
||||
if (typeItem?.type == 4) {
|
||||
if (mBinding.etText.text.toString().trim().isEmpty()) {
|
||||
toast(R.string.red_package_msg_empty_tips)
|
||||
return
|
||||
}
|
||||
}
|
||||
val minNum = initInfo.redEnvelopeConfig.roomRedEnvelopeMinNum
|
||||
val maxNum = initInfo.redEnvelopeConfig.roomRedEnvelopeMaxNum
|
||||
val minGold = initInfo.redEnvelopeConfig.roomRedEnvelopeMinAmount
|
||||
val maxGold = initInfo.redEnvelopeConfig.roomRedEnvelopeMaxAmount
|
||||
val rate =
|
||||
if (initInfo.redEnvelopeConfig.exchangeDiamondsRate == 0.0) 0.68 else initInfo.redEnvelopeConfig.exchangeDiamondsRate
|
||||
|
||||
val redNum = mBinding?.etNum?.text.toString().toIntOrDef()
|
||||
if (redNum < minNum || redNum > maxNum) {
|
||||
SingleToastUtil.showToast("紅包數量不能小於${minNum}或大於${maxNum}!")
|
||||
return
|
||||
}
|
||||
val goldNum = mBinding?.etMoney?.text.toString().toIntOrDef()
|
||||
if (goldNum % 10 != 0) {
|
||||
SingleToastUtil.showToast("鉆石數必須為10的倍數!")
|
||||
return
|
||||
}
|
||||
|
||||
if (goldNum < minGold || goldNum > maxGold) {
|
||||
SingleToastUtil.showToast("鉆石數量不能小於${minGold}或大於${maxGold}!")
|
||||
return
|
||||
}
|
||||
if (goldNum.toFloat() / redNum * rate < 0.1) {//單個手氣紅包價值不低於0.1水晶
|
||||
SingleToastUtil.showToast("單個紅包金額過低")
|
||||
return
|
||||
}
|
||||
UserModel.get().cacheLoginUserInfo?.let {
|
||||
if (!it.isBindPaymentPwd) {
|
||||
ModifyPwdActivity.start(context, ModifyPwdActivity.PAY_PWD)
|
||||
return
|
||||
}
|
||||
}
|
||||
GiveGoldPassWordFragment.newInstance(
|
||||
childFragmentManager,
|
||||
mBinding?.etMoney?.text.toString()
|
||||
).apply {
|
||||
setListener(object : GridPasswordNoFocusView.OnPasswordChangedListener {
|
||||
override fun onTextChanged(psw: String?) {
|
||||
val password = passWordFragment?.password?.password ?: ""
|
||||
if (password.length == 6) {
|
||||
send(password)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onInputFinish(psw: String?) {
|
||||
}
|
||||
})
|
||||
passWordFragment = this
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 密码输入完成
|
||||
*/
|
||||
private fun send(password: String) {
|
||||
dialogManager.showProgressDialog(context)
|
||||
val kind = typeAdapter?.getSelect()?.type ?: 1
|
||||
val message = if (kind == 4) {
|
||||
mBinding.etText.text.trim().toString()
|
||||
} else {
|
||||
null
|
||||
}
|
||||
val validityType = if (kind == 1) {
|
||||
timeType
|
||||
} else {
|
||||
// 非无门槛红包 默认限时
|
||||
1
|
||||
}
|
||||
RedPackageModel.sendRedPackage(
|
||||
goldNum = mBinding.etMoney.text.trim().toString().toLongOrDefault(0),
|
||||
message = message,
|
||||
num = mBinding.etNum.text.trim().toString().toLongOrDefault(0),
|
||||
roomUId = AvRoomDataManager.get().mCurrentRoomInfo?.uid.toString(),
|
||||
type = 1,
|
||||
kind = kind,
|
||||
validityType = validityType,
|
||||
password = DESUtils.DESAndBase64(password)
|
||||
)
|
||||
.compose(bindToLifecycle())
|
||||
.doOnError {
|
||||
dialogManager.dismissDialog()
|
||||
SingleToastUtil.showToast(it.message)
|
||||
passWordFragment?.password?.clearPassword()
|
||||
}
|
||||
.subscribe { _ ->
|
||||
PayModel.get().getWalletInfo(AuthModel.get().currentUid).subscribe()
|
||||
dialogManager.dismissDialog()
|
||||
SingleToastUtil.showToast("發送成功")
|
||||
passWordFragment?.dismissAllowingStateLoss()
|
||||
(parentFragment as? RedPackageSendDialog2)?.dismissAllowingStateLoss()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
passWordFragment?.dismissAllowingStateLoss()
|
||||
passWordFragment = null
|
||||
}
|
||||
}
|
@@ -0,0 +1,139 @@
|
||||
package com.yizhuan.erban.avroom.redpackage.send
|
||||
|
||||
import com.chuhai.utils.ktx.addDisableFilter
|
||||
import com.chuhai.utils.ktx.setOnInputChangedListener
|
||||
import com.chuhai.utils.ktx.singleClick
|
||||
import com.chuhai.utils.ktx.toStringRes
|
||||
import com.yizhuan.erban.R
|
||||
import com.yizhuan.erban.base.BaseBindingFragment
|
||||
import com.yizhuan.erban.databinding.RedPackagePublicFragmentBinding
|
||||
import com.yizhuan.erban.pay.password.GiveGoldPassWordFragment
|
||||
import com.yizhuan.erban.pay.widget.GridPasswordNoFocusView
|
||||
import com.yizhuan.erban.ui.setting.ModifyPwdActivity
|
||||
import com.yizhuan.xchat_android_core.auth.AuthModel
|
||||
import com.yizhuan.xchat_android_core.initial.InitialModel
|
||||
import com.yizhuan.xchat_android_core.initial.bean.InitInfo
|
||||
import com.yizhuan.xchat_android_core.manager.AvRoomDataManager
|
||||
import com.yizhuan.xchat_android_core.pay.PayModel
|
||||
import com.yizhuan.xchat_android_core.redpackage.RedPackageModel
|
||||
import com.yizhuan.xchat_android_core.user.UserModel
|
||||
import com.yizhuan.xchat_android_core.utils.toIntOrDef
|
||||
import com.yizhuan.xchat_android_library.annatation.ActLayoutRes
|
||||
import com.yizhuan.xchat_android_library.utils.SingleToastUtil
|
||||
import com.yizhuan.xchat_android_library.utils.codec.DESUtils
|
||||
import okhttp3.internal.toLongOrDefault
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/10/23 12:14
|
||||
* Desc:全服红包
|
||||
**/
|
||||
@ActLayoutRes(R.layout.red_package_public_fragment)
|
||||
class PublicRedPackageEditorFragment : BaseBindingFragment<RedPackagePublicFragmentBinding>() {
|
||||
|
||||
private var passWordFragment: GiveGoldPassWordFragment? = null
|
||||
|
||||
override fun initiate() {
|
||||
mBinding.etText.addDisableFilter("\n")
|
||||
mBinding.etText.setOnInputChangedListener {
|
||||
mBinding.tvTextLength.text =
|
||||
R.string.red_package_result_count_format.toStringRes().format(this, 20)
|
||||
true
|
||||
}
|
||||
|
||||
mBinding.tvSend.singleClick {
|
||||
checkSend()
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkSend() {
|
||||
val initInfo = InitialModel.get().cacheInitInfo ?: InitInfo()
|
||||
val minNum = initInfo.redEnvelopeConfig.serverRedEnvelopeMinNum
|
||||
val maxNum = initInfo.redEnvelopeConfig.serverRedEnvelopeMaxNum
|
||||
val minGold = initInfo.redEnvelopeConfig.serverRedEnvelopeMinAmount
|
||||
val maxGold = initInfo.redEnvelopeConfig.serverRedEnvelopeMaxAmount
|
||||
val rate =
|
||||
if (initInfo.redEnvelopeConfig.exchangeDiamondsRate == 0.0) 0.68 else initInfo.redEnvelopeConfig.exchangeDiamondsRate
|
||||
|
||||
val redNum = mBinding?.etNum?.text.toString().toIntOrDef()
|
||||
if (redNum < minNum || redNum > maxNum) {
|
||||
SingleToastUtil.showToast("紅包數量不能小於${minNum}或大於${maxNum}!")
|
||||
return
|
||||
}
|
||||
val goldNum = mBinding?.etMoney?.text.toString().toIntOrDef()
|
||||
if (goldNum % 100 != 0) {
|
||||
SingleToastUtil.showToast("鉆石數必須為100的倍數!")
|
||||
return
|
||||
}
|
||||
if (goldNum < minGold || goldNum > maxGold) {
|
||||
SingleToastUtil.showToast("鉆石數量不能小於${minGold}或大於${maxGold}!")
|
||||
return
|
||||
}
|
||||
if (goldNum.toFloat() / redNum * rate < 0.1) {//單個手氣紅包價值不低於0.1水晶
|
||||
SingleToastUtil.showToast("單個紅包金額過低")
|
||||
return
|
||||
}
|
||||
UserModel.get().cacheLoginUserInfo?.let {
|
||||
if (!it.isBindPaymentPwd) {
|
||||
ModifyPwdActivity.start(context, ModifyPwdActivity.PAY_PWD)
|
||||
return
|
||||
}
|
||||
}
|
||||
GiveGoldPassWordFragment.newInstance(
|
||||
childFragmentManager,
|
||||
mBinding?.etMoney?.text.toString()
|
||||
).apply {
|
||||
setListener(object : GridPasswordNoFocusView.OnPasswordChangedListener {
|
||||
override fun onTextChanged(psw: String?) {
|
||||
val password = passWordFragment?.password?.password ?: ""
|
||||
if (password.length == 6) {
|
||||
send(password)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onInputFinish(psw: String?) {
|
||||
}
|
||||
})
|
||||
passWordFragment = this
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 密码输入完成
|
||||
*/
|
||||
private fun send(password: String) {
|
||||
dialogManager.showProgressDialog(context)
|
||||
var message = mBinding.etText.text.trim().toString()
|
||||
if (message.isEmpty()) {
|
||||
message = R.string.red_package_msg_def.toStringRes()
|
||||
}
|
||||
RedPackageModel.sendRedPackage(
|
||||
goldNum = mBinding.etMoney.text.trim().toString().toLongOrDefault(0),
|
||||
message = message,
|
||||
num = mBinding.etNum.text.trim().toString().toLongOrDefault(0),
|
||||
roomUId = AvRoomDataManager.get().mCurrentRoomInfo?.uid.toString(),
|
||||
type = 2,
|
||||
kind = 0,
|
||||
validityType = 0,
|
||||
password = DESUtils.DESAndBase64(password)
|
||||
)
|
||||
.compose(bindToLifecycle())
|
||||
.doOnError {
|
||||
dialogManager.dismissDialog()
|
||||
SingleToastUtil.showToast(it.message)
|
||||
passWordFragment?.password?.clearPassword()
|
||||
}
|
||||
.subscribe { _ ->
|
||||
PayModel.get().getWalletInfo(AuthModel.get().currentUid).subscribe()
|
||||
dialogManager.dismissDialog()
|
||||
SingleToastUtil.showToast("發送成功")
|
||||
passWordFragment?.dismissAllowingStateLoss()
|
||||
(parentFragment as? RedPackageSendDialog2)?.dismissAllowingStateLoss()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
passWordFragment?.dismissAllowingStateLoss()
|
||||
passWordFragment = null
|
||||
}
|
||||
}
|
@@ -0,0 +1,127 @@
|
||||
package com.yizhuan.erban.avroom.redpackage.send
|
||||
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.view.Gravity
|
||||
import android.view.WindowManager
|
||||
import com.chuhai.utils.ktx.singleClick
|
||||
import com.chuhai.utils.ktx.toStringRes
|
||||
import com.yizhuan.erban.R
|
||||
import com.yizhuan.erban.avroom.redpackage.RedPackageEvent
|
||||
import com.yizhuan.erban.base.BaseDialog
|
||||
import com.yizhuan.erban.common.ViewPagerAdapter
|
||||
import com.yizhuan.erban.databinding.RedPackageSendDialogBinding
|
||||
import com.yizhuan.erban.ui.pay.ChargeActivity
|
||||
import com.yizhuan.erban.ui.webview.CommonWebViewActivity
|
||||
import com.yizhuan.erban.ui.webview.DialogWebViewActivity
|
||||
import com.yizhuan.erban.ui.widget.magicindicator.ViewPagerHelper
|
||||
import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.CommonNavigator
|
||||
import com.yizhuan.xchat_android_core.Constants
|
||||
import com.yizhuan.xchat_android_core.UriProvider
|
||||
import com.yizhuan.xchat_android_core.initial.InitialModel
|
||||
import com.yizhuan.xchat_android_core.pay.PayModel
|
||||
import com.yizhuan.xchat_android_core.pay.event.UpdateWalletInfoEvent
|
||||
import com.yizhuan.xchat_android_core.redpackage.*
|
||||
import com.yizhuan.xchat_android_library.annatation.ActLayoutRes
|
||||
import com.yizhuan.xchat_android_library.common.util.DeviceUtil
|
||||
import com.yizhuan.xchat_android_library.utils.AppMetaDataUtil
|
||||
import com.yizhuan.xchat_android_library.utils.ResUtil
|
||||
import com.yizhuan.xchat_android_library.utils.SingleToastUtil
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/10/23 12:14
|
||||
* Desc:发红包
|
||||
**/
|
||||
@ActLayoutRes(R.layout.red_package_send_dialog)
|
||||
class RedPackageSendDialog2 : BaseDialog<RedPackageSendDialogBinding>() {
|
||||
|
||||
override fun onStart() {
|
||||
gravity = Gravity.BOTTOM
|
||||
width = WindowManager.LayoutParams.MATCH_PARENT
|
||||
height = WindowManager.LayoutParams.WRAP_CONTENT
|
||||
super.onStart()
|
||||
}
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
override fun init() {
|
||||
EventBus.getDefault().register(this)
|
||||
if (InitialModel.get().cacheInitInfo == null) {
|
||||
InitialModel.get().init(true)
|
||||
SingleToastUtil.showToast(ResUtil.getString(R.string.avroom_redpackage_redpackagesenddialog_01))
|
||||
dismissAllowingStateLoss()
|
||||
return
|
||||
}
|
||||
initView()
|
||||
initEvent()
|
||||
PayModel.get().currentWalletInfo?.let {
|
||||
binding.tvBalance.text = it.diamondNum.toLong().toString()
|
||||
}
|
||||
}
|
||||
|
||||
private fun initView() {
|
||||
val tabTitles = arrayListOf(
|
||||
R.string.red_package_room.toStringRes(),
|
||||
R.string.red_package_public.toStringRes()
|
||||
)
|
||||
val topMagicIndicatorAdapter = TabIndicatorAdapter(context, tabTitles)
|
||||
topMagicIndicatorAdapter.setOnItemSelectListener {
|
||||
binding.viewPager.currentItem = it
|
||||
}
|
||||
val commonNavigator = CommonNavigator(context)
|
||||
commonNavigator.isAdjustMode = true
|
||||
commonNavigator.adapter = topMagicIndicatorAdapter
|
||||
binding.tabLayout.navigator = commonNavigator
|
||||
val fragments =
|
||||
arrayListOf(PrivateRedPackageEditorFragment(), PublicRedPackageEditorFragment())
|
||||
binding.viewPager.adapter = ViewPagerAdapter(
|
||||
childFragmentManager,
|
||||
fragments.toList(),
|
||||
null
|
||||
)
|
||||
ViewPagerHelper.bind(binding.tabLayout, binding.viewPager)
|
||||
}
|
||||
|
||||
private fun initEvent() {
|
||||
binding.ivHelp.singleClick {
|
||||
DialogWebViewActivity.start(
|
||||
context,
|
||||
UriProvider.getRedPacketRule()
|
||||
)
|
||||
}
|
||||
|
||||
binding.tvBalance.singleClick {
|
||||
if (AppMetaDataUtil.getChannelID() == Constants.GOOGLE) {
|
||||
ChargeActivity.start(context)
|
||||
} else {
|
||||
CommonWebViewActivity.start(
|
||||
context, UriProvider.getOfficialPay(
|
||||
4,
|
||||
DeviceUtil.getDeviceId(context)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
EventBus.getDefault().unregister(this)
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onWalletInfoUpdate(event: UpdateWalletInfoEvent?) {
|
||||
if (!isViewLoaded) {
|
||||
return
|
||||
}
|
||||
binding.tvBalance.text = PayModel.get().currentWalletInfo?.diamondNum?.toString()
|
||||
?: "0"
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun handleRedPackageDialog(event: RedPackageEvent?) {
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
}
|
@@ -0,0 +1,76 @@
|
||||
package com.yizhuan.erban.avroom.redpackage.send
|
||||
|
||||
import com.chad.library.adapter.base.BaseQuickAdapter
|
||||
import com.chad.library.adapter.base.BaseViewHolder
|
||||
import com.chuhai.utils.ktx.getColorById
|
||||
import com.yizhuan.erban.R
|
||||
import io.realm.internal.Keep
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/10/23 18:02
|
||||
* Desc:
|
||||
**/
|
||||
class RedPackageTypeItemAdapter(list: List<ItemData>) :
|
||||
BaseQuickAdapter<RedPackageTypeItemAdapter.ItemData, BaseViewHolder>(
|
||||
R.layout.red_package_private_item_type,
|
||||
list
|
||||
) {
|
||||
|
||||
private var selectPosition = -1
|
||||
|
||||
@Keep
|
||||
data class ItemData(
|
||||
/**
|
||||
* 红包种类 0 旧版本 1 无门槛红包 2 关注红包 3 分享红包 4 弹幕红包
|
||||
*/
|
||||
val type: Int, val name: Int, val tips: Int
|
||||
)
|
||||
|
||||
override fun convert(helper: BaseViewHolder, item: ItemData) {
|
||||
helper.setText(R.id.tv_name, item.name)
|
||||
helper.setText(R.id.tv_tips, item.tips)
|
||||
convertState(helper, item)
|
||||
}
|
||||
|
||||
override fun convertPayloads(
|
||||
helper: BaseViewHolder,
|
||||
item: ItemData,
|
||||
payloads: MutableList<Any>
|
||||
) {
|
||||
super.convertPayloads(helper, item, payloads)
|
||||
convertState(helper, item)
|
||||
}
|
||||
|
||||
private fun convertState(helper: BaseViewHolder, item: ItemData) {
|
||||
if (helper.bindingAdapterPosition == selectPosition) {
|
||||
helper.setBackgroundRes(R.id.layout_root, R.drawable.red_package_bg_type_selected)
|
||||
helper.setTextColor(
|
||||
R.id.tv_name,
|
||||
helper.itemView.context.getColorById(R.color.color_FF285C)
|
||||
)
|
||||
helper.setTextColor(
|
||||
R.id.tv_tips,
|
||||
helper.itemView.context.getColorById(R.color.color_FF285C)
|
||||
)
|
||||
} else {
|
||||
helper.setBackgroundRes(R.id.layout_root, R.drawable.shape_f8f8fa_8)
|
||||
helper.setTextColor(
|
||||
R.id.tv_name,
|
||||
helper.itemView.context.getColorById(R.color.color_767585)
|
||||
)
|
||||
helper.setTextColor(
|
||||
R.id.tv_tips,
|
||||
helper.itemView.context.getColorById(R.color.color_94959C)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun select(position: Int) {
|
||||
this.selectPosition = position
|
||||
notifyItemRangeChanged(0, itemCount, true)
|
||||
}
|
||||
|
||||
fun getSelect(): ItemData? {
|
||||
return data.getOrNull(selectPosition)
|
||||
}
|
||||
}
|
@@ -0,0 +1,116 @@
|
||||
package com.yizhuan.erban.avroom.redpackage.send;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import androidx.appcompat.widget.AppCompatTextView;
|
||||
|
||||
import com.chuhai.utils.UiUtils;
|
||||
import com.yizhuan.erban.R;
|
||||
import com.yizhuan.erban.common.util.Utils;
|
||||
import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil;
|
||||
import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.CommonNavigatorAdapter;
|
||||
import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IPagerIndicator;
|
||||
import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IPagerTitleView;
|
||||
import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.indicators.LinePagerIndicator;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author jack
|
||||
* @Description
|
||||
* @Date 2018/11/1
|
||||
*/
|
||||
public class TabIndicatorAdapter extends CommonNavigatorAdapter {
|
||||
private List<String> mTitleList;
|
||||
private Context mContext;
|
||||
|
||||
public TabIndicatorAdapter(Context mContext, List<String> mTitleList ) {
|
||||
this.mTitleList = mTitleList;
|
||||
this.mContext = mContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return mTitleList == null ? 0 : mTitleList.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPagerTitleView getTitleView(Context context, int index) {
|
||||
ContactsPagerTitleView categoryPagerTitleView = new ContactsPagerTitleView(context, mTitleList.get(index));
|
||||
categoryPagerTitleView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (null != mOnItemSelectListener) {
|
||||
mOnItemSelectListener.onItemSelect(index);
|
||||
}
|
||||
}
|
||||
});
|
||||
return categoryPagerTitleView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPagerIndicator getIndicator(Context context) {
|
||||
LinePagerIndicator indicator = new LinePagerIndicator(context);
|
||||
indicator.setMode(LinePagerIndicator.MODE_EXACTLY);
|
||||
indicator.setLineHeight(UIUtil.dip2px(mContext, 4));
|
||||
indicator.setRoundRadius(UIUtil.dip2px(mContext, 4));
|
||||
indicator.setLineWidth(UIUtil.dip2px(mContext, 12));
|
||||
indicator.setColors(context.getResources().getColor(R.color.color_FF285C));
|
||||
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
|
||||
lp.topMargin = UIUtil.dip2px(mContext, 2);
|
||||
indicator.setLayoutParams(lp);
|
||||
return indicator;
|
||||
}
|
||||
|
||||
private OnItemSelectListener mOnItemSelectListener;
|
||||
|
||||
public void setOnItemSelectListener(OnItemSelectListener onItemSelectListener) {
|
||||
mOnItemSelectListener = onItemSelectListener;
|
||||
}
|
||||
|
||||
public interface OnItemSelectListener {
|
||||
void onItemSelect(int position);
|
||||
}
|
||||
|
||||
class ContactsPagerTitleView extends AppCompatTextView implements IPagerTitleView {
|
||||
|
||||
|
||||
public ContactsPagerTitleView(Context context, String tabInfo) {
|
||||
super(context);
|
||||
setHeight(Utils.dip2px(getContext(), 25));
|
||||
setTextSize(18);
|
||||
setText(tabInfo);
|
||||
setGravity(Gravity.CENTER);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onSelected(int index, int totalCount) {
|
||||
// setBackgroundResource(R.drawable.shape_bg_contact_indicator_item);
|
||||
setTextColor(getResources().getColor(R.color.color_FF285C));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeselected(int index, int totalCount) {
|
||||
// setBackgroundDrawable(null);
|
||||
setTextColor(getResources().getColor(R.color.color_767585));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLeave(int index, int totalCount, float leavePercent, boolean leftToRight) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnter(int index, int totalCount, float enterPercent, boolean leftToRight) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -116,6 +116,9 @@ public class MicroView extends LinearLayout implements View.OnLayoutChangeListen
|
||||
}
|
||||
|
||||
private void subMsg() {
|
||||
if (isInEditMode()) {
|
||||
return;
|
||||
}
|
||||
subscribe = IMNetEaseManager.get()
|
||||
.getChatRoomEventObservable().subscribe(
|
||||
roomEvent -> onReceiveRoomEvent(roomEvent),
|
||||
|
@@ -35,7 +35,6 @@ import android.text.Spannable;
|
||||
import android.text.SpannableString;
|
||||
import android.text.TextUtils;
|
||||
import android.text.style.StyleSpan;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
@@ -51,6 +50,7 @@ import androidx.fragment.app.FragmentManager;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.chuhai.utils.log.ILog;
|
||||
import com.google.gson.Gson;
|
||||
import com.netease.nim.uikit.common.util.log.LogUtil;
|
||||
import com.netease.nimlib.sdk.NIMSDK;
|
||||
@@ -70,6 +70,7 @@ import com.yizhuan.erban.avroom.activity.AVRoomActivity;
|
||||
import com.yizhuan.erban.avroom.firstcharge.FirstChargeDialog;
|
||||
import com.yizhuan.erban.avroom.redpackage.RedPackageGoRoomDialog;
|
||||
import com.yizhuan.erban.avroom.redpackage.RedPackageOpenDialog;
|
||||
import com.yizhuan.erban.avroom.redpackage.open.RedPackageOpenDialog2;
|
||||
import com.yizhuan.erban.common.LoadingFragment;
|
||||
import com.yizhuan.erban.common.NetworkErrorFragment;
|
||||
import com.yizhuan.erban.common.NoDataFragment;
|
||||
@@ -103,7 +104,6 @@ import com.yizhuan.xchat_android_core.UriProvider;
|
||||
import com.yizhuan.xchat_android_core.bean.BaseProtocol;
|
||||
import com.yizhuan.xchat_android_core.gift.bean.LuckyBagNoticeInfo;
|
||||
import com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment;
|
||||
import com.yizhuan.xchat_android_core.im.custom.bean.NotifyH5Attachment;
|
||||
import com.yizhuan.xchat_android_core.im.custom.bean.NotifyH5Info;
|
||||
import com.yizhuan.xchat_android_core.im.custom.bean.PlayEffectInfo;
|
||||
import com.yizhuan.xchat_android_core.im.custom.bean.RoomBoxPrizeInfo;
|
||||
@@ -959,7 +959,7 @@ public abstract class BaseActivity extends RxAppCompatActivity
|
||||
RedPackageNotifyInfo notifyInfo = new Gson().fromJson(String.valueOf(baseProtocol.getData()), RedPackageNotifyInfo.class);
|
||||
RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo;
|
||||
if (roomInfo != null && roomInfo.getUid() == notifyInfo.getRoomUid() && context instanceof AVRoomActivity) {
|
||||
RedPackageOpenDialog.Companion.newInstance(notifyInfo).show(BaseActivity.this);
|
||||
RedPackageOpenDialog2.Companion.newInstance(notifyInfo).show(BaseActivity.this);
|
||||
} else {
|
||||
RedPackageGoRoomDialog.Companion.newInstance(notifyInfo).show(this);
|
||||
}
|
||||
|
@@ -14,6 +14,7 @@ import java.lang.reflect.ParameterizedType
|
||||
|
||||
abstract class BaseDialog<T : ViewBinding> : RxDialogFragment() {
|
||||
|
||||
val isViewLoaded: Boolean get() = _binding != null
|
||||
private var _binding: T? = null
|
||||
private var onDismissListener: (() -> Unit)? = null
|
||||
val binding get() = _binding!!
|
||||
@@ -70,6 +71,7 @@ abstract class BaseDialog<T : ViewBinding> : RxDialogFragment() {
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
this.onDismissListener = null
|
||||
}
|
||||
|
||||
abstract fun init()
|
||||
|
@@ -6,8 +6,10 @@ import android.os.Build
|
||||
import android.os.Environment
|
||||
import android.text.SpannableString
|
||||
import android.view.View
|
||||
import com.chuhai.utils.log.ILog
|
||||
import com.netease.nim.uikit.StatusBarUtil
|
||||
import com.tongdaxing.erban.upgrade.AppUpgradeHelper
|
||||
import com.yizhuan.erban.BuildConfig
|
||||
import com.yizhuan.erban.R
|
||||
import com.yizhuan.erban.UIHelper
|
||||
import com.yizhuan.erban.base.BaseViewBindingActivity
|
||||
@@ -40,7 +42,7 @@ import java.io.File
|
||||
* 设置页
|
||||
* Created by wushaocheng on 2023/2/1.
|
||||
*/
|
||||
class SettingActivity : BaseViewBindingActivity<ActivitySettingBinding>(), View.OnClickListener {
|
||||
class SettingActivity : BaseViewBindingActivity<ActivitySettingBinding>(), View.OnClickListener,ILog {
|
||||
override fun init() {
|
||||
EventBus.getDefault().register(this)
|
||||
initWhiteTitleBar(ResUtil.getString(R.string.ui_setting_settingactivity_01))
|
||||
@@ -74,6 +76,12 @@ class SettingActivity : BaseViewBindingActivity<ActivitySettingBinding>(), View.
|
||||
binding.tvShieldManager.setOnClickListener(this)
|
||||
binding.rlyPermission.setOnClickListener(this)
|
||||
binding.rlyCheck.setOnClickListener(this)
|
||||
|
||||
if (BuildConfig.DEBUG) {
|
||||
binding.titleBar.setOnTitleClickListener {
|
||||
debug()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
@@ -103,6 +111,7 @@ class SettingActivity : BaseViewBindingActivity<ActivitySettingBinding>(), View.
|
||||
BindPhoneActivity.start(this)
|
||||
}
|
||||
}
|
||||
|
||||
R.id.rly_contact_us -> UIHelper.openContactUs(this)
|
||||
R.id.rly_help -> UIHelper.showUsinghelp(this)
|
||||
R.id.rly_update -> startActivity(Intent(applicationContext, AboutActivity::class.java))
|
||||
@@ -115,9 +124,14 @@ class SettingActivity : BaseViewBindingActivity<ActivitySettingBinding>(), View.
|
||||
}
|
||||
ModifyPwdActivity.start(this, ModifyPwdActivity.PAY_PWD)
|
||||
}
|
||||
|
||||
R.id.btn_login_out -> {
|
||||
val cacheLoginUserInfo = UserModel.get().cacheLoginUserInfo ?: return
|
||||
if (!cacheLoginUserInfo.isBindPasswd && !SPUtils.getBoolean(SpConstants.SET_PASSWORD, false)) {
|
||||
if (!cacheLoginUserInfo.isBindPasswd && !SPUtils.getBoolean(
|
||||
SpConstants.SET_PASSWORD,
|
||||
false
|
||||
)
|
||||
) {
|
||||
dialogManager.showOkCancelWithTitleDialog(ResUtil.getString(R.string.set_login_password),
|
||||
SpannableString(ResUtil.getString(R.string.set_login_password_tip)),
|
||||
ResUtil.getString(R.string.login_fragment_adduserinfofragment_04),
|
||||
@@ -126,7 +140,10 @@ class SettingActivity : BaseViewBindingActivity<ActivitySettingBinding>(), View.
|
||||
override fun onCancel() {}
|
||||
override fun onOk() {
|
||||
SPUtils.putBoolean(SpConstants.SET_PASSWORD, true)
|
||||
ModifyPwdActivity.start(this@SettingActivity, ModifyPwdActivity.LOGIN_PWD)
|
||||
ModifyPwdActivity.start(
|
||||
this@SettingActivity,
|
||||
ModifyPwdActivity.LOGIN_PWD
|
||||
)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
@@ -134,10 +151,12 @@ class SettingActivity : BaseViewBindingActivity<ActivitySettingBinding>(), View.
|
||||
LogoutHelper.logout()
|
||||
}
|
||||
}
|
||||
|
||||
R.id.tv_community_norms -> CommonWebViewActivity.start(
|
||||
this,
|
||||
UriProvider.getCommnunityNorms()
|
||||
)
|
||||
|
||||
R.id.rly_clear_cache -> dialogManager.showOkCancelWithTitleDialog(ResUtil.getString(R.string.ui_setting_settingactivity_07),
|
||||
SpannableString(ResUtil.getString(R.string.ui_setting_settingactivity_08)),
|
||||
ResUtil.getString(R.string.ui_setting_settingactivity_09),
|
||||
@@ -148,6 +167,7 @@ class SettingActivity : BaseViewBindingActivity<ActivitySettingBinding>(), View.
|
||||
clearCache()
|
||||
}
|
||||
})
|
||||
|
||||
R.id.tv_notice_setting -> NoticeSettingActivity.start(context)
|
||||
R.id.tv_shield_manager -> ShieldManageActivity.start(context)
|
||||
R.id.rly_permission -> PermissionGuideActivity.start(context)
|
||||
@@ -194,4 +214,8 @@ class SettingActivity : BaseViewBindingActivity<ActivitySettingBinding>(), View.
|
||||
dialogManager.dismissDialog()
|
||||
EventBus.getDefault().unregister(this)
|
||||
}
|
||||
|
||||
private fun debug() {
|
||||
// RedPackageOpenDialog2().show(this)
|
||||
}
|
||||
}
|
@@ -0,0 +1,37 @@
|
||||
package com.yizhuan.erban.view
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import androidx.viewpager.widget.ViewPager
|
||||
|
||||
/**
|
||||
* Created by Max on 2022/10/10 15:30
|
||||
* 高度自适应(采用最大的子页面高度)-ViewPager
|
||||
*/
|
||||
class WrapHeightViewPager : ViewPager {
|
||||
|
||||
constructor(context: Context) : this(context, null)
|
||||
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
|
||||
|
||||
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
||||
var height = 0
|
||||
for (i in 0 until childCount) {
|
||||
val child: View = getChildAt(i)
|
||||
child.measure(
|
||||
widthMeasureSpec,
|
||||
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)
|
||||
)
|
||||
val h = child.measuredHeight
|
||||
if (h > height) {
|
||||
height = h
|
||||
}
|
||||
}
|
||||
super.onMeasure(
|
||||
widthMeasureSpec, MeasureSpec.makeMeasureSpec(
|
||||
height,
|
||||
MeasureSpec.EXACTLY
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
BIN
app/src/main/res/drawable-xxhdpi/red_package_open_bg.webp
Normal file
After Width: | Height: | Size: 130 KiB |
BIN
app/src/main/res/drawable-xxhdpi/red_package_open_btn_bg.webp
Normal file
After Width: | Height: | Size: 46 KiB |
BIN
app/src/main/res/drawable-xxhdpi/red_package_open_btn_get.webp
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
app/src/main/res/drawable-xxhdpi/red_package_result_bg.webp
Normal file
After Width: | Height: | Size: 113 KiB |
BIN
app/src/main/res/drawable-xxhdpi/red_package_send_bg.webp
Normal file
After Width: | Height: | Size: 112 KiB |
BIN
app/src/main/res/drawable-xxhdpi/red_package_send_ic.webp
Normal file
After Width: | Height: | Size: 5.6 KiB |
After Width: | Height: | Size: 3.6 KiB |
BIN
app/src/main/res/drawable-xxhdpi/red_package_widget_bg.webp
Normal file
After Width: | Height: | Size: 6.2 KiB |
BIN
app/src/main/res/drawable-xxhdpi/red_package_widget_bg_text.webp
Normal file
After Width: | Height: | Size: 1.0 KiB |
11
app/src/main/res/drawable/red_package_bg_balance.xml
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<corners
|
||||
android:bottomLeftRadius="26dp"
|
||||
android:topLeftRadius="26dp" />
|
||||
<gradient
|
||||
android:angle="0"
|
||||
android:endColor="#FF225C"
|
||||
android:startColor="#FF6060" />
|
||||
</shape>
|
9
app/src/main/res/drawable/red_package_bg_num.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle"
|
||||
android:useLevel="false">
|
||||
|
||||
<corners android:radius="6dp" />
|
||||
<solid android:color="#FFF44646" />
|
||||
|
||||
</shape>
|
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<corners android:radius="8dp" />
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="#FF285C" />
|
||||
<solid android:color="#0FFF285C" />
|
||||
</shape>
|
12
app/src/main/res/drawable/red_package_ic_add.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="16dp"
|
||||
android:height="16dp"
|
||||
android:viewportWidth="16"
|
||||
android:viewportHeight="16">
|
||||
<path
|
||||
android:pathData="M8,3C8.491,3 8.889,3.398 8.889,3.889L8.888,7.111L12.111,7.111C12.602,7.111 13,7.509 13,8C13,8.491 12.602,8.889 12.111,8.889L8.888,8.888L8.889,12.111C8.889,12.602 8.491,13 8,13C7.509,13 7.111,12.602 7.111,12.111L7.111,8.888L3.889,8.889C3.398,8.889 3,8.491 3,8C3,7.509 3.398,7.111 3.889,7.111L7.111,7.111L7.111,3.889C7.111,3.398 7.509,3 8,3Z"
|
||||
android:strokeWidth="0.5"
|
||||
android:fillColor="#FFFFFF"
|
||||
android:strokeColor="#FFFFFF"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
22
app/src/main/res/drawable/red_package_ic_close.xml
Normal file
@@ -0,0 +1,22 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="28dp"
|
||||
android:height="28dp"
|
||||
android:viewportWidth="28"
|
||||
android:viewportHeight="28">
|
||||
<path
|
||||
android:pathData="M14,28C6.28,28 0,21.72 0,14C0,6.28 6.28,0 14,0C21.72,0 28,6.28 28,14C28,21.72 21.72,28 14,28ZM14,2.009C7.388,2.009 2.009,7.388 2.009,14C2.009,20.611 7.388,25.991 14,25.991C20.611,25.991 25.991,20.611 25.991,14C25.991,7.388 20.611,2.009 14,2.009Z"
|
||||
android:strokeAlpha="0.8"
|
||||
android:strokeWidth="1"
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="nonZero"
|
||||
android:strokeColor="#00000000"
|
||||
android:fillAlpha="0.8"/>
|
||||
<path
|
||||
android:pathData="M15.408,14.043L19.732,9.766C20.125,9.378 20.128,8.745 19.74,8.352C19.352,7.959 18.718,7.956 18.326,8.344L13.996,12.626L9.732,8.349C9.341,7.958 8.709,7.956 8.318,8.347C7.927,8.737 7.926,9.37 8.316,9.761L12.574,14.032L8.281,18.279C7.888,18.668 7.885,19.3 8.273,19.693C8.469,19.891 8.726,19.99 8.984,19.99C9.238,19.99 9.492,19.893 9.687,19.701L13.986,15.449L18.32,19.797C18.515,19.993 18.771,20.091 19.028,20.091C19.284,20.091 19.539,19.993 19.734,19.799C20.125,19.409 20.126,18.777 19.736,18.385L15.408,14.043Z"
|
||||
android:strokeAlpha="0.8"
|
||||
android:strokeWidth="1"
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="nonZero"
|
||||
android:strokeColor="#00000000"
|
||||
android:fillAlpha="0.8"/>
|
||||
</vector>
|
22
app/src/main/res/drawable/red_package_ic_help.xml
Normal file
@@ -0,0 +1,22 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M12.171,6.342C11.02,6.342 10.118,6.669 9.464,7.338C8.811,7.991 8.484,8.878 8.484,10.013L10.118,10.013C10.118,9.329 10.258,8.8 10.538,8.427C10.849,7.976 11.362,7.758 12.062,7.758C12.622,7.758 13.073,7.913 13.384,8.224C13.68,8.536 13.836,8.956 13.836,9.5C13.836,9.904 13.68,10.278 13.4,10.636L13.136,10.931C12.171,11.787 11.58,12.424 11.378,12.86C11.16,13.264 11.067,13.762 11.067,14.338L11.067,14.602L12.731,14.602L12.731,14.338C12.731,13.964 12.809,13.622 12.98,13.311C13.12,13.031 13.338,12.751 13.633,12.502C14.364,11.864 14.8,11.46 14.94,11.289C15.329,10.791 15.531,10.153 15.531,9.391C15.531,8.458 15.22,7.711 14.598,7.167C13.976,6.607 13.167,6.342 12.171,6.342ZM11.891,15.442C11.58,15.442 11.3,15.536 11.082,15.753C10.864,15.956 10.756,16.22 10.756,16.547C10.756,16.858 10.864,17.122 11.082,17.34C11.3,17.558 11.58,17.667 11.891,17.667C12.202,17.667 12.482,17.558 12.7,17.356C12.918,17.138 13.042,16.873 13.042,16.547C13.042,16.22 12.933,15.956 12.716,15.753C12.498,15.536 12.218,15.442 11.891,15.442Z"
|
||||
android:strokeAlpha="0.90000004"
|
||||
android:strokeWidth="1"
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="nonZero"
|
||||
android:strokeColor="#00000000"
|
||||
android:fillAlpha="0.90000004"/>
|
||||
<path
|
||||
android:pathData="M12,12m-9.333,0a9.333,9.333 0,1 1,18.667 0a9.333,9.333 0,1 1,-18.667 0"
|
||||
android:strokeAlpha="0.90000004"
|
||||
android:strokeWidth="1.33333333"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#FFFFFF"
|
||||
android:fillType="evenOdd"
|
||||
android:fillAlpha="0.90000004"/>
|
||||
</vector>
|
7
app/src/main/res/drawable/red_package_open_tips_bg.xml
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape android:shape="rectangle"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<stroke android:width="1dp" android:color="#b3ffffff" />
|
||||
<solid android:color="#66f52727" />
|
||||
<corners android:radius="8dp" />
|
||||
</shape>
|
7
app/src/main/res/drawable/shape_99292929_8.xml
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
|
||||
<corners android:radius="8dp"/>
|
||||
<solid android:color="#99292929"/>
|
||||
</shape>
|
7
app/src/main/res/drawable/shape_e03654_10.xml
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
|
||||
<corners android:radius="10dp"/>
|
||||
<solid android:color="#FFE03654"/>
|
||||
</shape>
|
7
app/src/main/res/drawable/shape_f8f8fa_8.xml
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
|
||||
<corners android:radius="8dp"/>
|
||||
<solid android:color="#F8F8FA"/>
|
||||
</shape>
|
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<corners android:radius="26dp" />
|
||||
<gradient
|
||||
android:angle="0"
|
||||
android:endColor="#FF225C"
|
||||
android:startColor="#FF6060" />
|
||||
</shape>
|
343
app/src/main/res/layout/red_package_open_dialog.xml
Normal file
@@ -0,0 +1,343 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
tools:background="@color/black">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/layout_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginHorizontal="24dp"
|
||||
android:background="@drawable/red_package_open_bg"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintDimensionRatio="h,327:466"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:id="@+id/line_close_top"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintGuide_percent="0.0665" />
|
||||
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:id="@+id/line_send_avatar_top"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintGuide_percent="0.2017" />
|
||||
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:id="@+id/line_tips_top"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintGuide_percent="0.4184" />
|
||||
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:id="@+id/line_btn_top"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintGuide_percent="0.5257" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_close"
|
||||
android:layout_width="44dp"
|
||||
android:layout_height="44dp"
|
||||
android:scaleType="center"
|
||||
android:src="@drawable/red_package_ic_close"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/line_close_top" />
|
||||
|
||||
<com.yizhuan.erban.common.widget.CircleImageView
|
||||
android:id="@+id/iv_send_avatar"
|
||||
android:layout_width="65dp"
|
||||
android:layout_height="65dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/line_send_avatar_top"
|
||||
tools:src="@drawable/default_avatar" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_send_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:ellipsize="end"
|
||||
android:maxWidth="300dp"
|
||||
android:maxLines="1"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="16dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/iv_send_avatar"
|
||||
tools:text="Name" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_open_tips"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="36dp"
|
||||
android:background="@drawable/red_package_open_tips_bg"
|
||||
android:gravity="center"
|
||||
android:paddingHorizontal="5dp"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="11dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/line_tips_top"
|
||||
app:layout_constraintWidth_percent="0.7064"
|
||||
tools:text="恭喜发财!"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/layout_btn"
|
||||
android:layout_width="143dp"
|
||||
android:layout_height="124dp"
|
||||
android:background="@drawable/red_package_open_btn_bg"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/line_btn_top">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_btn_time"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_horizontal"
|
||||
android:maxLines="1"
|
||||
android:text="00:00"
|
||||
android:textColor="@color/color_BF461F"
|
||||
android:textSize="24dp"
|
||||
app:layout_constraintBottom_toTopOf="@id/tv_btn_time_tips"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_chainStyle="packed" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_btn_time_tips"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/red_package_open_btn_await"
|
||||
android:textColor="@color/color_BF461F"
|
||||
android:textSize="12dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_btn_time" />
|
||||
|
||||
<androidx.constraintlayout.widget.Group
|
||||
android:id="@+id/group_btn_time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:constraint_referenced_ids="tv_btn_time,tv_btn_time_tips"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_btn_msg"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:text="@string/red_package_open_btn_msg"
|
||||
android:textColor="@color/color_BF461F"
|
||||
android:textSize="14dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_btn_get"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/red_package_open_btn_get"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<!--待开启状态视图-->
|
||||
<androidx.constraintlayout.widget.Group
|
||||
android:id="@+id/group_open"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:constraint_referenced_ids="layout_btn,iv_send_avatar,tv_send_name"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:id="@+id/line_money_top"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintGuide_percent="0.1909" />
|
||||
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:id="@+id/line_empty_tips_top"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintGuide_percent="0.236" />
|
||||
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:id="@+id/line_result_send_avatar_top"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintGuide_percent="0.3776" />
|
||||
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:id="@+id/line_count_top"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintGuide_percent="0.854" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_money"
|
||||
android:layout_width="34dp"
|
||||
android:layout_height="34dp"
|
||||
android:src="@drawable/red_package_send_ic_diamond"
|
||||
app:layout_constraintEnd_toStartOf="@id/tv_money"
|
||||
app:layout_constraintHorizontal_chainStyle="packed"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/line_money_top" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_money"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="2dp"
|
||||
android:maxLines="1"
|
||||
android:text="0"
|
||||
android:textColor="@color/color_FF285C"
|
||||
android:textSize="32dp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toBottomOf="@id/iv_money"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/iv_money"
|
||||
app:layout_constraintTop_toTopOf="@id/iv_money" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_money_tips"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/red_package_result_money_tips"
|
||||
android:textColor="@color/color_767585"
|
||||
android:textSize="12dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_money" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_result_empty_tips"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/red_package_result_empty_tips"
|
||||
android:textColor="@color/color_767585"
|
||||
android:textSize="12dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/line_empty_tips_top"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<com.yizhuan.erban.common.widget.CircleImageView
|
||||
android:id="@+id/iv_result_send_avatar"
|
||||
android:layout_width="26dp"
|
||||
android:layout_height="26dp"
|
||||
app:cborder_color="@color/white"
|
||||
app:cborder_width="1dp"
|
||||
app:layout_constraintEnd_toStartOf="@id/tv_result_send_name"
|
||||
app:layout_constraintHorizontal_chainStyle="packed"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/line_result_send_avatar_top"
|
||||
tools:src="@drawable/default_avatar" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_result_send_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="3dp"
|
||||
android:maxLines="1"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="14dp"
|
||||
app:layout_constraintBottom_toBottomOf="@id/iv_result_send_avatar"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/iv_result_send_avatar"
|
||||
app:layout_constraintTop_toTopOf="@id/iv_result_send_avatar"
|
||||
tools:text="Name" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_message"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="10dp"
|
||||
android:layout_marginTop="3dp"
|
||||
android:alpha="90"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:text="@string/red_package_msg_def"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="14dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/iv_result_send_avatar" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_count"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:alpha="0.8"
|
||||
android:text="@string/red_package_result_count_format"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="10dp"
|
||||
app:layout_constraintEnd_toEndOf="@id/recyclerView"
|
||||
app:layout_constraintTop_toBottomOf="@id/line_count_top" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recyclerView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:background="@drawable/shape_e03654_10"
|
||||
android:orientation="vertical"
|
||||
android:scrollbars="none"
|
||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||
app:layout_constraintBottom_toTopOf="@id/tv_count"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_message"
|
||||
app:layout_constraintWidth_percent="0.6819"
|
||||
tools:listitem="@layout/red_package_open_item_result" />
|
||||
|
||||
<androidx.constraintlayout.widget.Group
|
||||
android:id="@+id/group_result_money"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
app:constraint_referenced_ids="tv_money,tv_money_tips,iv_money"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<androidx.constraintlayout.widget.Group
|
||||
android:id="@+id/group_result"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
app:constraint_referenced_ids="recyclerView,tv_count,tv_message,tv_result_send_name,iv_result_send_avatar"
|
||||
tools:visibility="gone" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
91
app/src/main/res/layout/red_package_open_item_result.xml
Normal file
@@ -0,0 +1,91 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/layout_root"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
tools:background="@color/black">
|
||||
|
||||
<com.yizhuan.erban.common.widget.CircleImageView
|
||||
android:id="@+id/iv_avatar"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:layout_marginStart="15dp"
|
||||
app:cborder_color="@color/white"
|
||||
app:cborder_width="1dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:src="@drawable/default_avatar" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_name"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="5dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:ellipsize="end"
|
||||
android:textColor="@color/color_white"
|
||||
android:textSize="12dp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toTopOf="@id/tv_time"
|
||||
app:layout_constraintEnd_toStartOf="@id/iv_money"
|
||||
app:layout_constraintStart_toEndOf="@id/iv_avatar"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_chainStyle="packed"
|
||||
tools:text="Name" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_time"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textColor="@color/color_white_60"
|
||||
android:textSize="9dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="@id/tv_name"
|
||||
app:layout_constraintStart_toStartOf="@id/tv_name"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_name"
|
||||
tools:text="10月23日 12:00" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_money"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="15dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="16dp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="0" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_money"
|
||||
android:layout_width="19dp"
|
||||
android:layout_height="19dp"
|
||||
android:layout_marginEnd="1dp"
|
||||
android:src="@drawable/red_package_send_ic_diamond"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/tv_money"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<View
|
||||
android:id="@+id/v_line"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="2px"
|
||||
android:layout_marginHorizontal="14dp"
|
||||
android:background="@color/color_ffffff_30"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
225
app/src/main/res/layout/red_package_private_fragment.xml
Normal file
@@ -0,0 +1,225 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingBottom="24dp">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et_money"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginHorizontal="24dp"
|
||||
android:background="@drawable/shape_f8f8fa_8"
|
||||
android:gravity="end|center_vertical"
|
||||
android:hint="0"
|
||||
android:inputType="number"
|
||||
android:paddingEnd="59dp"
|
||||
android:singleLine="true"
|
||||
android:textColor="@color/color_322F4D"
|
||||
android:textColorHint="@color/color_B3B3C3"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_money"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="9dp"
|
||||
android:src="@drawable/red_package_send_ic"
|
||||
app:layout_constraintBottom_toBottomOf="@id/et_money"
|
||||
app:layout_constraintStart_toStartOf="@id/et_money"
|
||||
app:layout_constraintTop_toTopOf="@id/et_money" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="1dp"
|
||||
android:text="@string/red_package_money"
|
||||
android:textColor="@color/color_322F4D"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintBottom_toBottomOf="@id/et_money"
|
||||
app:layout_constraintStart_toEndOf="@id/iv_money"
|
||||
app:layout_constraintTop_toTopOf="@id/et_money" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_money_unit"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:text="@string/red_package_money_unit"
|
||||
android:textColor="@color/color_767585"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintBottom_toBottomOf="@id/et_money"
|
||||
app:layout_constraintEnd_toEndOf="@id/et_money"
|
||||
app:layout_constraintTop_toTopOf="@id/et_money" />
|
||||
|
||||
<View
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="26dp"
|
||||
android:layout_marginEnd="14dp"
|
||||
android:background="@color/color_EBEEF5"
|
||||
app:layout_constraintBottom_toBottomOf="@id/et_money"
|
||||
app:layout_constraintEnd_toStartOf="@id/tv_money_unit"
|
||||
app:layout_constraintTop_toTopOf="@id/et_money" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et_num"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginHorizontal="24dp"
|
||||
android:layout_marginTop="12dp"
|
||||
android:background="@drawable/shape_f8f8fa_8"
|
||||
android:gravity="end|center_vertical"
|
||||
android:hint="0"
|
||||
android:inputType="number"
|
||||
android:paddingEnd="59dp"
|
||||
android:singleLine="true"
|
||||
android:textColor="@color/color_322F4D"
|
||||
android:textColorHint="@color/color_B3B3C3"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/et_money" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:text="@string/red_package_num"
|
||||
android:textColor="@color/color_322F4D"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintBottom_toBottomOf="@id/et_num"
|
||||
app:layout_constraintStart_toStartOf="@id/et_num"
|
||||
app:layout_constraintTop_toTopOf="@id/et_num" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_num_unit"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:text="@string/red_package_num_unit"
|
||||
android:textColor="@color/color_767585"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintBottom_toBottomOf="@id/et_num"
|
||||
app:layout_constraintEnd_toEndOf="@id/et_num"
|
||||
app:layout_constraintTop_toTopOf="@id/et_num" />
|
||||
|
||||
<View
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="26dp"
|
||||
android:layout_marginEnd="14dp"
|
||||
android:background="@color/color_EBEEF5"
|
||||
app:layout_constraintBottom_toBottomOf="@id/et_num"
|
||||
app:layout_constraintEnd_toStartOf="@id/tv_num_unit"
|
||||
app:layout_constraintTop_toTopOf="@id/et_num" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_type"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="24dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="@string/red_package_type"
|
||||
android:textColor="@color/color_322F4D"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/et_num" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recyclerView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="62dp"
|
||||
android:layout_marginStart="24dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:clipToPadding="false"
|
||||
android:orientation="horizontal"
|
||||
android:paddingEnd="6dp"
|
||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_type" />
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/layout_parameter"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="52dp"
|
||||
android:layout_marginTop="12dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/recyclerView">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_now"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="52dp"
|
||||
android:layout_marginStart="24dp"
|
||||
android:background="@drawable/shape_f8f8fa_8"
|
||||
android:gravity="center"
|
||||
android:text="@string/red_package_now"
|
||||
android:textColor="@color/color_FF285C"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintEnd_toStartOf="@id/tv_delay"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_delay"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="52dp"
|
||||
android:layout_marginStart="19dp"
|
||||
android:layout_marginEnd="24dp"
|
||||
android:background="@drawable/shape_f8f8fa_8"
|
||||
android:gravity="center"
|
||||
android:text="@string/red_package_delay"
|
||||
android:textColor="@color/color_FF285C"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/tv_now"
|
||||
app:layout_constraintTop_toTopOf="@id/tv_now" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="52dp"
|
||||
android:layout_marginHorizontal="24dp"
|
||||
android:background="@drawable/shape_f8f8fa_8"
|
||||
android:gravity="center"
|
||||
android:hint="@string/red_package_msg_hint"
|
||||
android:maxLength="10"
|
||||
android:singleLine="true"
|
||||
android:textColor="@color/color_322F4D"
|
||||
android:textColorHint="@color/color_B3B3C3"
|
||||
android:textSize="16sp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_send"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="52dp"
|
||||
android:layout_marginHorizontal="40dp"
|
||||
android:layout_marginTop="28dp"
|
||||
android:background="@drawable/shape_g_ff6060_ff225c_26_lr"
|
||||
android:gravity="center"
|
||||
android:text="@string/red_package_send"
|
||||
android:textColor="@color/color_FFFFFF"
|
||||
android:textSize="18sp"
|
||||
app:layout_constraintTop_toBottomOf="@id/layout_parameter" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
android:text="@string/red_package_tips"
|
||||
android:textColor="@color/color_94959C"
|
||||
android:textSize="12sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_send" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
36
app/src/main/res/layout/red_package_private_item_type.xml
Normal file
@@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/layout_root"
|
||||
android:background="@drawable/shape_f8f8fa_8"
|
||||
android:layout_width="94dp"
|
||||
android:layout_height="62dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:textColor="@color/color_767585"
|
||||
android:textSize="12dp"
|
||||
app:layout_constraintBottom_toTopOf="@id/tv_tips"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_chainStyle="packed"
|
||||
tools:text="Name" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_tips"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:textColor="@color/color_94959C"
|
||||
android:textSize="10dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_name"
|
||||
tools:text="Tips" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
175
app/src/main/res/layout/red_package_public_fragment.xml
Normal file
@@ -0,0 +1,175 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingBottom="24dp">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et_money"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginHorizontal="24dp"
|
||||
android:background="@drawable/shape_f8f8fa_8"
|
||||
android:gravity="end|center_vertical"
|
||||
android:hint="0"
|
||||
android:inputType="number"
|
||||
android:paddingEnd="59dp"
|
||||
android:singleLine="true"
|
||||
android:textColor="@color/color_322F4D"
|
||||
android:textColorHint="@color/color_B3B3C3"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_money"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="9dp"
|
||||
android:src="@drawable/red_package_send_ic"
|
||||
app:layout_constraintBottom_toBottomOf="@id/et_money"
|
||||
app:layout_constraintStart_toStartOf="@id/et_money"
|
||||
app:layout_constraintTop_toTopOf="@id/et_money" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="1dp"
|
||||
android:text="@string/red_package_money"
|
||||
android:textColor="@color/color_322F4D"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintBottom_toBottomOf="@id/et_money"
|
||||
app:layout_constraintStart_toEndOf="@id/iv_money"
|
||||
app:layout_constraintTop_toTopOf="@id/et_money" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_money_unit"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:text="@string/red_package_money_unit"
|
||||
android:textColor="@color/color_767585"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintBottom_toBottomOf="@id/et_money"
|
||||
app:layout_constraintEnd_toEndOf="@id/et_money"
|
||||
app:layout_constraintTop_toTopOf="@id/et_money" />
|
||||
|
||||
<View
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="26dp"
|
||||
android:layout_marginEnd="14dp"
|
||||
android:background="@color/color_EBEEF5"
|
||||
app:layout_constraintBottom_toBottomOf="@id/et_money"
|
||||
app:layout_constraintEnd_toStartOf="@id/tv_money_unit"
|
||||
app:layout_constraintTop_toTopOf="@id/et_money" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et_num"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginHorizontal="24dp"
|
||||
android:layout_marginTop="12dp"
|
||||
android:background="@drawable/shape_f8f8fa_8"
|
||||
android:gravity="end|center_vertical"
|
||||
android:hint="0"
|
||||
android:inputType="number"
|
||||
android:paddingEnd="59dp"
|
||||
android:singleLine="true"
|
||||
android:textColor="@color/color_322F4D"
|
||||
android:textColorHint="@color/color_B3B3C3"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/et_money" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:text="@string/red_package_num"
|
||||
android:textColor="@color/color_322F4D"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintBottom_toBottomOf="@id/et_num"
|
||||
app:layout_constraintStart_toStartOf="@id/et_num"
|
||||
app:layout_constraintTop_toTopOf="@id/et_num" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_num_unit"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:text="@string/red_package_num_unit"
|
||||
android:textColor="@color/color_767585"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintBottom_toBottomOf="@id/et_num"
|
||||
app:layout_constraintEnd_toEndOf="@id/et_num"
|
||||
app:layout_constraintTop_toTopOf="@id/et_num" />
|
||||
|
||||
<View
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="26dp"
|
||||
android:layout_marginEnd="14dp"
|
||||
android:background="@color/color_EBEEF5"
|
||||
app:layout_constraintBottom_toBottomOf="@id/et_num"
|
||||
app:layout_constraintEnd_toStartOf="@id/tv_num_unit"
|
||||
app:layout_constraintTop_toTopOf="@id/et_num" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="76dp"
|
||||
android:layout_marginHorizontal="24dp"
|
||||
android:layout_marginTop="24dp"
|
||||
android:background="@drawable/shape_f8f8fa_8"
|
||||
android:gravity="center"
|
||||
android:maxLength="20"
|
||||
android:paddingHorizontal="10dp"
|
||||
android:paddingVertical="10dp"
|
||||
android:hint="@string/red_package_msg_def"
|
||||
android:textColorHint="@color/color_B3B3C3"
|
||||
android:textColor="@color/color_322F4D"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintTop_toBottomOf="@id/et_num" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_text_length"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:text="0/20"
|
||||
android:textColor="@color/color_94959C"
|
||||
android:textSize="12sp"
|
||||
app:layout_constraintBottom_toBottomOf="@id/et_text"
|
||||
app:layout_constraintEnd_toEndOf="@id/et_text" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_send"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="52dp"
|
||||
android:layout_marginHorizontal="40dp"
|
||||
android:layout_marginTop="28dp"
|
||||
android:gravity="center"
|
||||
android:background="@drawable/shape_g_ff6060_ff225c_26_lr"
|
||||
android:text="@string/red_package_send"
|
||||
android:textColor="@color/color_FFFFFF"
|
||||
android:textSize="18sp"
|
||||
app:layout_constraintTop_toBottomOf="@id/et_text" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
android:text="@string/red_package_tips"
|
||||
android:textColor="@color/color_94959C"
|
||||
android:textSize="12sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_send" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
88
app/src/main/res/layout/red_package_send_dialog.xml
Normal file
@@ -0,0 +1,88 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:background="@color/white"
|
||||
app:layout_constraintBottom_toBottomOf="@id/viewPager"
|
||||
app:layout_constraintTop_toTopOf="@id/viewPager" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_top"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:adjustViewBounds="true"
|
||||
android:src="@drawable/red_package_send_bg"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<com.yizhuan.erban.ui.widget.magicindicator.MagicIndicator
|
||||
android:id="@+id/tab_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="30dp"
|
||||
android:layout_marginHorizontal="20dp"
|
||||
android:layout_marginTop="170dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/iv_top" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_help"
|
||||
android:layout_width="44dp"
|
||||
android:layout_height="44dp"
|
||||
android:layout_marginTop="64dp"
|
||||
android:layout_marginEnd="2dp"
|
||||
android:scaleType="center"
|
||||
android:src="@drawable/red_package_ic_help"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/iv_top" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_balance"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="30dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:background="@drawable/red_package_bg_balance"
|
||||
android:gravity="center"
|
||||
android:paddingStart="25dp"
|
||||
android:paddingEnd="23dp"
|
||||
android:text="0"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="13sp"
|
||||
app:layout_constraintBottom_toTopOf="@id/tab_layout"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="21dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="2dp"
|
||||
android:scaleType="center"
|
||||
android:src="@drawable/red_package_ic_add"
|
||||
app:layout_constraintBottom_toBottomOf="@id/tv_balance"
|
||||
app:layout_constraintEnd_toEndOf="@id/tv_balance"
|
||||
app:layout_constraintTop_toTopOf="@id/tv_balance" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="5dp"
|
||||
android:scaleType="center"
|
||||
android:src="@drawable/red_package_send_ic_diamond"
|
||||
app:layout_constraintBottom_toBottomOf="@id/tv_balance"
|
||||
app:layout_constraintStart_toStartOf="@id/tv_balance"
|
||||
app:layout_constraintTop_toTopOf="@id/tv_balance" />
|
||||
|
||||
<com.yizhuan.erban.view.WrapHeightViewPager
|
||||
android:id="@+id/viewPager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/tab_layout" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
43
app/src/main/res/layout/red_package_widget.xml
Normal file
@@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/red_package_widget_bg"
|
||||
tools:layout_height="58dp"
|
||||
tools:layout_width="58dp"
|
||||
tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_text"
|
||||
android:layout_width="36dp"
|
||||
android:layout_height="15dp"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:background="@drawable/red_package_widget_bg_text"
|
||||
android:gravity="center"
|
||||
android:includeFontPadding="false"
|
||||
android:text="@string/red_package_widget_get"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="9dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_num"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="12dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:background="@drawable/red_package_bg_num"
|
||||
android:gravity="center"
|
||||
android:includeFontPadding="false"
|
||||
android:minWidth="12dp"
|
||||
android:paddingHorizontal="3dp"
|
||||
android:text="1"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="9dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
</merge>
|
@@ -703,5 +703,11 @@
|
||||
<color name="color_1E686868">#1E686868</color>
|
||||
<color name="color_9E9EA8">#9E9EA8</color>
|
||||
<color name="color_001338">#001338</color>
|
||||
|
||||
<color name="color_FF285C">#FF285C</color>
|
||||
<color name="color_322F4D">#322F4D</color>
|
||||
<color name="color_EBEEF5">#EBEEF5</color>
|
||||
<color name="color_94959C">#94959C</color>
|
||||
<color name="color_BF461F">#FFBF461F</color>
|
||||
<color name="color_FFF87A">#FFFFF87A</color>
|
||||
<color name="color_ffffff_30">#4CFFFFFF</color>
|
||||
</resources>
|
||||
|
@@ -5143,4 +5143,44 @@
|
||||
<string name="room_album_type_no_need_unlocked_gift_tips">當前無需選擇解鎖禮物</string>
|
||||
<string name="room_album_type_choose_unlocked_gift_tips">選擇解鎖禮物</string>
|
||||
|
||||
<string name="red_package_type_unlimited_name">無門檻紅包</string>
|
||||
<string name="red_package_type_unlimited_tips">所有人均可參與</string>
|
||||
<string name="red_package_type_follow_name">關註紅包</string>
|
||||
<string name="red_package_type_follow_tips">關註主播可參與</string>
|
||||
<string name="red_package_type_share_name">分享紅包</string>
|
||||
<string name="red_package_type_share_tips">分享房間可參與</string>
|
||||
<string name="red_package_type_msg_name">發彈幕紅包</string>
|
||||
<string name="red_package_type_msg_tips">發指定彈幕內容</string>
|
||||
|
||||
<string name="red_package_room">廳內紅包</string>
|
||||
<string name="red_package_public">全服紅包</string>
|
||||
<string name="red_package_money">紅包金額</string>
|
||||
<string name="red_package_num">紅包數量</string>
|
||||
<string name="red_package_money_unit">鉆</string>
|
||||
<string name="red_package_num_unit">個</string>
|
||||
<string name="red_package_type">搶紅包條件</string>
|
||||
<string name="red_package_msg_hint">輸入指定彈幕內容(最多10個字符)</string>
|
||||
<string name="red_package_send">發紅包</string>
|
||||
<string name="red_package_tips">未搶完的紅包將在12小時後返還你的錢包</string>
|
||||
<string name="red_package_now">立即生效</string>
|
||||
<string name="red_package_delay">限時生效</string>
|
||||
<string name="red_package_msg_def">恭喜發財,大吉大利!</string>
|
||||
<string name="red_package_open_btn_await">後開搶</string>
|
||||
<string name="red_package_open_btn_msg">發彈幕\n搶紅包</string>
|
||||
<string name="red_package_open_btn_share">分享房間\n搶紅包</string>
|
||||
<string name="red_package_open_btn_follow">關注主播\n搶紅包</string>
|
||||
<string name="red_package_open_btn_no">未參與活動</string>
|
||||
<string name="red_package_open_no_tips">未參與活動,無法搶該紅包</string>
|
||||
<string name="red_package_result_money_tips">已存入錢包,請到我的收益確認</string>
|
||||
<string name="red_package_result_count_format">已領取%s/%s個</string>
|
||||
<string name="red_package_widget_get">搶紅包</string>
|
||||
<string name="red_package_msg_empty_tips">請輸入彈幕內容</string>
|
||||
<string name="red_package_open_tips_follow">關注主播</string>
|
||||
<string name="red_package_open_tips_share">对外分享房間</string>
|
||||
<string name="red_package_open_tips_msg1">發送彈幕</string>
|
||||
<string name="red_package_open_tips_msg_end">可搶紅包</string>
|
||||
<string name="red_package_result_empty_tips">搶完了,下次早點來哦~</string>
|
||||
<string name="red_package_disabled_tips">該紅包已失效</string>
|
||||
”
|
||||
|
||||
</resources>
|
@@ -229,20 +229,33 @@
|
||||
android:onClick="@{click}"
|
||||
android:src="@drawable/ic_first_charge_enter"
|
||||
android:visibility="gone"
|
||||
tools:contentDescription="@string/layout_fragment_av_room_game_02" />
|
||||
tools:contentDescription="@string/layout_fragment_av_room_game_02"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_radish_entrance"
|
||||
android:layout_width="65dp"
|
||||
android:layout_height="65dp"
|
||||
android:layout_above="@id/iv_treasure_box"
|
||||
android:layout_above="@id/red_package_widget"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_marginEnd="15dp"
|
||||
android:layout_marginBottom="6dp"
|
||||
android:onClick="@{click}"
|
||||
android:src="@drawable/ic_radish_entrance"
|
||||
android:visibility="gone"
|
||||
tools:contentDescription="@string/layout_fragment_av_room_game_03" />
|
||||
tools:contentDescription="@string/layout_fragment_av_room_game_03"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<com.yizhuan.erban.avroom.redpackage.RedPackageWidget
|
||||
android:id="@+id/red_package_widget"
|
||||
android:layout_width="58dp"
|
||||
android:layout_height="58dp"
|
||||
android:layout_above="@id/iv_treasure_box"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_marginEnd="18.5dp"
|
||||
android:layout_marginBottom="6dp"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_treasure_box"
|
||||
@@ -255,7 +268,8 @@
|
||||
android:onClick="@{click}"
|
||||
android:src="@drawable/icon_room_treasure_box"
|
||||
android:visibility="gone"
|
||||
tools:contentDescription="@string/layout_fragment_av_room_game_04" />
|
||||
tools:contentDescription="@string/layout_fragment_av_room_game_04"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_queuing_micro"
|
||||
@@ -269,7 +283,8 @@
|
||||
android:onClick="@{click}"
|
||||
android:src="@drawable/ic_dating_queuing_micro"
|
||||
android:visibility="gone"
|
||||
tools:contentDescription="@string/layout_fragment_av_room_game_05" />
|
||||
tools:contentDescription="@string/layout_fragment_av_room_game_05"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
|
@@ -100,24 +100,25 @@
|
||||
android:id="@+id/contribute_list"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="20dp"
|
||||
android:layout_marginTop="85dp"
|
||||
android:background="@drawable/bg_single_room_rank_entrance"
|
||||
android:drawablePadding="@dimen/dp_2"
|
||||
android:gravity="center"
|
||||
android:onClick="@{click}"
|
||||
android:paddingStart="@dimen/dp_8"
|
||||
android:paddingEnd="@dimen/dp_4"
|
||||
android:layout_marginTop="85dp"
|
||||
android:text="@string/room_host_list"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="@dimen/sp_10"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:drawableStartCompat="@drawable/ic_sing_room_contribute_list"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:drawableStartCompat="@drawable/ic_sing_room_contribute_list" />
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_hour_rank"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="20dp"
|
||||
android:layout_marginTop="@dimen/dp_8"
|
||||
android:background="@drawable/bg_single_room_rank_entrance"
|
||||
android:drawablePadding="@dimen/dp_2"
|
||||
android:gravity="center"
|
||||
@@ -126,7 +127,6 @@
|
||||
android:text="@string/room_list_hour"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="@dimen/sp_10"
|
||||
android:layout_marginTop="@dimen/dp_8"
|
||||
app:drawableStartCompat="@drawable/ic_single_room_rank"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/contribute_list" />
|
||||
@@ -201,10 +201,20 @@
|
||||
android:onClick="@{click}"
|
||||
android:src="@drawable/ic_radish_entrance"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toTopOf="@id/iv_treasure_box"
|
||||
tools:visibility="visible"
|
||||
app:layout_constraintBottom_toTopOf="@id/red_package_widget"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
tools:contentDescription="@string/layout_fragment_single_room_06" />
|
||||
|
||||
<com.yizhuan.erban.avroom.redpackage.RedPackageWidget
|
||||
android:id="@+id/red_package_widget"
|
||||
android:layout_width="58dp"
|
||||
android:layout_height="58dp"
|
||||
android:layout_marginBottom="6dp"
|
||||
app:layout_constraintBottom_toTopOf="@id/iv_treasure_box"
|
||||
app:layout_constraintEnd_toEndOf="@id/iv_treasure_box"
|
||||
app:layout_constraintStart_toStartOf="@id/iv_treasure_box" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_treasure_box"
|
||||
android:layout_width="65dp"
|
||||
@@ -216,7 +226,8 @@
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toTopOf="@id/fl_speedy_message"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
tools:contentDescription="@string/layout_fragment_single_room_07" />
|
||||
tools:contentDescription="@string/layout_fragment_single_room_07"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<com.yizhuan.erban.avroom.widget.MessageView
|
||||
android:id="@+id/message_view"
|
||||
|
@@ -0,0 +1,7 @@
|
||||
package com.yizhuan.xchat_android_core.home.event
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/10/27 11:56
|
||||
* Desc:打开公屏输入
|
||||
**/
|
||||
class OpenRoomMessageInputEvent(val text: String? = null)
|
@@ -99,6 +99,7 @@ import com.yizhuan.xchat_android_core.im.custom.bean.MonsterHuntingResultAttachm
|
||||
import com.yizhuan.xchat_android_core.im.custom.bean.MonsterStatusAttachment;
|
||||
import com.yizhuan.xchat_android_core.im.custom.bean.MultiGiftAttachment;
|
||||
import com.yizhuan.xchat_android_core.im.custom.bean.NobleAttachment;
|
||||
import com.yizhuan.xchat_android_core.im.custom.bean.RedPackageAttachment;
|
||||
import com.yizhuan.xchat_android_core.im.custom.bean.RoomBoxPrizeAttachment;
|
||||
import com.yizhuan.xchat_android_core.im.custom.bean.RoomFreeGiftAttachment;
|
||||
import com.yizhuan.xchat_android_core.im.custom.bean.RoomFreeGiftMsgBean;
|
||||
@@ -1148,12 +1149,17 @@ public final class IMNetEaseManager {
|
||||
|
||||
case CustomAttachment.CUSTOM_MSG_RED_PACKAGE:
|
||||
switch (second) {
|
||||
// 老版本厅内红包(2.2.0之前)
|
||||
case CUSTOM_MSG_SUB_RED_PACKAGE_RECEIVE_ROOM_DIAMOND:
|
||||
noticeRoomEvent(msg, RoomEvent.RECEIVE_RED_PACKAGE);
|
||||
break;
|
||||
case CUSTOM_MSG_SUB_RED_PACKAGE_RECEIVE_ROOM_MSG:
|
||||
addMessages(msg);
|
||||
break;
|
||||
// 新版厅内红包(>=2.2.0版本)
|
||||
case CUSTOM_MSG_SUB_RED_PACKAGE_RECEIVE_ROOM_DIAMOND2:
|
||||
noticeRoomEvent(msg, RoomEvent.RECEIVE_RED_PACKAGE);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@@ -64,6 +64,7 @@ import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUS
|
||||
import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MSG_SUB_PUBLIC_CHAT_HALL_GIFT;
|
||||
import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MSG_SUB_RED_PACKAGE_RECEIVE_ALL_DIAMOND;
|
||||
import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MSG_SUB_RED_PACKAGE_RECEIVE_ROOM_DIAMOND;
|
||||
import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MSG_SUB_RED_PACKAGE_RECEIVE_ROOM_DIAMOND2;
|
||||
import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MSG_SUB_RED_PACKAGE_RECEIVE_ROOM_MSG;
|
||||
import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MSG_SUB_TYPE_DRAW_GIFT_EFFECT;
|
||||
import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MSG_SUB_TYPE_RECEIVE_LUCKY_MONEY;
|
||||
@@ -458,6 +459,7 @@ public class CustomAttachParser implements MsgAttachmentParser {
|
||||
switch (second) {
|
||||
case CUSTOM_MSG_SUB_RED_PACKAGE_RECEIVE_ROOM_DIAMOND:
|
||||
case CUSTOM_MSG_SUB_RED_PACKAGE_RECEIVE_ALL_DIAMOND:
|
||||
case CUSTOM_MSG_SUB_RED_PACKAGE_RECEIVE_ROOM_DIAMOND2:
|
||||
attachment = new RedPackageAttachment(second);
|
||||
break;
|
||||
case CUSTOM_MSG_SUB_RED_PACKAGE_RECEIVE_ROOM_MSG:
|
||||
|
@@ -317,6 +317,7 @@ public class CustomAttachment implements MsgAttachment {
|
||||
public static final int CUSTOM_MSG_SUB_RED_PACKAGE_RECEIVE_ROOM_DIAMOND = 602;
|
||||
public static final int CUSTOM_MSG_SUB_RED_PACKAGE_RECEIVE_ALL_DIAMOND = 604;//全服红包
|
||||
public static final int CUSTOM_MSG_SUB_RED_PACKAGE_RECEIVE_ROOM_MSG = 605;
|
||||
public static final int CUSTOM_MSG_SUB_RED_PACKAGE_RECEIVE_ROOM_DIAMOND2 = 606;//新版本-厅内红包
|
||||
//开福袋飘屏
|
||||
public static final int CUSTOM_MSG_LUCKY_GIFT = 61;
|
||||
public static final int CUSTOM_MSG_LUCKY_GIFT_ROOM_NOTIFY = 610;// 福袋礼物房间飘屏通知
|
||||
|
@@ -14,7 +14,7 @@ import lombok.EqualsAndHashCode;
|
||||
@Data
|
||||
public class RedPackageAttachment extends CustomAttachment {
|
||||
|
||||
private RedPackageNotifyInfo redPackageNotifyInfo;
|
||||
public RedPackageNotifyInfo redPackageNotifyInfo;
|
||||
|
||||
public RedPackageAttachment(int second) {
|
||||
super(CUSTOM_MSG_RED_PACKAGE, second);
|
||||
|
@@ -0,0 +1,57 @@
|
||||
package com.yizhuan.xchat_android_core.interceptor
|
||||
|
||||
import com.chuhai.utils.AppUtils
|
||||
import com.chuhai.utils.ServiceTime
|
||||
import com.yizhuan.xchat_android_core.utils.LogUtils
|
||||
import com.yizhuan.xchat_android_library.utils.NetworkUtils
|
||||
import okhttp3.Headers
|
||||
import okhttp3.Interceptor
|
||||
import okhttp3.Response
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/10/25 14:17 AM
|
||||
* Desc:服务器时间同步器
|
||||
*/
|
||||
class TimeSyncInterceptor : Interceptor {
|
||||
|
||||
private var minResponseTime = Long.MAX_VALUE
|
||||
|
||||
override fun intercept(chain: Interceptor.Chain): Response {
|
||||
val request = chain.request()
|
||||
val startTime = System.nanoTime()
|
||||
val proceed = chain.proceed(request)
|
||||
val lastTime = System.nanoTime() - startTime
|
||||
val headers = proceed.headers
|
||||
calibration(lastTime, headers)
|
||||
return proceed
|
||||
}
|
||||
|
||||
private fun calibration(responseTime: Long, headers: Headers?) {
|
||||
if (headers == null) {
|
||||
return
|
||||
}
|
||||
|
||||
//如果这一次的请求响应时间小于上一次,则更新本地维护的时间
|
||||
if (responseTime >= minResponseTime) {
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
// 网络无法使用时,不能同步时间
|
||||
if (!NetworkUtils.isNetworkAvailable(AppUtils.getApp())) {
|
||||
return
|
||||
}
|
||||
// 网络响应头包含Date字段(世界时间)
|
||||
// 利用Interceptor记录每次请求响应时间,如果本次网络操作的时间小于上一次网络操作的时间,则获取Date字段,转换时区后更新本地
|
||||
val date = headers.getDate("Date")
|
||||
LogUtils.d("TimeSyncInterceptor date:$date time:${date?.time}")
|
||||
date?.let {
|
||||
//客户端请求过程一般大于比收到响应时间耗时,所以没有简单的除2 加上去,而是直接用该时间
|
||||
ServiceTime.refreshServiceTime(it.time)
|
||||
minResponseTime = responseTime
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
@@ -39,6 +39,7 @@ import com.yizhuan.xchat_android_core.room.game.GameStatus;
|
||||
import com.yizhuan.xchat_android_core.room.giftvalue.helper.GiftValueMrg;
|
||||
import com.yizhuan.xchat_android_core.super_admin.SuperAdminDataMrg;
|
||||
import com.yizhuan.xchat_android_core.super_admin.util.SuperAdminUtil;
|
||||
import com.yizhuan.xchat_android_core.support.room.RoomContext;
|
||||
import com.yizhuan.xchat_android_core.user.UserModel;
|
||||
import com.yizhuan.xchat_android_core.utils.CurrentTimeUtils;
|
||||
import com.yizhuan.xchat_android_core.utils.LogUtils;
|
||||
@@ -261,6 +262,10 @@ public final class AvRoomDataManager {
|
||||
kickOutRoomUids.clear();
|
||||
kickOutRoomUids = null;
|
||||
}
|
||||
RoomContext context = RoomContext.Companion.get();
|
||||
if (context != null) {
|
||||
context.performStop();
|
||||
}
|
||||
LogUtils.d(ResUtil.getString(R.string.xchat_android_core_manager_avroomdatamanager_05));
|
||||
}
|
||||
|
||||
|
@@ -4,20 +4,32 @@ import com.yizhuan.xchat_android_core.community.UserVo
|
||||
|
||||
|
||||
data class RedEnvelopeVO(
|
||||
var beginTime: Long = 0,
|
||||
var createTime: Long = 0,
|
||||
var endTime: Long = 0,
|
||||
var id: String,
|
||||
var message: String,
|
||||
var redEnvelopeAmount: Double = 0.0,
|
||||
var roomUId: Long = 0,
|
||||
/**
|
||||
* 红包类型 1:房间水晶红包 2:全服水晶红包 3:房间礼物红包 4:全服礼物红包
|
||||
*/
|
||||
var type: Int = 0,
|
||||
var updateTime: Long = 0,
|
||||
var userId: Long = 0,
|
||||
var totalNum: String = "",
|
||||
var pickNum: String = "",
|
||||
var userVO: UserVo? = null
|
||||
var beginTime: Long = 0,
|
||||
var createTime: Long = 0,
|
||||
var endTime: Long = 0,
|
||||
var id: String,
|
||||
var message: String,
|
||||
var redEnvelopeAmount: Double = 0.0,
|
||||
var roomUId: Long = 0,
|
||||
/**
|
||||
* 红包类型 1:房间水晶红包 2:全服水晶红包 3:房间礼物红包 4:全服礼物红包
|
||||
*/
|
||||
var type: Int = 0,
|
||||
var updateTime: Long = 0,
|
||||
var userId: Long = 0,
|
||||
var totalNum: Long = 0,
|
||||
var pickNum: Long = 0,
|
||||
var userVO: UserVo? = null,
|
||||
/**
|
||||
* 红包种类 0 旧版本 1 无门槛红包 2 关注红包 3 分享红包 4 弹幕红包
|
||||
*/
|
||||
var kind: Int = 0,
|
||||
/**
|
||||
* 生效类型 0 立即生效 1 限时生效
|
||||
*/
|
||||
var validityType: Int = 0,
|
||||
/**
|
||||
* 红包状态 1 开抢中 2 过时 3 抢光了 4 抢到了 5 将要开始 6 超时已退还
|
||||
*/
|
||||
var state: Int?
|
||||
)
|
@@ -0,0 +1,36 @@
|
||||
package com.yizhuan.xchat_android_core.redpackage
|
||||
|
||||
import java.io.Serializable
|
||||
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/10/24 16:37
|
||||
* Desc:红包数据
|
||||
**/
|
||||
data class RedPackageData(
|
||||
val amount: Double?,
|
||||
val avatar: String?,
|
||||
val beginTime: Long?,
|
||||
val commissionAmount: Long?,
|
||||
val createTime: Long?,
|
||||
val duration: Long?,
|
||||
val endTime: Long?,
|
||||
val finish: Boolean?,
|
||||
val id: Long?,
|
||||
val kind: Int?,
|
||||
val message: String?,
|
||||
val nick: String?,
|
||||
val num: Long?,
|
||||
val originalAmount: Long?,
|
||||
val position: String?,
|
||||
val roomTitle: String?,
|
||||
val roomUid: Long?,
|
||||
//红包状态 1 开抢中 2 过时 3 抢光了 4 抢到了 5 将要开始 6 超时已退还
|
||||
val state: Int?,
|
||||
val type: String?,
|
||||
val updateTime: Long?,
|
||||
val userId: Long?,
|
||||
val validityType: Int?,
|
||||
// 结果
|
||||
val result: RedPackageInfo?
|
||||
) : Serializable
|
@@ -2,17 +2,19 @@ package com.yizhuan.xchat_android_core.redpackage
|
||||
|
||||
|
||||
data class RedPackageInfo(
|
||||
var redEnvelopeItemVOs: List<RedEnvelopeItemVO>? = null,
|
||||
var redEnvelopeVO: RedEnvelopeVO? = null,
|
||||
var redEnvelopeItemVOs: List<RedEnvelopeItemVO>? = null,
|
||||
var redEnvelopeVO: RedEnvelopeVO? = null,
|
||||
|
||||
/**
|
||||
* ING(1, “开抢中”)
|
||||
* TIME_OUT(2, “过时”)
|
||||
* REMAIN_ZERO(3, “抢光了”)
|
||||
* SUCCESS(4, “抢到了”)
|
||||
* WILL(5, “将要开始”)
|
||||
* TIME_OUT_BACK(6, “超时已退还”)
|
||||
*/
|
||||
var redEnvelopeState: Int = 0
|
||||
/**
|
||||
* ING(1, “开抢中”)
|
||||
* TIME_OUT(2, “过时”)
|
||||
* REMAIN_ZERO(3, “抢光了”)
|
||||
* SUCCESS(4, “抢到了”)
|
||||
* WILL(5, “将要开始”)
|
||||
* TIME_OUT_BACK(6, “超时已退还”)
|
||||
*/
|
||||
var redEnvelopeState: Int = 0,
|
||||
|
||||
// 领取金额
|
||||
var currentUserAmount: Double?
|
||||
)
|
@@ -1,7 +1,6 @@
|
||||
package com.yizhuan.xchat_android_core.redpackage
|
||||
|
||||
|
||||
|
||||
import com.yizhuan.xchat_android_core.bean.response.ServiceResult
|
||||
import com.yizhuan.xchat_android_core.utils.net.handleBeanData
|
||||
import com.yizhuan.xchat_android_core.utils.net.handleStringData
|
||||
@@ -20,32 +19,66 @@ object RedPackageModel {
|
||||
api = RxNet.create(Api::class.java)
|
||||
}
|
||||
|
||||
fun sendRedPackage(goldNum: String, message: String, num: String, roomUId: String, type: Int, password: String): Single<String> {
|
||||
return api.sendRedPackage(goldNum, message, num, roomUId, type, password)
|
||||
.io2main()
|
||||
.handleStringData()
|
||||
fun sendRedPackage(
|
||||
goldNum: Long, message: String?, num: Long, roomUId: String, type: Int,
|
||||
kind: Int, validityType: Int, password: String
|
||||
): Single<String> {
|
||||
return api.sendRedPackage(
|
||||
goldNum,
|
||||
message,
|
||||
num,
|
||||
roomUId,
|
||||
type,
|
||||
kind,
|
||||
validityType,
|
||||
password
|
||||
)
|
||||
.io2main()
|
||||
.handleStringData()
|
||||
}
|
||||
|
||||
|
||||
fun openRedPackage(redEnvelopeId: String): Single<RedPackageInfo> {
|
||||
fun openRedPackage(redEnvelopeId: Long): Single<RedPackageInfo> {
|
||||
return api.openRedPackage(redEnvelopeId)
|
||||
.io2main()
|
||||
.handleBeanData()
|
||||
.io2main()
|
||||
.handleBeanData()
|
||||
}
|
||||
|
||||
fun getRedPackage(uid: Long): Observable<RedPackageNotifyInfo> {
|
||||
return api.getRedPackage(uid)
|
||||
.io2main()
|
||||
.handleBeanData()
|
||||
.toObservable()
|
||||
.flatMap { Observable.fromIterable(it) }
|
||||
.map { RedPackageNotifyInfo(it.id, it.type, it.message, it.userVO?.avatar?:"", it.userVO?.nick?:"", it.roomUId, "") }
|
||||
fun getRedPackage(id: Long): Observable<RedPackageData> {
|
||||
return api.getRedPackageData(id)
|
||||
.io2main()
|
||||
.handleBeanData()
|
||||
.toObservable()
|
||||
}
|
||||
|
||||
fun setRedPackageSwitch(roomUid: Long):Single<Boolean> {
|
||||
/**
|
||||
* 获取房间最新可用红包
|
||||
*/
|
||||
fun getLatestRoomRedPackage(uid: Long): Observable<RedPackageNotifyInfo> {
|
||||
return api.getRedPackage(true, uid)
|
||||
.io2main()
|
||||
.handleBeanData()
|
||||
.toObservable().map {
|
||||
val item = it.last()
|
||||
RedPackageNotifyInfo(
|
||||
redEnvelopeId = item.id,
|
||||
redEnvelopeType = item.type,
|
||||
redEnvelopeMessage = item.message,
|
||||
sendUserAvatar = item.userVO?.avatar ?: "",
|
||||
sendUserNick = item.userVO?.nick ?: "",
|
||||
roomUid = item.roomUId,
|
||||
roomTitle = "",
|
||||
kind = item.kind,
|
||||
beginTime = item.beginTime,
|
||||
redEnvelopeNum = it.size.toLong(),
|
||||
validityType = item.validityType
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun setRedPackageSwitch(roomUid: Long): Single<Boolean> {
|
||||
return api.setRedPackageSwitch(roomUid)
|
||||
.io2main()
|
||||
.handleBeanData()
|
||||
.io2main()
|
||||
.handleBeanData()
|
||||
}
|
||||
|
||||
private interface Api {
|
||||
@@ -57,12 +90,16 @@ object RedPackageModel {
|
||||
*/
|
||||
@FormUrlEncoded
|
||||
@POST("/red-envelope")
|
||||
fun sendRedPackage(@Field("goldNum") goldNum: String,
|
||||
@Field("message") message: String,
|
||||
@Field("num") num: String,
|
||||
@Field("roomUId") roomUId: String,
|
||||
@Field("type") type: Int,
|
||||
@Field("password") password: String): Single<ServiceResult<String>>
|
||||
fun sendRedPackage(
|
||||
@Field("goldNum") goldNum: Long,
|
||||
@Field("message") message: String?,
|
||||
@Field("num") num: Long,
|
||||
@Field("roomUId") roomUId: String,
|
||||
@Field("type") type: Int,
|
||||
@Field("kind") kind: Int,
|
||||
@Field("validityType") validityType: Int,
|
||||
@Field("password") password: String
|
||||
): Single<ServiceResult<String>>
|
||||
|
||||
/**
|
||||
* 开红包
|
||||
@@ -71,7 +108,7 @@ object RedPackageModel {
|
||||
*/
|
||||
@FormUrlEncoded
|
||||
@POST("/red-envelope/open")
|
||||
fun openRedPackage(@Field("redEnvelopeId") redEnvelopeId: String): Single<ServiceResult<RedPackageInfo>>
|
||||
fun openRedPackage(@Field("redEnvelopeId") redEnvelopeId: Long): Single<ServiceResult<RedPackageInfo>>
|
||||
|
||||
|
||||
/**
|
||||
@@ -80,7 +117,18 @@ object RedPackageModel {
|
||||
* @return
|
||||
*/
|
||||
@GET("/room/red-envelop")
|
||||
fun getRedPackage(@Query("uid") uid: Long): Single<ServiceResult<List<RedEnvelopeVO>>>
|
||||
fun getRedPackage(
|
||||
@Query("isShowKind") isShowKind: Boolean,
|
||||
@Query("uid") uid: Long
|
||||
): Single<ServiceResult<List<RedEnvelopeVO>>>
|
||||
|
||||
/**
|
||||
* 获取红包详情
|
||||
*/
|
||||
@GET("/red-envelope/get")
|
||||
fun getRedPackageData(
|
||||
@Query("redEnvelopeId") redEnvelopeId: Long,
|
||||
): Single<ServiceResult<RedPackageData>>
|
||||
|
||||
|
||||
/**
|
||||
@@ -90,6 +138,5 @@ object RedPackageModel {
|
||||
fun setRedPackageSwitch(@Path("roomUid") uid: Long): Single<ServiceResult<Boolean>>
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@@ -4,38 +4,58 @@ import java.io.Serializable
|
||||
|
||||
data class RedPackageNotifyInfo(
|
||||
|
||||
/**
|
||||
* 红包 id
|
||||
*/
|
||||
var redEnvelopeId: String = "",
|
||||
/**
|
||||
* 红包 id
|
||||
*/
|
||||
var redEnvelopeId: String = "",
|
||||
|
||||
/**
|
||||
* 红包类型
|
||||
*/
|
||||
var redEnvelopeType: Int = 0,
|
||||
/**
|
||||
* 红包类型 1:房间水晶红包 2:全服水晶红包 3:房间礼物红包 4:全服礼物红包
|
||||
*/
|
||||
var redEnvelopeType: Int = 0,
|
||||
|
||||
/**
|
||||
* 红包消息
|
||||
*/
|
||||
var redEnvelopeMessage: String = "",
|
||||
/**
|
||||
* 红包消息
|
||||
*/
|
||||
var redEnvelopeMessage: String = "",
|
||||
|
||||
/**
|
||||
* 红包发送者头像
|
||||
*/
|
||||
var sendUserAvatar: String = "",
|
||||
/**
|
||||
* 红包发送者头像
|
||||
*/
|
||||
var sendUserAvatar: String = "",
|
||||
|
||||
/**
|
||||
* 红包发送者昵称
|
||||
*/
|
||||
var sendUserNick: String = "",
|
||||
/**
|
||||
* 房间uid
|
||||
*/
|
||||
var roomUid: Long = 0,
|
||||
/**
|
||||
* 红包发送者昵称
|
||||
*/
|
||||
var sendUserNick: String = "",
|
||||
/**
|
||||
* 房间uid
|
||||
*/
|
||||
var roomUid: Long = 0,
|
||||
|
||||
/**
|
||||
* 房间名称
|
||||
*/
|
||||
var roomTitle: String = ""
|
||||
/**
|
||||
* 房间名称
|
||||
*/
|
||||
var roomTitle: String = "",
|
||||
|
||||
) : Serializable
|
||||
/**
|
||||
* 红包种类 0 旧版本 1 无门槛红包 2 关注红包 3 分享红包 4 弹幕红包
|
||||
*/
|
||||
var kind: Int = 0,
|
||||
|
||||
/**
|
||||
* 红包可领取时间
|
||||
*/
|
||||
var beginTime: Long = 0,
|
||||
|
||||
/**
|
||||
* 红包数量
|
||||
*/
|
||||
var redEnvelopeNum: Long = 0,
|
||||
|
||||
/**
|
||||
* 生效类型 0 立即生效 1 限时生效
|
||||
*/
|
||||
var validityType: Int?,
|
||||
|
||||
) : Serializable
|
@@ -0,0 +1,10 @@
|
||||
package com.yizhuan.xchat_android_core.room.core
|
||||
|
||||
import com.yizhuan.xchat_android_core.support.room.RoomService
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/10/26 12:36
|
||||
* Desc:房间数据服务
|
||||
**/
|
||||
class RoomDataService : RoomService() {
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
package com.yizhuan.xchat_android_core.support.config
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/10/26 22:50
|
||||
* Desc:常用变量
|
||||
**/
|
||||
object Constants {
|
||||
val KEY_INTENT = "/intent"
|
||||
}
|
@@ -0,0 +1,98 @@
|
||||
package com.yizhuan.xchat_android_core.support.room
|
||||
|
||||
import androidx.annotation.CallSuper
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.LifecycleEventObserver
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import com.chuhai.utils.log.ILog
|
||||
import com.trello.rxlifecycle3.LifecycleProvider
|
||||
import com.trello.rxlifecycle3.LifecycleTransformer
|
||||
import com.trello.rxlifecycle3.OutsideLifecycleException
|
||||
import com.trello.rxlifecycle3.RxLifecycle
|
||||
import com.yizhuan.xchat_android_core.support.room.lifecycle.RoomFullLifecycleObserver
|
||||
import com.yizhuan.xchat_android_core.support.room.lifecycle.RoomLifecycle
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.functions.Function
|
||||
import io.reactivex.subjects.BehaviorSubject
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/10/26 11:03
|
||||
* Desc:房间-基础能力组件
|
||||
**/
|
||||
abstract class RoomAbility : LifecycleEventObserver, ILog, RoomFullLifecycleObserver,
|
||||
LifecycleProvider<RoomLifecycle.Event> {
|
||||
|
||||
protected var roomContext: RoomContext? = null
|
||||
|
||||
protected var roomView: RoomView? = null
|
||||
|
||||
// 自定义RxLifeCycle(临时方案:后续替换为Flow)
|
||||
private val lifecycleSubject = BehaviorSubject.create<RoomLifecycle.Event>()
|
||||
|
||||
/**
|
||||
* 被RoomContext激活
|
||||
*/
|
||||
@CallSuper
|
||||
open fun onAttach(context: RoomContext) {
|
||||
this.roomContext = context
|
||||
context.roomLifecycle.addObserver(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* View附加状态
|
||||
* @param view
|
||||
*/
|
||||
@CallSuper
|
||||
open fun onViewAttach(view: RoomView) {
|
||||
roomView?.getLifecycleOwner()?.lifecycle?.removeObserver(this)
|
||||
roomView = view
|
||||
view.getLifecycleOwner().lifecycle.addObserver(this)
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
|
||||
if (event == Lifecycle.Event.ON_DESTROY) {
|
||||
roomView?.getLifecycleOwner()?.lifecycle?.removeObserver(this)
|
||||
roomView = null
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStateChanged(context: RoomContext, event: RoomLifecycle.Event) {
|
||||
super.onStateChanged(context, event)
|
||||
// 同步更新事件
|
||||
lifecycleSubject.onNext(event)
|
||||
if (event == RoomLifecycle.Event.STOP) {
|
||||
roomContext?.roomLifecycle?.removeObserver(this)
|
||||
roomContext = null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 下面为RxLifeCycle相关(临时方案,后续替换Flow)
|
||||
*/
|
||||
override fun lifecycle(): Observable<RoomLifecycle.Event?> {
|
||||
return lifecycleSubject.hide()
|
||||
}
|
||||
|
||||
override fun <T> bindUntilEvent(event: RoomLifecycle.Event): LifecycleTransformer<T> {
|
||||
return RxLifecycle.bindUntilEvent(lifecycleSubject, event)
|
||||
}
|
||||
|
||||
override fun <T> bindToLifecycle(): LifecycleTransformer<T> {
|
||||
return RxLifecycle.bind(lifecycleSubject, ROOM_LIFECYCLE)
|
||||
}
|
||||
|
||||
private val ROOM_LIFECYCLE: Function<RoomLifecycle.Event, RoomLifecycle.Event> =
|
||||
Function { lastEvent ->
|
||||
when (lastEvent) {
|
||||
RoomLifecycle.Event.START -> RoomLifecycle.Event.STOP
|
||||
RoomLifecycle.Event.STOP -> throw OutsideLifecycleException("Cannot bind to Room lifecycle when outside of it.")
|
||||
else -> throw UnsupportedOperationException("Binding to $lastEvent not yet implemented")
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,111 @@
|
||||
package com.yizhuan.xchat_android_core.support.room
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.chuhai.utils.log.ILog
|
||||
import com.yizhuan.xchat_android_core.support.room.lifecycle.RoomLifecycle
|
||||
import com.yizhuan.xchat_android_core.support.room.lifecycle.RoomLifecycleRegistry
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/10/26 11:50
|
||||
* Desc:一个房间
|
||||
**/
|
||||
abstract class RoomContext(val roomId: Long) : ILog {
|
||||
|
||||
/**
|
||||
* 临时维护在这里,后续逐步改动
|
||||
*/
|
||||
companion object {
|
||||
private var context: RoomContext? = null
|
||||
|
||||
// TODO:#临时方案 目前房间的生命周期有点出乎意料,未成功进房时,View层都已初始化完毕,所以临时开放这个LiveData供View层获取到Context
|
||||
private val _contextLiveData = MutableLiveData<RoomContext?>()
|
||||
val contextLiveData: LiveData<RoomContext?> get() = _contextLiveData
|
||||
fun get(): RoomContext? {
|
||||
return context
|
||||
}
|
||||
|
||||
fun set(context: RoomContext?) {
|
||||
this.context = context
|
||||
_contextLiveData.postValue(context)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生命周期处理
|
||||
*/
|
||||
val roomLifecycle: RoomLifecycleRegistry = RoomLifecycleRegistry()
|
||||
|
||||
/**
|
||||
* 所有能力组件
|
||||
*/
|
||||
private val abilityList = LinkedHashMap<String, RoomAbility>()
|
||||
|
||||
init {
|
||||
initAbility()
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动(进入房间)
|
||||
*/
|
||||
fun performStart() {
|
||||
logI("performStart()", filePrinter = true)
|
||||
roomLifecycle.handleLifecycleEvent(this, RoomLifecycle.Event.START)
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止(退出房间)
|
||||
*/
|
||||
fun performStop() {
|
||||
logI("performStop()", filePrinter = true)
|
||||
roomLifecycle.handleLifecycleEvent(this, RoomLifecycle.Event.STOP)
|
||||
onCleared()
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化Ability
|
||||
*/
|
||||
private fun initAbility() {
|
||||
loadAbility(abilityList)
|
||||
abilityList.keys.forEach {
|
||||
abilityList[it]?.onAttach(this)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 装载能力组件
|
||||
*/
|
||||
open fun loadAbility(list: MutableMap<String, RoomAbility>) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找组件
|
||||
*/
|
||||
fun <T : RoomAbility> findAbility(key: String): T? {
|
||||
return abilityList[key] as? T
|
||||
}
|
||||
|
||||
/**
|
||||
* 附加上视图了
|
||||
*/
|
||||
@Deprecated("临时方案:后续逐步完善RoomContext替换计划,到时候不会在这里实现该逻辑")
|
||||
fun onViewAttach(view: RoomView) {
|
||||
abilityList.keys.forEach {
|
||||
abilityList[it]?.onViewAttach(view)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 激活房间(进入房间后)
|
||||
*/
|
||||
@Deprecated("临时方案:后续逐步完善RoomContext替换计划,到时候不会在这里实现该逻辑")
|
||||
fun run() {
|
||||
set(this)
|
||||
performStart()
|
||||
}
|
||||
|
||||
private fun onCleared() {
|
||||
abilityList.clear()
|
||||
set(null)
|
||||
}
|
||||
}
|
@@ -0,0 +1,8 @@
|
||||
package com.yizhuan.xchat_android_core.support.room
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/10/26 11:02
|
||||
* Desc:房间内的业务处理器
|
||||
**/
|
||||
open class RoomHandler : RoomAbility() {
|
||||
}
|
@@ -0,0 +1,10 @@
|
||||
package com.yizhuan.xchat_android_core.support.room
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/10/26 12:31
|
||||
* Desc:房间-基础服务组件
|
||||
* PS:基于[RoomContext],提供整个房间的基础服务能力。(服务之间可相互提供能力,也可向下提供能力。)
|
||||
*
|
||||
**/
|
||||
abstract class RoomService : RoomAbility() {
|
||||
}
|
@@ -0,0 +1,22 @@
|
||||
package com.yizhuan.xchat_android_core.support.room
|
||||
|
||||
import android.app.Activity
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/10/26 15:05
|
||||
* Desc:房间视图层
|
||||
* TODO:目前Activity和子Fragment都实现该接口,感觉有些奇怪,PS:还没熟悉现阶段的房间视图层级关系,后续梳理后整体优化
|
||||
**/
|
||||
interface RoomView {
|
||||
fun getLifecycleOwner(): LifecycleOwner
|
||||
|
||||
fun getActivity(): Activity?
|
||||
|
||||
/**
|
||||
* 获取房间上下文
|
||||
*/
|
||||
fun getRoomContext(): RoomContext? {
|
||||
return RoomContext.get()
|
||||
}
|
||||
}
|
@@ -0,0 +1,20 @@
|
||||
package com.yizhuan.xchat_android_core.support.room
|
||||
|
||||
import com.chuhai.utils.log.ILog
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/10/26 17:12
|
||||
* Desc:房间UI组件
|
||||
**/
|
||||
interface RoomWidget : ILog {
|
||||
|
||||
/**
|
||||
* 组件激活
|
||||
*/
|
||||
fun onStart(roomView: RoomView)
|
||||
|
||||
/**
|
||||
* 组件停止
|
||||
*/
|
||||
fun onStop()
|
||||
}
|
@@ -0,0 +1,34 @@
|
||||
package com.yizhuan.xchat_android_core.support.room.lifecycle
|
||||
|
||||
import com.yizhuan.xchat_android_core.support.room.RoomContext
|
||||
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/10/26 11:50
|
||||
* Desc:房间生命周期事件观察者(完整)
|
||||
**/
|
||||
interface RoomFullLifecycleObserver : RoomLifecycleObserver {
|
||||
|
||||
override fun onStateChanged(context: RoomContext, event: RoomLifecycle.Event) {
|
||||
when (event) {
|
||||
RoomLifecycle.Event.START -> {
|
||||
onStart(context)
|
||||
}
|
||||
RoomLifecycle.Event.STOP -> {
|
||||
onStop(context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动房间
|
||||
* PS:只会执行一次,相当于Activity的onCreate。
|
||||
*/
|
||||
fun onStart(context: RoomContext) {}
|
||||
|
||||
/**
|
||||
* 退出房间
|
||||
* PS:只会执行一次,相当于Activity的onDestroy。
|
||||
*/
|
||||
fun onStop(context: RoomContext) {}
|
||||
}
|
@@ -0,0 +1,35 @@
|
||||
package com.yizhuan.xchat_android_core.support.room.lifecycle
|
||||
|
||||
import com.chuhai.utils.ICleared
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/10/26 11:50
|
||||
* Desc:房间生命周期
|
||||
**/
|
||||
abstract class RoomLifecycle : ICleared {
|
||||
|
||||
/**
|
||||
* 添加生命周期监听
|
||||
* PS:目前是及时事件分发,对于已发生状态事件不会补充分发。
|
||||
*/
|
||||
abstract fun addObserver(observer: RoomLifecycleObserver)
|
||||
|
||||
/**
|
||||
* 移除生命周期监听
|
||||
*/
|
||||
abstract fun removeObserver(observer: RoomLifecycleObserver)
|
||||
|
||||
enum class Event {
|
||||
/**
|
||||
* 启动房间
|
||||
* PS:只会执行一次,相当于Activity的onCreate。
|
||||
*/
|
||||
START,
|
||||
|
||||
/**
|
||||
* 退出房间
|
||||
* PS:只会执行一次,相当于Activity的onDestroy。
|
||||
*/
|
||||
STOP;
|
||||
}
|
||||
}
|
@@ -0,0 +1,18 @@
|
||||
package com.yizhuan.xchat_android_core.support.room.lifecycle
|
||||
|
||||
import com.yizhuan.xchat_android_core.support.room.RoomContext
|
||||
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/10/26 11:50
|
||||
* Desc:房间生命周期事件观察者
|
||||
**/
|
||||
interface RoomLifecycleObserver {
|
||||
|
||||
/**
|
||||
* 状态改变
|
||||
* @param event 新事件
|
||||
*/
|
||||
fun onStateChanged(context: RoomContext, event: RoomLifecycle.Event)
|
||||
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
package com.yizhuan.xchat_android_core.support.room.lifecycle
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/10/26 11:50
|
||||
* Desc:房间生命周期持有者
|
||||
**/
|
||||
interface RoomLifecycleOwner {
|
||||
fun getLifecycle(): RoomLifecycle
|
||||
}
|
@@ -0,0 +1,62 @@
|
||||
package com.yizhuan.xchat_android_core.support.room.lifecycle
|
||||
|
||||
import com.chuhai.utils.log.ILog
|
||||
import com.yizhuan.xchat_android_core.support.room.RoomContext
|
||||
import java.util.concurrent.CopyOnWriteArrayList
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/10/26 11:50
|
||||
* Desc:房间生命周期简单实现
|
||||
* PS:目前是及时事件分发,对于已发生状态事件不会补充分发。
|
||||
**/
|
||||
class RoomLifecycleRegistry : RoomLifecycle(), ILog {
|
||||
/**
|
||||
* 生命周期监听
|
||||
*/
|
||||
private val observers: CopyOnWriteArrayList<RoomLifecycleObserver> = CopyOnWriteArrayList()
|
||||
|
||||
/**
|
||||
* 当前事件
|
||||
*/
|
||||
private var event: Event? = null
|
||||
|
||||
override fun addObserver(observer: RoomLifecycleObserver) {
|
||||
observers.add(observer)
|
||||
}
|
||||
|
||||
override fun removeObserver(observer: RoomLifecycleObserver) {
|
||||
observers.remove(observer)
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置最新的事件
|
||||
*/
|
||||
fun handleLifecycleEvent(context: RoomContext, event: Event) {
|
||||
logI("handleLifecycleEvent() event:$event", filePrinter = true)
|
||||
if (this.event == Event.STOP) {
|
||||
// 停止状态
|
||||
logI("handleLifecycleEvent() 停止状态", filePrinter = true)
|
||||
return
|
||||
}
|
||||
if (this.event == event) {
|
||||
// 状态未改变
|
||||
return
|
||||
}
|
||||
dispatchEvent(context, event)
|
||||
}
|
||||
|
||||
/**
|
||||
* 分发事件
|
||||
*/
|
||||
private fun dispatchEvent(context: RoomContext, event: Event) {
|
||||
logI("dispatchEvent() event:$event", filePrinter = true)
|
||||
this.event = event
|
||||
observers.forEach {
|
||||
it.onStateChanged(context, event)
|
||||
}
|
||||
if (event == Event.STOP) {
|
||||
// 停止后,主动清空下
|
||||
observers.clear()
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
package com.yizhuan.xchat_android_core.support.room.lifecycle.rx;
|
||||
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/10/26 11:50
|
||||
* Desc:RxLifecycle 房间生命周期
|
||||
**/
|
||||
public enum RoomRxLifecycleEvent {
|
||||
START,
|
||||
STOP
|
||||
}
|
@@ -31,8 +31,8 @@ COMPILE_SDK_VERSION=33
|
||||
MIN_SDK_VERSION=21
|
||||
TARGET_SDK_VERSION=33
|
||||
|
||||
version_name=2.1.1
|
||||
version_code=2110
|
||||
version_name=2.2.0
|
||||
version_code=2220
|
||||
|
||||
#systemProp.https.proxyHost=127.0.0.1
|
||||
#systemProp.https.proxyPort=7890
|
@@ -4,6 +4,7 @@ import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
|
||||
import com.facebook.stetho.okhttp3.StethoInterceptor;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.yizhuan.xchat_android_library.BuildConfig;
|
||||
@@ -70,6 +71,8 @@ public final class RxNetManager {
|
||||
});
|
||||
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
|
||||
mBuilder.addInterceptor(loggingInterceptor);
|
||||
|
||||
mBuilder.addNetworkInterceptor(new StethoInterceptor());
|
||||
}
|
||||
|
||||
for (Interceptor interceptor : interceptors) {
|
||||
|
@@ -26,6 +26,7 @@ public abstract class BaseApp extends Application{
|
||||
|
||||
public static void init(Application application) {
|
||||
gContext = application;
|
||||
com.chuhai.utils.AppUtils.init(application);
|
||||
}
|
||||
|
||||
/**
|
||||
|
14
library/src/module_utils/java/com/chuhai/utils/ICleared.kt
Normal file
@@ -0,0 +1,14 @@
|
||||
package com.chuhai.utils
|
||||
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/10/26 11:50
|
||||
* Desc:清除释放统一接口
|
||||
**/
|
||||
interface ICleared {
|
||||
|
||||
/**
|
||||
* 清除/释放
|
||||
*/
|
||||
fun onCleared() {}
|
||||
}
|
@@ -0,0 +1,13 @@
|
||||
package com.chuhai.utils.log
|
||||
|
||||
import android.util.Log
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/10/26 10:29
|
||||
* Desc:Android日志
|
||||
*/
|
||||
class AndroidLogPrinter : LogPrinter {
|
||||
override fun println(level: Int, tag: String, message: String) {
|
||||
Log.println(level, tag, message)
|
||||
}
|
||||
}
|
61
library/src/module_utils/java/com/chuhai/utils/log/ILog.kt
Normal file
@@ -0,0 +1,61 @@
|
||||
package com.chuhai.utils.log
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/10/26 10:29
|
||||
* Desc:日志快捷使用接口
|
||||
*/
|
||||
interface ILog {
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* 清理(退出APP时调用)
|
||||
*/
|
||||
fun onCleared() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 默认日志Tag
|
||||
*/
|
||||
fun getLogTag(): String {
|
||||
return this::class.java.simpleName
|
||||
}
|
||||
|
||||
fun logI(message: String, tag: String = getLogTag(), filePrinter: Boolean = false) {
|
||||
LogUtil.i(tag, message, filePrinter)
|
||||
}
|
||||
|
||||
fun logV(message: String, tag: String = getLogTag(), filePrinter: Boolean = false) {
|
||||
LogUtil.v(tag, message, filePrinter)
|
||||
}
|
||||
|
||||
fun logW(message: String, tag: String = getLogTag(), filePrinter: Boolean = false) {
|
||||
LogUtil.w(tag, message, filePrinter)
|
||||
}
|
||||
|
||||
fun logD(message: String, tag: String = getLogTag(), filePrinter: Boolean = false) {
|
||||
LogUtil.d(tag, message, filePrinter)
|
||||
}
|
||||
|
||||
fun logE(message: String, tag: String = getLogTag(), filePrinter: Boolean = false) {
|
||||
LogUtil.e(tag, message, filePrinter)
|
||||
}
|
||||
|
||||
fun logE(
|
||||
throwable: Throwable,
|
||||
tag: String = getLogTag(),
|
||||
filePrinter: Boolean = false
|
||||
) {
|
||||
LogUtil.e(tag, throwable, filePrinter)
|
||||
}
|
||||
|
||||
fun logE(
|
||||
message: String,
|
||||
throwable: Throwable,
|
||||
tag: String = getLogTag(),
|
||||
filePrinter: Boolean = false
|
||||
) {
|
||||
LogUtil.e(tag, message, throwable, filePrinter)
|
||||
}
|
||||
}
|
@@ -0,0 +1,14 @@
|
||||
package com.chuhai.utils.log
|
||||
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/10/26 10:29
|
||||
* Desc: 日志打印
|
||||
*/
|
||||
interface LogPrinter {
|
||||
/**
|
||||
* 打印
|
||||
* @param level 级别 [android.util.Log]
|
||||
*/
|
||||
fun println(level: Int, tag: String, message: String)
|
||||
}
|
101
library/src/module_utils/java/com/chuhai/utils/log/LogUtil.kt
Normal file
@@ -0,0 +1,101 @@
|
||||
package com.chuhai.utils.log
|
||||
|
||||
import android.util.Log
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/10/26 10:29
|
||||
* Desc:日志工具
|
||||
*/
|
||||
object LogUtil {
|
||||
|
||||
private var consolePrinter: LogPrinter? = AndroidLogPrinter()
|
||||
|
||||
private var filePrinter: LogPrinter? = null
|
||||
|
||||
// 是否启动控制台打印
|
||||
var consolePrinterEnabled: Boolean = true
|
||||
|
||||
// 是否启动文件打印
|
||||
var filePrinterEnabled: Boolean = true
|
||||
|
||||
/**
|
||||
* 设置文件打印
|
||||
*/
|
||||
fun setFilePrinter(filePrinter: LogPrinter) {
|
||||
this.filePrinter = filePrinter
|
||||
}
|
||||
|
||||
fun e(tag: String, message: String, filePrinter: Boolean = false) {
|
||||
log(Log.ERROR, tag, message, filePrinter)
|
||||
}
|
||||
|
||||
fun e(tag: String, throwable: Throwable, filePrinter: Boolean = false) {
|
||||
val cause = Log.getStackTraceString(throwable)
|
||||
if (cause.isEmpty()) {
|
||||
return
|
||||
}
|
||||
e(tag, cause, filePrinter)
|
||||
}
|
||||
|
||||
fun e(tag: String, message: String?, throwable: Throwable, filePrinter: Boolean = false) {
|
||||
val cause = Log.getStackTraceString(throwable)
|
||||
if (message == null && cause.isEmpty()) {
|
||||
return
|
||||
}
|
||||
e(tag, message + "\t\t" + cause, filePrinter)
|
||||
}
|
||||
|
||||
fun d(tag: String, message: String, filePrinter: Boolean = false) {
|
||||
log(Log.DEBUG, tag, message, filePrinter)
|
||||
}
|
||||
|
||||
fun i(tag: String, message: String, filePrinter: Boolean = false) {
|
||||
log(Log.INFO, tag, message, filePrinter)
|
||||
}
|
||||
|
||||
fun v(tag: String, message: String, filePrinter: Boolean = false) {
|
||||
log(Log.VERBOSE, tag, message, filePrinter)
|
||||
}
|
||||
|
||||
fun w(tag: String, message: String, filePrinter: Boolean = false) {
|
||||
log(Log.WARN, tag, message, filePrinter)
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出日志
|
||||
*/
|
||||
fun log(level: Int = Log.INFO, tag: String?, message: String?, filePrinter: Boolean = false) {
|
||||
if (tag.isNullOrEmpty()) {
|
||||
return
|
||||
}
|
||||
if (message.isNullOrEmpty()) {
|
||||
return
|
||||
}
|
||||
// 输出控制台
|
||||
logConsole(level, tag, message)
|
||||
// 输出文件
|
||||
if (filePrinter) {
|
||||
logFile(level, tag, message)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出到控制台
|
||||
*/
|
||||
fun logConsole(level: Int = Log.INFO, tag: String, message: String) {
|
||||
if (!consolePrinterEnabled) {
|
||||
return
|
||||
}
|
||||
consolePrinter?.println(level, tag, message)
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出到文件
|
||||
*/
|
||||
fun logFile(level: Int = Log.INFO, tag: String, message: String) {
|
||||
if (!filePrinterEnabled) {
|
||||
return
|
||||
}
|
||||
filePrinter?.println(level, tag, message)
|
||||
}
|
||||
}
|
@@ -0,0 +1,156 @@
|
||||
package com.chuhai.utils.spannable;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.text.TextPaint;
|
||||
import android.text.TextUtils;
|
||||
import android.text.style.ReplacementSpan;
|
||||
import android.util.TypedValue;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/10/26 20:14
|
||||
**/
|
||||
public class IconTextSpan extends ReplacementSpan {
|
||||
private Context mContext;
|
||||
private int mBgColorResId; //Icon背景颜色
|
||||
private String mText; //Icon内文字
|
||||
private float mBgHeight; //Icon背景高度
|
||||
private float mBgWidth; //Icon背景宽度
|
||||
private float mRadius; //Icon圆角半径
|
||||
private float mRightMargin; //右边距
|
||||
private float mTextSize; //文字大小
|
||||
private int mTextColorResId; //文字颜色
|
||||
|
||||
private Paint mBgPaint; //icon背景画笔
|
||||
private Paint mTextPaint; //icon文字画笔
|
||||
private int paddingHorizontal = 0;
|
||||
|
||||
public IconTextSpan(Context context, int bgColorResId, String text, int textColor, int mTextSize, int round, int marginRight, int paddingHorizontal) {
|
||||
if (TextUtils.isEmpty(text)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.paddingHorizontal = paddingHorizontal;
|
||||
//初始化默认数值
|
||||
initDefaultValue(context, bgColorResId, text, textColor, mTextSize, round, marginRight);
|
||||
//计算背景的宽度
|
||||
this.mBgWidth = caculateBgWidth(text);
|
||||
//初始化画笔
|
||||
initPaint();
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化画笔
|
||||
*/
|
||||
private void initPaint() {
|
||||
//初始化背景画笔
|
||||
mBgPaint = new Paint();
|
||||
mBgPaint.setColor(mBgColorResId);
|
||||
mBgPaint.setStyle(Paint.Style.FILL);
|
||||
mBgPaint.setAntiAlias(true);
|
||||
|
||||
//初始化文字画笔
|
||||
mTextPaint = new TextPaint();
|
||||
mTextPaint.setColor(mTextColorResId);
|
||||
mTextPaint.setTextSize(mTextSize);
|
||||
mTextPaint.setAntiAlias(true);
|
||||
mTextPaint.setTextAlign(Paint.Align.CENTER);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化默认数值
|
||||
*
|
||||
* @param context 上下文
|
||||
* @param textColor 字体颜色
|
||||
*/
|
||||
private void initDefaultValue(Context context, int bgColorResId, String text, int textColor, int textSize, int round, int marginRight) {
|
||||
this.mContext = context.getApplicationContext();
|
||||
this.mBgColorResId = bgColorResId;
|
||||
this.mText = text;
|
||||
this.mBgHeight = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 18f, mContext.getResources().getDisplayMetrics());
|
||||
this.mRightMargin = marginRight;
|
||||
this.mRadius = round;
|
||||
this.mTextSize = textSize;
|
||||
this.mTextColorResId = textColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算icon背景宽度
|
||||
*
|
||||
* @param text icon内文字
|
||||
*/
|
||||
private float caculateBgWidth(String text) {
|
||||
// if (text.length() > 1) {
|
||||
//多字,宽度=文字宽度+padding
|
||||
Rect textRect = new Rect();
|
||||
Paint paint = new Paint();
|
||||
paint.setTextSize(mTextSize);
|
||||
paint.getTextBounds(text, 0, text.length(), textRect);
|
||||
float padding = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, paddingHorizontal, mContext.getResources().getDisplayMetrics());
|
||||
return textRect.width() + padding * 2;
|
||||
// } else {
|
||||
//单字,宽高一致为正方形
|
||||
// return mBgHeight + paddingHorizontal;
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置右边距
|
||||
* @param rightMarginDpValue 右边边距
|
||||
*/
|
||||
public void setRightMarginDpValue(int rightMarginDpValue) {
|
||||
this.mRightMargin = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, rightMarginDpValue, mContext.getResources().getDisplayMetrics());
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置宽度,宽度=背景宽度+右边距
|
||||
*/
|
||||
@Override
|
||||
public int getSize(@NonNull Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) {
|
||||
return (int) (mBgWidth + mRightMargin);
|
||||
}
|
||||
|
||||
/**
|
||||
* draw
|
||||
*
|
||||
* @param text 完整文本
|
||||
* @param start setSpan里设置的start
|
||||
* @param end setSpan里设置的start
|
||||
* @param top 当前span所在行的上方y
|
||||
* @param y y其实就是metric里baseline的位置
|
||||
* @param bottom 当前span所在行的下方y(包含了行间距),会和下一行的top重合
|
||||
* @param paint 使用此span的画笔
|
||||
*/
|
||||
@Override
|
||||
public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) {
|
||||
//画背景
|
||||
Paint bgPaint = new Paint();
|
||||
bgPaint.setColor(mBgColorResId);
|
||||
bgPaint.setStyle(Paint.Style.FILL);
|
||||
bgPaint.setAntiAlias(true);
|
||||
Paint.FontMetrics metrics = paint.getFontMetrics();
|
||||
|
||||
float textHeight = metrics.descent - metrics.ascent;
|
||||
//算出背景开始画的y坐标
|
||||
float bgStartY = y + (textHeight - mBgHeight) / 2 + metrics.ascent;
|
||||
|
||||
//画背景
|
||||
RectF bgRect = new RectF(x, bgStartY, x + mBgWidth , bgStartY + mBgHeight);
|
||||
canvas.drawRoundRect(bgRect, mRadius, mRadius, bgPaint);
|
||||
|
||||
//把字画在背景中间
|
||||
TextPaint textPaint = new TextPaint();
|
||||
textPaint.setColor(mTextColorResId);
|
||||
textPaint.setTextSize(mTextSize);
|
||||
textPaint.setAntiAlias(true);
|
||||
textPaint.setTextAlign(Paint.Align.CENTER); //这个只针对x有效
|
||||
Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
|
||||
float textRectHeight = fontMetrics.bottom - fontMetrics.top;
|
||||
canvas.drawText(mText, x + mBgWidth / 2, bgStartY + (mBgHeight - textRectHeight) / 2 - fontMetrics.top, textPaint);
|
||||
}
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
package com.chuhai.utils.spannable
|
||||
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Paint
|
||||
import android.graphics.RectF
|
||||
import android.text.style.ReplacementSpan
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/10/26 20:14
|
||||
* Desc:文字 圆背景
|
||||
**/
|
||||
class RoundBackgroundColorSpan(var textColor: Int, var textSize: Int, var bgColor: Int, var paddingHorizontal: Int, var paddingVertical: Int, var marginHorizontal: Int,var round:Int) : ReplacementSpan() {
|
||||
|
||||
override fun getSize(paint: Paint, text: CharSequence?, start: Int, end: Int, fm: Paint.FontMetricsInt?): Int {
|
||||
return paint.measureText(text, start, end).toInt()+(paddingHorizontal)+marginHorizontal
|
||||
}
|
||||
|
||||
override fun draw(canvas: Canvas, text: CharSequence?, start: Int, end: Int, x: Float, top: Int, y: Int, bottom: Int, paint: Paint) {
|
||||
|
||||
paint.color = this.textColor
|
||||
paint.textSize = textSize.toFloat()
|
||||
canvas.drawText(text.toString(), start, end, x + paddingHorizontal+marginHorizontal, y.toFloat()-paddingVertical, paint)
|
||||
paint.color = paint.color
|
||||
|
||||
paint.color = this.bgColor;
|
||||
val rectF = RectF(x+marginHorizontal, top.toFloat(), (paint.measureText(text.toString())) , bottom.toFloat())
|
||||
canvas.drawRoundRect(rectF, round.toFloat(), round.toFloat(), paint)
|
||||
}
|
||||
}
|
@@ -0,0 +1,327 @@
|
||||
package com.chuhai.utils.spannable
|
||||
|
||||
import android.text.Spannable
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.text.Spanned
|
||||
import android.text.TextPaint
|
||||
import android.text.method.LinkMovementMethod
|
||||
import android.text.style.*
|
||||
import android.view.View
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.ColorInt
|
||||
import androidx.annotation.DrawableRes
|
||||
import com.chuhai.utils.ktx.dp
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/10/26 20:14
|
||||
* Desc:可扩展文本
|
||||
**/
|
||||
class SpannableTextBuilder(private val textView: TextView) {
|
||||
|
||||
private val spannableBuilder: SpannableStringBuilder by lazy {
|
||||
SpannableStringBuilder()
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一段文本
|
||||
*/
|
||||
fun appendText(node: TextNode) {
|
||||
val onClick: ((String) -> Unit)? = if (node.getOnClickListener() != null) {
|
||||
{
|
||||
node.getOnClickListener()?.invoke(node)
|
||||
}
|
||||
} else {
|
||||
null
|
||||
}
|
||||
appendText(
|
||||
text = node.getContent(),
|
||||
textColor = node.getTextColor(),
|
||||
textSize = node.getTextSize(),
|
||||
backgroundColor = node.getBackgroundColor(),
|
||||
underline = node.isUnderline(),
|
||||
clickListener = onClick
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一段文本
|
||||
* @param text 文本
|
||||
* @param textColor 文本颜色
|
||||
* @param backgroundColor 背景颜色
|
||||
* @param textSize 文本大小
|
||||
* @param textStyle 文本样式
|
||||
* @param underline 是否有下划线
|
||||
* @param clickListener 点击事件
|
||||
*/
|
||||
fun appendText(
|
||||
text: String,
|
||||
@ColorInt textColor: Int? = null,
|
||||
@ColorInt backgroundColor: Int? = null,
|
||||
textSize: Int? = null,
|
||||
textStyle: Int? = null,
|
||||
underline: Boolean? = null,
|
||||
clickListener: ((String) -> Unit)? = null
|
||||
): SpannableTextBuilder {
|
||||
val start = spannableBuilder.length
|
||||
spannableBuilder.append(text)
|
||||
val end = spannableBuilder.length
|
||||
|
||||
// 文本颜色
|
||||
if (textColor != null) {
|
||||
spannableBuilder.setSpan(
|
||||
ForegroundColorSpan(textColor),
|
||||
start,
|
||||
end,
|
||||
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
|
||||
)
|
||||
}
|
||||
|
||||
// 文本背景颜色
|
||||
if (backgroundColor != null) {
|
||||
spannableBuilder.setSpan(
|
||||
BackgroundColorSpan(backgroundColor),
|
||||
start,
|
||||
end,
|
||||
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
|
||||
)
|
||||
}
|
||||
|
||||
// 文本大小
|
||||
if (textSize != null) {
|
||||
spannableBuilder.setSpan(
|
||||
AbsoluteSizeSpan(textSize, true),
|
||||
start,
|
||||
end,
|
||||
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
|
||||
)
|
||||
}
|
||||
|
||||
// 文本样式
|
||||
if (textStyle != null) {
|
||||
spannableBuilder.setSpan(
|
||||
StyleSpan(textStyle),
|
||||
start,
|
||||
end,
|
||||
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
|
||||
)
|
||||
}
|
||||
|
||||
// 下划线
|
||||
if (underline == true) {
|
||||
spannableBuilder.setSpan(UnderlineSpan(), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
}
|
||||
|
||||
// 点击事件
|
||||
if (clickListener != null) {
|
||||
// 设置highlightColor=Color.TRANSPARENT,可以解决点击时的高亮色问题,但光标的区域选中也是透明的,貌似对用户体验不太好
|
||||
// textView.highlightColor = Color.TRANSPARENT
|
||||
textView.movementMethod = LinkMovementMethod.getInstance()
|
||||
val clickableSpan = TextClickableSpan(
|
||||
clickListener, text, textColor
|
||||
?: textView.currentTextColor, underline ?: false
|
||||
)
|
||||
spannableBuilder.setSpan(clickableSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加图片
|
||||
* @param drawable 图片
|
||||
* @param clickListener 点击事件
|
||||
*/
|
||||
fun appendDrawable(
|
||||
@DrawableRes drawable: Int,
|
||||
clickListener: ((Int) -> Unit)?
|
||||
): SpannableTextBuilder {
|
||||
// 需要时再完善
|
||||
val start = spannableBuilder.length
|
||||
spannableBuilder.append("[icon}")
|
||||
val end = spannableBuilder.length
|
||||
|
||||
// 图片
|
||||
val imageSpan: ImageSpan = VerticalImageSpan(textView.context, drawable)
|
||||
spannableBuilder.setSpan(imageSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
|
||||
// 点击事件
|
||||
if (clickListener != null) {
|
||||
textView.movementMethod = LinkMovementMethod.getInstance()
|
||||
val clickableSpan = DrawableClickableSpan(clickListener, drawable)
|
||||
spannableBuilder.setSpan(clickableSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加有背景圆角的文字
|
||||
* @param text 文本
|
||||
* @param textColor 文本颜色
|
||||
* @param backgroundColor 背景颜色
|
||||
* @param paddingHorizontal 内横向边距
|
||||
* @param paddingVertical 内竖向边距
|
||||
* @param marginHorizontal 外横向边距
|
||||
*/
|
||||
fun appendTextRoundBackground(
|
||||
text: String,
|
||||
@ColorInt textColor: Int,
|
||||
textSize: Int,
|
||||
@ColorInt backgroundColor: Int,
|
||||
paddingHorizontal: Int,
|
||||
paddingVertical: Int,
|
||||
marginHorizontal: Int,
|
||||
round: Int
|
||||
): SpannableTextBuilder {
|
||||
val start = spannableBuilder.length
|
||||
spannableBuilder.append(text)
|
||||
val end = spannableBuilder.length
|
||||
spannableBuilder.setSpan(
|
||||
RoundBackgroundColorSpan(
|
||||
textColor,
|
||||
textSize,
|
||||
backgroundColor,
|
||||
paddingHorizontal,
|
||||
paddingVertical,
|
||||
marginHorizontal,
|
||||
round
|
||||
), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
|
||||
);
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加有背景圆角的文字
|
||||
* @param text 文本
|
||||
* @param textColor 文本颜色
|
||||
* @param backgroundColor 背景颜色
|
||||
* @param paddingHorizontal 内横向边距
|
||||
* @param paddingVertical 内竖向边距
|
||||
* @param marginHorizontal 外横向边距
|
||||
*/
|
||||
fun appendIconTextRoundBackground(
|
||||
text: String,
|
||||
@ColorInt textColor: Int,
|
||||
textSize: Int,
|
||||
@ColorInt backgroundColor: Int,
|
||||
marginRight: Int,
|
||||
round: Int
|
||||
): SpannableTextBuilder {
|
||||
val start = spannableBuilder.length
|
||||
spannableBuilder.append(text)
|
||||
val end = spannableBuilder.length
|
||||
spannableBuilder.setSpan(
|
||||
IconTextSpan(
|
||||
textView.context,
|
||||
backgroundColor,
|
||||
text,
|
||||
textColor,
|
||||
textSize,
|
||||
round,
|
||||
marginRight,
|
||||
2.dp
|
||||
),
|
||||
start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
|
||||
)
|
||||
return this
|
||||
}
|
||||
|
||||
fun build(): SpannableStringBuilder {
|
||||
return spannableBuilder
|
||||
}
|
||||
|
||||
/**
|
||||
* 应用
|
||||
*/
|
||||
fun apply() {
|
||||
textView.text = spannableBuilder
|
||||
}
|
||||
|
||||
/**
|
||||
* 文本点击
|
||||
*/
|
||||
class TextClickableSpan(
|
||||
private val clickListener: ((String) -> Unit)? = null,
|
||||
private val text: String,
|
||||
private val textColor: Int,
|
||||
private val underline: Boolean
|
||||
) : ClickableSpan() {
|
||||
override fun onClick(widget: View) {
|
||||
clickListener?.invoke(text)
|
||||
}
|
||||
|
||||
override fun updateDrawState(ds: TextPaint) {
|
||||
ds.color = textColor
|
||||
ds.isUnderlineText = underline
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 图片点击
|
||||
*/
|
||||
class DrawableClickableSpan(
|
||||
private val clickListener: ((Int) -> Unit)? = null,
|
||||
private val drawable: Int
|
||||
) : ClickableSpan() {
|
||||
override fun onClick(widget: View) {
|
||||
clickListener?.invoke(drawable)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
interface TextNode {
|
||||
/**
|
||||
* 内容
|
||||
*/
|
||||
fun getContent(): String
|
||||
|
||||
/**
|
||||
* 文本颜色
|
||||
*/
|
||||
fun getTextSize(): Int? {
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* 文本颜色
|
||||
*/
|
||||
fun getTextColor(): Int? {
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* 文本样式
|
||||
*/
|
||||
fun getTextStyle(): Int? {
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* 背景颜色
|
||||
*/
|
||||
fun getBackgroundColor(): Int? {
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否有下划线
|
||||
*/
|
||||
fun isUnderline(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取点击事件
|
||||
*/
|
||||
fun getOnClickListener(): ((TextNode) -> Unit)? {
|
||||
return null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 快速构建生成器
|
||||
*/
|
||||
fun TextView.spannableBuilder(): SpannableTextBuilder {
|
||||
return SpannableTextBuilder(this)
|
||||
}
|
@@ -0,0 +1,66 @@
|
||||
package com.chuhai.utils.spannable
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Paint
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.text.style.ImageSpan
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/10/26 20:14
|
||||
* Desc:垂直居中的ImageSpan
|
||||
**/
|
||||
class VerticalImageSpan : ImageSpan {
|
||||
constructor(drawable: Drawable) : super(drawable)
|
||||
constructor(context: Context, resourceId: Int) : super(context, resourceId)
|
||||
|
||||
/**
|
||||
* update the text line height
|
||||
*/
|
||||
override fun getSize(
|
||||
paint: Paint, text: CharSequence?, start: Int, end: Int,
|
||||
fontMetricsInt: Paint.FontMetricsInt?
|
||||
): Int {
|
||||
val drawable = drawable
|
||||
val rect = drawable.bounds
|
||||
if (fontMetricsInt != null) {
|
||||
val fmPaint = paint.fontMetricsInt
|
||||
val fontHeight = fmPaint.descent - fmPaint.ascent
|
||||
val drHeight = rect.bottom - rect.top
|
||||
val centerY = fmPaint.ascent + fontHeight / 2
|
||||
fontMetricsInt.ascent = centerY - drHeight / 2
|
||||
fontMetricsInt.top = fontMetricsInt.ascent
|
||||
fontMetricsInt.bottom = centerY + drHeight / 2
|
||||
fontMetricsInt.descent = fontMetricsInt.bottom
|
||||
}
|
||||
return rect.right
|
||||
}
|
||||
|
||||
/**
|
||||
* see detail message in android.text.TextLine
|
||||
*
|
||||
* @param canvas the canvas, can be null if not rendering
|
||||
* @param text the text to be draw
|
||||
* @param start the text start position
|
||||
* @param end the text end position
|
||||
* @param x the edge of the replacement closest to the leading margin
|
||||
* @param top the top of the line
|
||||
* @param y the baseline
|
||||
* @param bottom the bottom of the line
|
||||
* @param paint the work paint
|
||||
*/
|
||||
override fun draw(
|
||||
canvas: Canvas, text: CharSequence, start: Int, end: Int,
|
||||
x: Float, top: Int, y: Int, bottom: Int, paint: Paint
|
||||
) {
|
||||
val drawable = drawable
|
||||
canvas.save()
|
||||
val fmPaint = paint.fontMetricsInt
|
||||
val fontHeight = fmPaint.descent - fmPaint.ascent
|
||||
val centerY = y + fmPaint.descent - fontHeight / 2
|
||||
val transY = centerY - (drawable.bounds.bottom - drawable.bounds.top) / 2
|
||||
canvas.translate(x, transY.toFloat())
|
||||
drawable.draw(canvas)
|
||||
canvas.restore()
|
||||
}
|
||||
}
|
@@ -79,4 +79,6 @@
|
||||
<color name="text_hint_555574">#B3333333</color>
|
||||
<color name="color_f4f4fa">#FFF4F4FA</color>
|
||||
|
||||
|
||||
|
||||
</resources>
|