diff --git a/app/src/main/java/com/yizhuan/erban/avroom/dialog/RoomOperationDialog.java b/app/src/main/java/com/yizhuan/erban/avroom/dialog/RoomOperationDialog.java index 7e3674f47..54455de41 100644 --- a/app/src/main/java/com/yizhuan/erban/avroom/dialog/RoomOperationDialog.java +++ b/app/src/main/java/com/yizhuan/erban/avroom/dialog/RoomOperationDialog.java @@ -341,7 +341,9 @@ public class RoomOperationDialog extends BottomSheetDialog { * @param optAdapter */ private void addRedPacketAction(OptAdapter optAdapter) { - if (AvRoomDataManager.get().isRedEnvelopeOpen()) { + // TODO 临时打开 +// if (AvRoomDataManager.get().isRedEnvelopeOpen()) { + if (true) { RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; if (roomInfo == null) { return; diff --git a/app/src/main/java/com/yizhuan/erban/avroom/redpackage/send/PrivateRedPackageEditorFragment.kt b/app/src/main/java/com/yizhuan/erban/avroom/redpackage/send/PrivateRedPackageEditorFragment.kt new file mode 100644 index 000000000..5f4f92f3b --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/redpackage/send/PrivateRedPackageEditorFragment.kt @@ -0,0 +1,121 @@ +package com.yizhuan.erban.avroom.redpackage.send + +import android.graphics.Color +import androidx.core.view.isVisible +import com.chuhai.utils.ktx.getColorById +import com.yizhuan.erban.R +import com.yizhuan.erban.base.BaseBindingFragment +import com.yizhuan.erban.databinding.RedPackagePrivateFragmentBinding +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil +import com.yizhuan.erban.ui.widget.recyclerview.decoration.ColorDecoration +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes + +/** + * Created by Max on 2023/10/23 12:14 + * Desc: + **/ +@ActLayoutRes(R.layout.red_package_private_fragment) +class PrivateRedPackageEditorFragment : BaseBindingFragment() { + override fun initiate() { + initTypeView() + updateTimeView(true) + } + + override fun onSetListener() { + super.onSetListener() + mBinding.tvNow.setOnClickListener { + updateTimeView(true) + } + mBinding.tvDelay.setOnClickListener { + updateTimeView(false) + } + } + + private fun initTypeView() { + mBinding.recyclerView.addItemDecoration( + ColorDecoration( + Color.TRANSPARENT, UIUtil.dip2px(context, 6.0), 0, false + ) + ) + val list = ArrayList() + list.add( + RedPackageTypeItemAdapter.ItemData( + "UNLIMITED", + R.string.red_package_type_unlimited_name, + R.string.red_package_type_unlimited_tips + ) + ) + list.add( + RedPackageTypeItemAdapter.ItemData( + "FOLLOW", + R.string.red_package_type_follow_name, + R.string.red_package_type_follow_tips + ) + ) + list.add( + RedPackageTypeItemAdapter.ItemData( + "SHARE", + R.string.red_package_type_share_name, + R.string.red_package_type_share_tips + ) + ) + list.add( + RedPackageTypeItemAdapter.ItemData( + "MSG", + R.string.red_package_type_msg_name, + R.string.red_package_type_msg_tips + ) + ) + val adapter = RedPackageTypeItemAdapter(list) + 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: String?) { + when (type) { + "UNLIMITED" -> { + mBinding.tvNow.isVisible = true + mBinding.tvDelay.isVisible = true + mBinding.etText.isVisible = false + } + + "MSG" -> { + 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) { + 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 { + 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)) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/avroom/redpackage/send/PublicRedPackageEditorFragment.kt b/app/src/main/java/com/yizhuan/erban/avroom/redpackage/send/PublicRedPackageEditorFragment.kt new file mode 100644 index 000000000..12b94ff0f --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/redpackage/send/PublicRedPackageEditorFragment.kt @@ -0,0 +1,17 @@ +package com.yizhuan.erban.avroom.redpackage.send + +import com.yizhuan.erban.R +import com.yizhuan.erban.base.BaseBindingFragment +import com.yizhuan.erban.databinding.RedPackagePrivateFragmentBinding +import com.yizhuan.erban.databinding.RedPackagePublicFragmentBinding +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes + +/** + * Created by Max on 2023/10/23 12:14 + * Desc: + **/ +@ActLayoutRes(R.layout.red_package_public_fragment) +class PublicRedPackageEditorFragment : BaseBindingFragment() { + override fun initiate() { + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/avroom/redpackage/send/RedPackageSendDialog2.kt b/app/src/main/java/com/yizhuan/erban/avroom/redpackage/send/RedPackageSendDialog2.kt new file mode 100644 index 000000000..4873edb94 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/redpackage/send/RedPackageSendDialog2.kt @@ -0,0 +1,62 @@ +package com.yizhuan.erban.avroom.redpackage.send + + +import android.annotation.SuppressLint +import android.view.Gravity +import android.view.WindowManager +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.DialogRedPackageSend2Binding +import com.yizhuan.erban.home.adapter.ContactsIndicatorAdapter +import com.yizhuan.erban.ui.widget.magicindicator.ViewPagerHelper +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.CommonNavigator +import com.yizhuan.xchat_android_core.redpackage.* +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes +import org.greenrobot.eventbus.EventBus +import org.greenrobot.eventbus.Subscribe +import org.greenrobot.eventbus.ThreadMode + +@ActLayoutRes(R.layout.dialog_red_package_send2) +class RedPackageSendDialog2 : BaseDialog() { + + 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) + val tabTitles = arrayListOf("厅内红包", "全服红包") + val topMagicIndicatorAdapter = ContactsIndicatorAdapter(context, tabTitles, 1) + 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) + } + + override fun onDestroy() { + super.onDestroy() + EventBus.getDefault().unregister(this) + } + + @Subscribe(threadMode = ThreadMode.MAIN) + fun handleRedPackageDialog(event: RedPackageEvent?) { + dismissAllowingStateLoss() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/avroom/redpackage/send/RedPackageTypeItemAdapter.kt b/app/src/main/java/com/yizhuan/erban/avroom/redpackage/send/RedPackageTypeItemAdapter.kt new file mode 100644 index 000000000..1d5eb05b1 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/redpackage/send/RedPackageTypeItemAdapter.kt @@ -0,0 +1,71 @@ +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) : + BaseQuickAdapter( + R.layout.red_package_private_item_type, + list + ) { + + private var selectPosition = -1 + + @Keep + data class ItemData(val type: String, 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 + ) { + 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) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/avroom/redpackage/send/TabIndicatorAdapter.java b/app/src/main/java/com/yizhuan/erban/avroom/redpackage/send/TabIndicatorAdapter.java new file mode 100644 index 000000000..ec3905747 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/redpackage/send/TabIndicatorAdapter.java @@ -0,0 +1,117 @@ +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.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 mTitleList; + private Context mContext; + private int mBottomMargin; + + public TabIndicatorAdapter(Context mContext, List mTitleList, int bottomMargin) { + this.mTitleList = mTitleList; + this.mContext = mContext; + mBottomMargin = bottomMargin; + } + + @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, 5)); + indicator.setRoundRadius(UIUtil.dip2px(mContext, 5)); + indicator.setLineWidth(UIUtil.dip2px(mContext, 9)); + indicator.setColors(context.getResources().getColor(R.color.app_248cfe)); + FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); + lp.bottomMargin = mBottomMargin; + 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(), 30)); + setTextSize(16); + 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_333333)); + } + + @Override + public void onDeselected(int index, int totalCount) { +// setBackgroundDrawable(null); + setTextColor(getResources().getColor(R.color.color_666666)); + } + + @Override + public void onLeave(int index, int totalCount, float leavePercent, boolean leftToRight) { + + } + + @Override + public void onEnter(int index, int totalCount, float enterPercent, boolean leftToRight) { + + } + } + + +} diff --git a/app/src/main/java/com/yizhuan/erban/home/adapter/ContactsIndicatorAdapter.java b/app/src/main/java/com/yizhuan/erban/home/adapter/ContactsIndicatorAdapter.java index 3f2853ea8..deb4f7745 100644 --- a/app/src/main/java/com/yizhuan/erban/home/adapter/ContactsIndicatorAdapter.java +++ b/app/src/main/java/com/yizhuan/erban/home/adapter/ContactsIndicatorAdapter.java @@ -57,10 +57,10 @@ public class ContactsIndicatorAdapter extends CommonNavigatorAdapter { public IPagerIndicator getIndicator(Context context) { LinePagerIndicator indicator = new LinePagerIndicator(context); indicator.setMode(LinePagerIndicator.MODE_EXACTLY); - indicator.setLineHeight(UIUtil.dip2px(mContext, 5)); - indicator.setRoundRadius(UIUtil.dip2px(mContext, 5)); - indicator.setLineWidth(UIUtil.dip2px(mContext, 9)); - indicator.setColors(context.getResources().getColor(R.color.app_248cfe)); + 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.bottomMargin = mBottomMargin; indicator.setLayoutParams(lp); @@ -82,8 +82,8 @@ public class ContactsIndicatorAdapter extends CommonNavigatorAdapter { public ContactsPagerTitleView(Context context, String tabInfo) { super(context); - setHeight(Utils.dip2px(getContext(), 30)); - setTextSize(16); + setHeight(Utils.dip2px(getContext(), 25)); + setTextSize(18); setText(tabInfo); setGravity(Gravity.CENTER); diff --git a/app/src/main/java/com/yizhuan/erban/ui/setting/SettingActivity.kt b/app/src/main/java/com/yizhuan/erban/ui/setting/SettingActivity.kt index 00481a7ba..64ab86c65 100644 --- a/app/src/main/java/com/yizhuan/erban/ui/setting/SettingActivity.kt +++ b/app/src/main/java/com/yizhuan/erban/ui/setting/SettingActivity.kt @@ -8,8 +8,10 @@ import android.text.SpannableString import android.view.View 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.avroom.redpackage.send.RedPackageSendDialog2 import com.yizhuan.erban.base.BaseViewBindingActivity import com.yizhuan.erban.common.widget.dialog.DialogManager.OkCancelDialogListener import com.yizhuan.erban.databinding.ActivitySettingBinding @@ -74,6 +76,12 @@ class SettingActivity : BaseViewBindingActivity(), View. binding.tvShieldManager.setOnClickListener(this) binding.rlyPermission.setOnClickListener(this) binding.rlyCheck.setOnClickListener(this) + + if (BuildConfig.DEBUG) { + binding.titleBar.setOnTitleClickListener { + RedPackageSendDialog2().show(this) + } + } } @SuppressLint("CheckResult") diff --git a/app/src/main/java/com/yizhuan/erban/view/WrapHeightViewPager.kt b/app/src/main/java/com/yizhuan/erban/view/WrapHeightViewPager.kt new file mode 100644 index 000000000..2b1523560 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/view/WrapHeightViewPager.kt @@ -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 + ) + ) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/red_package_bg_balance.xml b/app/src/main/res/drawable/red_package_bg_balance.xml new file mode 100644 index 000000000..563c60cf1 --- /dev/null +++ b/app/src/main/res/drawable/red_package_bg_balance.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/red_package_bg_type_selected.xml b/app/src/main/res/drawable/red_package_bg_type_selected.xml new file mode 100644 index 000000000..a93199994 --- /dev/null +++ b/app/src/main/res/drawable/red_package_bg_type_selected.xml @@ -0,0 +1,9 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_g_ff6060_ff225c_26_lr.xml b/app/src/main/res/drawable/shape_g_ff6060_ff225c_26_lr.xml new file mode 100644 index 000000000..2e88e8183 --- /dev/null +++ b/app/src/main/res/drawable/shape_g_ff6060_ff225c_26_lr.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/red_package_private_fragment.xml b/app/src/main/res/layout/red_package_private_fragment.xml new file mode 100644 index 000000000..5eda54be8 --- /dev/null +++ b/app/src/main/res/layout/red_package_private_fragment.xml @@ -0,0 +1,231 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index eeb12a542..953d48518 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -703,5 +703,9 @@ #1E686868 #9E9EA8 #001338 + #FF285C + #322F4D + #EBEEF5 + #94959C diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f2081ca9c..eacc4899c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -5143,4 +5143,13 @@ 當前無需選擇解鎖禮物 選擇解鎖禮物 + 無門檻紅包 + 所有人均可參與 + 關註紅包 + 關註主播可參與 + 分享紅包 + 分享房間可參與 + 發彈幕紅包 + 發指定彈幕內容 + \ No newline at end of file diff --git a/app/src/module_super_admin/res/drawable-xxhdpi/red_package_bg.webp b/app/src/module_super_admin/res/drawable-xxhdpi/red_package_bg.webp new file mode 100644 index 000000000..7c7c844ba Binary files /dev/null and b/app/src/module_super_admin/res/drawable-xxhdpi/red_package_bg.webp differ diff --git a/app/src/module_super_admin/res/drawable-xxhdpi/red_package_ic.webp b/app/src/module_super_admin/res/drawable-xxhdpi/red_package_ic.webp new file mode 100644 index 000000000..07bf608f5 Binary files /dev/null and b/app/src/module_super_admin/res/drawable-xxhdpi/red_package_ic.webp differ diff --git a/app/src/module_super_admin/res/drawable-xxhdpi/red_package_ic_diamond.webp b/app/src/module_super_admin/res/drawable-xxhdpi/red_package_ic_diamond.webp new file mode 100644 index 000000000..12623a70d Binary files /dev/null and b/app/src/module_super_admin/res/drawable-xxhdpi/red_package_ic_diamond.webp differ diff --git a/app/src/module_super_admin/res/drawable/red_package_ic_add.xml b/app/src/module_super_admin/res/drawable/red_package_ic_add.xml new file mode 100644 index 000000000..c774d9f61 --- /dev/null +++ b/app/src/module_super_admin/res/drawable/red_package_ic_add.xml @@ -0,0 +1,12 @@ + + + diff --git a/app/src/module_super_admin/res/drawable/red_package_ic_help.xml b/app/src/module_super_admin/res/drawable/red_package_ic_help.xml new file mode 100644 index 000000000..c3905e0c2 --- /dev/null +++ b/app/src/module_super_admin/res/drawable/red_package_ic_help.xml @@ -0,0 +1,22 @@ + + + + diff --git a/app/src/module_super_admin/res/drawable/shape_f8f8fa_8.xml b/app/src/module_super_admin/res/drawable/shape_f8f8fa_8.xml new file mode 100644 index 000000000..103f85690 --- /dev/null +++ b/app/src/module_super_admin/res/drawable/shape_f8f8fa_8.xml @@ -0,0 +1,7 @@ + + + + + + diff --git a/app/src/module_super_admin/res/layout/dialog_red_package_send2.xml b/app/src/module_super_admin/res/layout/dialog_red_package_send2.xml new file mode 100644 index 000000000..c79a6dac0 --- /dev/null +++ b/app/src/module_super_admin/res/layout/dialog_red_package_send2.xml @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/module_super_admin/res/layout/red_package_private_item_type.xml b/app/src/module_super_admin/res/layout/red_package_private_item_type.xml new file mode 100644 index 000000000..11495e7cf --- /dev/null +++ b/app/src/module_super_admin/res/layout/red_package_private_item_type.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/module_super_admin/res/layout/red_package_public_fragment.xml b/app/src/module_super_admin/res/layout/red_package_public_fragment.xml new file mode 100644 index 000000000..b94af206f --- /dev/null +++ b/app/src/module_super_admin/res/layout/red_package_public_fragment.xml @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/library/build.gradle b/library/build.gradle index 49eb74e47..3f2cc8384 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -35,6 +35,7 @@ android { 'src/module_luban/java', 'src/module_easyphoto/java', 'src/module_common/java', + 'src/module_utils/java', ] @@ -43,6 +44,7 @@ android { 'src/module_easypermission/res', 'src/module_easyphoto/res', 'src/module_common/res', + 'src/module_utils/res', ] @@ -144,6 +146,9 @@ dependencies { api 'com.facebook.android:facebook-android-sdk:16.2.0' api 'com.facebook.android:facebook-login:16.2.0' + // 网络请求chrome数据调试 + implementation 'com.facebook.stetho:stetho:1.5.1' + implementation 'com.facebook.stetho:stetho-okhttp3:1.5.1' } repositories { mavenCentral() diff --git a/library/src/main/java/com/yizhuan/xchat_android_library/net/rxnet/manager/RxNetManager.java b/library/src/main/java/com/yizhuan/xchat_android_library/net/rxnet/manager/RxNetManager.java index f3e6d6813..bcb5187d1 100644 --- a/library/src/main/java/com/yizhuan/xchat_android_library/net/rxnet/manager/RxNetManager.java +++ b/library/src/main/java/com/yizhuan/xchat_android_library/net/rxnet/manager/RxNetManager.java @@ -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) { diff --git a/library/src/module_common/java/com/yizhuan/xchat_android_library/common/application/BaseApp.java b/library/src/module_common/java/com/yizhuan/xchat_android_library/common/application/BaseApp.java index 58ee9d3b5..b8a0fa251 100644 --- a/library/src/module_common/java/com/yizhuan/xchat_android_library/common/application/BaseApp.java +++ b/library/src/module_common/java/com/yizhuan/xchat_android_library/common/application/BaseApp.java @@ -26,6 +26,7 @@ public abstract class BaseApp extends Application{ public static void init(Application application) { gContext = application; + com.chuhai.utils.AppUtils.init(application); } /** diff --git a/library/src/module_utils/java/com/chuhai/utils/AppUtils.java b/library/src/module_utils/java/com/chuhai/utils/AppUtils.java new file mode 100644 index 000000000..c232c3605 --- /dev/null +++ b/library/src/module_utils/java/com/chuhai/utils/AppUtils.java @@ -0,0 +1,403 @@ +package com.chuhai.utils; + +import android.annotation.SuppressLint; +import android.app.ActivityManager; +import android.app.Application; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.location.LocationManager; +import android.os.Handler; +import android.os.Looper; +import android.provider.Settings; +import android.text.TextUtils; +import android.view.View; +import android.view.Window; +import android.view.inputmethod.InputMethodManager; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + *
+ *     author:
+ *                                      ___           ___           ___         ___
+ *         _____                       /  /\         /__/\         /__/|       /  /\
+ *        /  /::\                     /  /::\        \  \:\       |  |:|      /  /:/
+ *       /  /:/\:\    ___     ___    /  /:/\:\        \  \:\      |  |:|     /__/::\
+ *      /  /:/~/::\  /__/\   /  /\  /  /:/~/::\   _____\__\:\   __|  |:|     \__\/\:\
+ *     /__/:/ /:/\:| \  \:\ /  /:/ /__/:/ /:/\:\ /__/::::::::\ /__/\_|:|____    \  \:\
+ *     \  \:\/:/~/:/  \  \:\  /:/  \  \:\/:/__\/ \  \:\~~\~~\/ \  \:\/:::::/     \__\:\
+ *      \  \::/ /:/    \  \:\/:/    \  \::/       \  \:\  ~~~   \  \::/~~~~      /  /:/
+ *       \  \:\/:/      \  \::/      \  \:\        \  \:\        \  \:\         /__/:/
+ *        \  \::/        \__\/        \  \:\        \  \:\        \  \:\        \__\/
+ *         \__\/                       \__\/         \__\/         \__\/
+ *     blog  : http://blankj.com
+ *     time  : 16/12/08
+ *     desc  : utils about initialization
+ * 
+ */ +public final class AppUtils { + + private static final ExecutorService UTIL_POOL = Executors.newFixedThreadPool(3); + private static final Handler UTIL_HANDLER = new Handler(Looper.getMainLooper()); + + @SuppressLint("StaticFieldLeak") + private static Application sApplication; + + + private AppUtils() { + throw new UnsupportedOperationException("u can't instantiate me..."); + } + + /** + * Init utils. + *

Init it in the class of Application.

+ * + * @param context context + */ + public static void init(final Context context) { + if (context == null) { + init(getApplicationByReflect()); + return; + } + init((Application) context.getApplicationContext()); + } + + /** + * Init utils. + *

Init it in the class of Application.

+ * + * @param app application + */ + public static void init(final Application app) { + if (sApplication == null) { + if (app == null) { + sApplication = getApplicationByReflect(); + } else { + sApplication = app; + } + } else { + sApplication = app; + } + } + + /** + * Return the context of Application object. + * + * @return the context of Application object + */ + public static Application getApp() { + if (sApplication != null) return sApplication; + Application app = getApplicationByReflect(); + init(app); + return app; + } + + + public static String getPackageName(Context context) { + return context.getPackageName(); + } + + /** + * 获取版本名 + * + * @param noSuffix 是否去掉后缀 (如:-debug、-test) + */ + public static String getVersionName(boolean noSuffix) { + PackageInfo packageInfo = getPackageInfo(getApp()); + if (packageInfo != null) { + String versionName = packageInfo.versionName; + if (noSuffix && versionName != null) { + int index = versionName.indexOf("-"); + if (index >= 0) { + return versionName.substring(0, index); + } + } + return versionName; + } + return ""; + } + + //版本号 + public static int getVersionCode() { + PackageInfo packageInfo = getPackageInfo(getApp()); + if (packageInfo != null) { + return packageInfo.versionCode; + } + return 0; + } + + /** + * 比较版本 + * 1 = 大于当前版本 + * 0 = 版本一样 + * -1 = 当前版本大于更新版本 + */ + public static int compareVersionNames(String newVersionName) { + try { + if (TextUtils.isEmpty(newVersionName)) { + return -1; + } + int res = 0; + String currentVersionName = getVersionName(true); + if (currentVersionName.equals(newVersionName)) { + return 0; + } + + String[] oldNumbers = currentVersionName.split("\\."); + String[] newNumbers = newVersionName.split("\\."); + + // To avoid IndexOutOfBounds + int minIndex = Math.min(oldNumbers.length, newNumbers.length); + + for (int i = 0; i < minIndex; i++) { + int oldVersionPart = Integer.parseInt(oldNumbers[i]); + int newVersionPart = Integer.parseInt(newNumbers[i]); + + if (oldVersionPart < newVersionPart) { + res = 1; + break; + } else if (oldVersionPart > newVersionPart) { + res = -1; + break; + } + } + + // If versions are the same so far, but they have different length... + if (res == 0 && oldNumbers.length != newNumbers.length) { + res = (oldNumbers.length > newNumbers.length) ? -1 : 1; + } + + return res; + } catch (Exception e) { + return -1; + } + } + + private static PackageInfo getPackageInfo(Context context) { + PackageInfo packageInfo; + try { + PackageManager pm = context.getPackageManager(); + packageInfo = pm.getPackageInfo(context.getPackageName(), PackageManager.GET_CONFIGURATIONS); + return packageInfo; + } catch (Exception e) { + return null; + } + } + + static Task doAsync(final Task task) { + UTIL_POOL.execute(task); + return task; + } + + public static void runOnUiThread(final Runnable runnable) { + if (Looper.myLooper() == Looper.getMainLooper()) { + runnable.run(); + } else { + AppUtils.UTIL_HANDLER.post(runnable); + } + } + + public static void runOnUiThreadDelayed(final Runnable runnable, long delayMillis) { + AppUtils.UTIL_HANDLER.postDelayed(runnable, delayMillis); + } + + static String getCurrentProcessName() { + String name = getCurrentProcessNameByFile(); + if (!TextUtils.isEmpty(name)) return name; + name = getCurrentProcessNameByAms(); + if (!TextUtils.isEmpty(name)) return name; + name = getCurrentProcessNameByReflect(); + return name; + } + + static void fixSoftInputLeaks(final Window window) { + InputMethodManager imm = + (InputMethodManager) AppUtils.getApp().getSystemService(Context.INPUT_METHOD_SERVICE); + if (imm == null) return; + String[] leakViews = new String[]{"mLastSrvView", "mCurRootView", "mServedView", "mNextServedView"}; + for (String leakView : leakViews) { + try { + Field leakViewField = InputMethodManager.class.getDeclaredField(leakView); + if (leakViewField == null) continue; + if (!leakViewField.isAccessible()) { + leakViewField.setAccessible(true); + } + Object obj = leakViewField.get(imm); + if (!(obj instanceof View)) continue; + View view = (View) obj; + if (view.getRootView() == window.getDecorView().getRootView()) { + leakViewField.set(imm, null); + } + } catch (Throwable ignore) {/**/} + } + } + + + /////////////////////////////////////////////////////////////////////////// + // private method + /////////////////////////////////////////////////////////////////////////// + + private static String getCurrentProcessNameByFile() { + try { + File file = new File("/proc/" + android.os.Process.myPid() + "/" + "cmdline"); + BufferedReader mBufferedReader = new BufferedReader(new FileReader(file)); + String processName = mBufferedReader.readLine().trim(); + mBufferedReader.close(); + return processName; + } catch (Exception e) { + e.printStackTrace(); + return ""; + } + } + + private static String getCurrentProcessNameByAms() { + ActivityManager am = (ActivityManager) AppUtils.getApp().getSystemService(Context.ACTIVITY_SERVICE); + if (am == null) return ""; + List info = am.getRunningAppProcesses(); + if (info == null || info.size() == 0) return ""; + int pid = android.os.Process.myPid(); + for (ActivityManager.RunningAppProcessInfo aInfo : info) { + if (aInfo.pid == pid) { + if (aInfo.processName != null) { + return aInfo.processName; + } + } + } + return ""; + } + + private static String getCurrentProcessNameByReflect() { + String processName = ""; + try { + Application app = AppUtils.getApp(); + Field loadedApkField = app.getClass().getField("mLoadedApk"); + loadedApkField.setAccessible(true); + Object loadedApk = loadedApkField.get(app); + + Field activityThreadField = loadedApk.getClass().getDeclaredField("mActivityThread"); + activityThreadField.setAccessible(true); + Object activityThread = activityThreadField.get(loadedApk); + + Method getProcessName = activityThread.getClass().getDeclaredMethod("getProcessName"); + processName = (String) getProcessName.invoke(activityThread); + } catch (Exception e) { + e.printStackTrace(); + } + return processName; + } + + private static Application getApplicationByReflect() { + try { + @SuppressLint("PrivateApi") + Class activityThread = Class.forName("android.app.ActivityThread"); + Object thread = activityThread.getMethod("currentActivityThread").invoke(null); + Object app = activityThread.getMethod("getApplication").invoke(thread); + if (app == null) { + throw new NullPointerException("u should init first"); + } + return (Application) app; + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + throw new NullPointerException("u should init first"); + } + + + /////////////////////////////////////////////////////////////////////////// + // interface + /////////////////////////////////////////////////////////////////////////// + + public abstract static class Task implements Runnable { + + private static final int NEW = 0; + private static final int COMPLETING = 1; + private static final int CANCELLED = 2; + private static final int EXCEPTIONAL = 3; + + private volatile int state = NEW; + + abstract Result doInBackground(); + + private final Callback mCallback; + + public Task(final Callback callback) { + mCallback = callback; + } + + @Override + public void run() { + try { + final Result t = doInBackground(); + + if (state != NEW) return; + state = COMPLETING; + UTIL_HANDLER.post(new Runnable() { + @Override + public void run() { + mCallback.onCall(t); + } + }); + } catch (Throwable th) { + if (state != NEW) return; + state = EXCEPTIONAL; + } + } + + public void cancel() { + state = CANCELLED; + } + + public boolean isDone() { + return state != NEW; + } + + public boolean isCanceled() { + return state == CANCELLED; + } + } + + public interface Callback { + void onCall(T data); + } + + /** + * 判断是否打开定位 + */ + public static boolean getGpsStatus(Context ctx) { + //从系统服务中获取定位管理器 + LocationManager locationManager + = (LocationManager) ctx.getSystemService(Context.LOCATION_SERVICE); + // 通过GPS卫星定位,定位级别可以精确到街(通过24颗卫星定位,在室外和空旷的地方定位准确、速度快) + boolean gps = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER); + // 通过WLAN或移动网络(3G/2G)确定的位置(也称作AGPS,辅助GPS定位。主要用于在室内或遮盖物(建筑群或茂密的深林等)密集的地方定位) + boolean network = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER); + if (gps || network) { + return true; + } + return false; + } + + /** + * 打开系统定位界面 + */ + public static void goToOpenGps(Context ctx) { + Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS); + ctx.startActivity(intent); + } +} \ No newline at end of file diff --git a/library/src/module_utils/java/com/chuhai/utils/ktx/ResourcesKtx.kt b/library/src/module_utils/java/com/chuhai/utils/ktx/ResourcesKtx.kt new file mode 100644 index 000000000..d1550c236 --- /dev/null +++ b/library/src/module_utils/java/com/chuhai/utils/ktx/ResourcesKtx.kt @@ -0,0 +1,195 @@ +package com.chuhai.utils.ktx + +import android.app.Activity +import android.content.Context +import android.content.res.TypedArray +import android.graphics.drawable.Drawable +import android.util.TypedValue +import androidx.annotation.* +import androidx.core.content.ContextCompat +import androidx.core.content.res.ResourcesCompat +import androidx.fragment.app.Fragment +import com.chuhai.utils.AppUtils + +/** + * 资源工具类 + * @author Max + * @date 2019-11-26. + */ + + +/** + * 获取颜色 + */ +fun Fragment.getColorById(@ColorRes colorResId: Int): Int { + return ContextCompat.getColor(context!!, colorResId) +} + + +/** + * 获取图片 + */ +fun Fragment.getDrawableById(@DrawableRes drawableRedId: Int): Drawable? { + return ContextCompat.getDrawable(context!!, drawableRedId) +} + + +/** + * 获取颜色 + */ +fun Activity.getColorById(@ColorRes colorResId: Int): Int { + return ContextCompat.getColor(this, colorResId) +} + +/** + * 获取图片 + */ +fun Activity.getDrawableById(@DrawableRes drawableRedId: Int): Drawable? { + return ContextCompat.getDrawable(this, drawableRedId) +} + + +/** + * 获取颜色 + */ +fun Context.getColorById(@ColorRes colorResId: Int): Int { + return ContextCompat.getColor(this, colorResId) +} + +/** + * 获取图片 + */ +fun Context.getDrawableById(@DrawableRes drawableRedId: Int): Drawable? { + return ContextCompat.getDrawable(this, drawableRedId) +} + + +/** + * 获取字符串资源 + */ +fun Any.getStringById(@StringRes stringResId: Int): String { + return AppUtils.getApp().getString(stringResId) +} + +/** + * 获取字符串资源 + */ +fun Int.toStringRes(): String { + return AppUtils.getApp().getString(this) +} + +/** + * 获取资源drawable + * */ +fun Int.toDrawableRes(): Drawable? { + return ContextCompat.getDrawable(AppUtils.getApp(), this) +} + +/** + * 获取资源color + * */ +fun Int.toColorRes(): Int { + return ContextCompat.getColor(AppUtils.getApp(), this) +} + +/** + * 通过自定义属性-获取DrawableRes + */ +@DrawableRes +fun Context.getDrawableResFromAttr( + @AttrRes attrResId: Int, + typedValue: TypedValue = TypedValue(), + resolveRefs: Boolean = true +): Int? { + return try { + theme.resolveAttribute(attrResId, typedValue, resolveRefs) + return typedValue.resourceId + } catch (e: Exception) { + e.printStackTrace() + null + } +} + +/** + * 通过自定义属性-获取Drawable + */ +fun Context.getDrawableFromAttr(@AttrRes attrId: Int): Drawable? { + return try { + val drawableRes = getDrawableResFromAttr(attrId) ?: return null + ResourcesCompat.getDrawable(resources, drawableRes, null) + } catch (e: Exception) { + e.printStackTrace() + null + } +} + +/** + * 通过自定义属性-获取ColorRes + */ +@ColorRes +fun Context.getColorResFromAttr( + @AttrRes attrResId: Int, + typedValue: TypedValue = TypedValue(), + resolveRefs: Boolean = true +): Int? { + return try { + theme.resolveAttribute(attrResId, typedValue, resolveRefs) + return typedValue.resourceId + } catch (e: Exception) { + e.printStackTrace() + null + } +} + +/** + * 通过自定义属性-获取Color + */ +@ColorRes +fun Context.getColorFromAttr( + @AttrRes attrResId: Int +): Int? { + return try { + val colorRes = getColorFromAttr(attrResId) ?: return null + ResourcesCompat.getColor(resources, colorRes, null) + } catch (e: Exception) { + e.printStackTrace() + null + } +} + +/** + * 通过自定义属性-获取LayoutRes + */ +@LayoutRes +fun Context.getLayoutResFromAttr( + @AttrRes attrResId: Int, + typedValue: TypedValue = TypedValue(), + resolveRefs: Boolean = true +): Int? { + return try { + theme.resolveAttribute(attrResId, typedValue, resolveRefs) + return typedValue.resourceId + } catch (e: Exception) { + e.printStackTrace() + null + } +} + +/** + * 通过自定义属性-获取Boolean + */ +fun Context.getBooleanResFromAttr( + @AttrRes attrResId: Int, + defValue: Boolean = false +): Boolean { + var attrs: TypedArray? = null + try { + attrs = obtainStyledAttributes(null, intArrayOf(attrResId)) + return attrs.getBoolean(0, defValue) + } catch (e: Exception) { + e.printStackTrace() + } finally { + attrs?.recycle() + } + return defValue +} diff --git a/library/src/module_utils/res/values/ids.xml b/library/src/module_utils/res/values/ids.xml new file mode 100644 index 000000000..78554f9eb --- /dev/null +++ b/library/src/module_utils/res/values/ids.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/library/src/module_utils/res/values/strings.xml b/library/src/module_utils/res/values/strings.xml new file mode 100644 index 000000000..f11f7450a --- /dev/null +++ b/library/src/module_utils/res/values/strings.xml @@ -0,0 +1,3 @@ + + +