feat: 更新 VIP 页面 UI & 功能

This commit is contained in:
eggmanQQQ
2024-08-26 09:13:28 +08:00
parent cb4dac8e81
commit 3d29568b3c
6 changed files with 156 additions and 76 deletions

View File

@@ -25,6 +25,7 @@ import com.chwl.app.databinding.ActivityVipCenterBinding
import com.chwl.app.ui.pay.ChargeActivity import com.chwl.app.ui.pay.ChargeActivity
import com.chwl.app.ui.utils.RVDelegate import com.chwl.app.ui.utils.RVDelegate
import com.chwl.app.ui.webview.CommonWebViewActivity import com.chwl.app.ui.webview.CommonWebViewActivity
import com.chwl.app.vip.adapter.OnItemClickListener
import com.chwl.app.vip.adapter.VipAuthAdapter import com.chwl.app.vip.adapter.VipAuthAdapter
import com.chwl.app.vip.adapter.VipCenterBannerAdapter import com.chwl.app.vip.adapter.VipCenterBannerAdapter
import com.chwl.app.vip.adapter.VipCenterIdentificationsAdapter import com.chwl.app.vip.adapter.VipCenterIdentificationsAdapter
@@ -41,6 +42,7 @@ import com.chwl.core.vip.bean.VipInfo
import com.example.module_base.support.billing.IBillingService import com.example.module_base.support.billing.IBillingService
import com.example.module_base.support.billing.IProductDetails import com.example.module_base.support.billing.IProductDetails
import com.example.module_base.support.billing.IPurchase import com.example.module_base.support.billing.IPurchase
import com.netease.nim.uikit.StatusBarUtil
import com.youth.banner.Banner import com.youth.banner.Banner
import com.youth.banner.adapter.BannerImageAdapter import com.youth.banner.adapter.BannerImageAdapter
import com.youth.banner.holder.BannerImageHolder import com.youth.banner.holder.BannerImageHolder
@@ -50,10 +52,11 @@ import com.youth.banner.transformer.DepthPageTransformer
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.EventBus
import com.youth.banner.listener.OnPageChangeListener
class VipCenterActivity : BaseViewBindingActivity<ActivityVipCenterBinding>(), class VipCenterActivity : BaseViewBindingActivity<ActivityVipCenterBinding>(),
VipMagicIndicatorAdapter.OnItemSelectListener, IBillingService.Listener { VipMagicIndicatorAdapter.OnItemSelectListener, OnItemClickListener, IBillingService.Listener {
private val authAdapter = VipAuthAdapter() // 用户权限 private val authAdapter = VipAuthAdapter() // 用户权限
private val vipViewModel: VipViewModel by viewModels() private val vipViewModel: VipViewModel by viewModels()
@@ -66,7 +69,7 @@ class VipCenterActivity : BaseViewBindingActivity<ActivityVipCenterBinding>(),
private lateinit var recyclerView: RecyclerView private lateinit var recyclerView: RecyclerView
private lateinit var vipIdentificationsAdapter: VipCenterIdentificationsAdapter private lateinit var vipIdentificationsAdapter: VipCenterIdentificationsAdapter
// protected var banner: Banner? = null private var currentIndex = 0
companion object { companion object {
@@ -88,10 +91,6 @@ class VipCenterActivity : BaseViewBindingActivity<ActivityVipCenterBinding>(),
initView() initView()
initObserve() initObserve()
handleAuthAdapter()
handleViewModel()
handleBinding()
rvDelegate = RVDelegate.Builder<VipAuthInfo>() rvDelegate = RVDelegate.Builder<VipAuthInfo>()
.setLayoutManager(GridLayoutManager(this, 3)) .setLayoutManager(GridLayoutManager(this, 3))
.setRecyclerView(binding.recyclerViewBottom) .setRecyclerView(binding.recyclerViewBottom)
@@ -110,6 +109,10 @@ class VipCenterActivity : BaseViewBindingActivity<ActivityVipCenterBinding>(),
} }
} }
handleAuthAdapter()
handleViewModel()
handleBinding()
requestChargeList{ requestChargeList{
loadChargeList(it) loadChargeList(it)
} }
@@ -117,17 +120,30 @@ class VipCenterActivity : BaseViewBindingActivity<ActivityVipCenterBinding>(),
private fun initView() { private fun initView() {
banner = findViewById(R.id.banner_view) banner = findViewById(R.id.banner_view)
banner.isAutoLoop(false)
banner.setBannerGalleryEffect(25, 25,25) banner.setBannerGalleryEffect(25, 25,25)
banner.addOnPageChangeListener(object : OnPageChangeListener {
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
// 页面滑动中
}
override fun onPageSelected(position: Int) {
// 页面被选中position 已更新
currentIndex = position
vipViewModel.onItemSelect(position)
}
override fun onPageScrollStateChanged(state: Int) {
// 页面滚动状态改变
}
})
recyclerView = findViewById(R.id.recycler_view) recyclerView = findViewById(R.id.recycler_view)
recyclerView.layoutManager = GridLayoutManager(this, 2) recyclerView.layoutManager = GridLayoutManager(this, 2)
// val identificationTitle = findViewById<TextView>(R.id.center_title) val identificationTitle = findViewById<TextView>(R.id.center_title)
// identificationTitle.text = R.string.vip_center_2.toString() identificationTitle.text = R.string.vip_center_2.toString()
// val exclusivePrivilegesTitle = findViewById<TextView>(R.id.center_title_2)
// val exclusivePrivilegesTitle = findViewById<TextView>(R.id.center_title_2) exclusivePrivilegesTitle.text = R.string.vip_center_4.toString()
// exclusivePrivilegesTitle.text = R.string.vip_center_4.toString()
} }
override fun initWhiteTitleBar(title: String?) { override fun initWhiteTitleBar(title: String?) {
@@ -182,48 +198,31 @@ class VipCenterActivity : BaseViewBindingActivity<ActivityVipCenterBinding>(),
// ArrayList[VipAuthInfo] // 全部特权列表 // ArrayList[VipAuthInfo] // 全部特权列表
authAdapter.setNewData(it) authAdapter.setNewData(it)
it?.let { it?.let {
vipIdentificationsAdapter = VipCenterIdentificationsAdapter(this, it) vipIdentificationsAdapter = VipCenterIdentificationsAdapter(this, it, this)
recyclerView.adapter = vipIdentificationsAdapter recyclerView.adapter = vipIdentificationsAdapter
} }
} }
vipViewModel.pageLiveData.observe(this) { vipViewModel.pageLiveData.observe(this) {
it?.let { // 当前显示的 index it?.let { // 当前显示的 index
// binding.magicIndicator.onPageSelected(it)
// TODO 处理轮播组件 index 更新 // TODO 处理轮播组件 index 更新
currentIndex = it
handleIdentificationAreaContent(it)
} }
} }
vipViewModel.vipInfosLiveData.observe(this) { vipViewModel.vipInfosLiveData.observe(this) {
it?.let { // ArrayList[VipInfo] 每个等级的 VIP 内容 it?.let { // ArrayList[VipInfo] 每个等级的 VIP 内容
// initTitleTab(it)
// TODO 初始化轮播组件 // TODO 初始化轮播组件
val adapter = VipCenterBannerAdapter(this, it) val adapter = VipCenterBannerAdapter(this, it)
banner.setAdapter(adapter) banner.setAdapter(adapter, false)
handleIdentificationAreaContent(0)
// banner.setAdapter(object : BannerImageAdapter<VipInfo>(it) {
// override fun onBindView(holder: BannerImageHolder, data: VipInfo, position: Int, size: Int) {
// //图片加载自己实现
// Glide.with(holder.itemView)
// .load(data.vipIcon)
// .apply(RequestOptions.bitmapTransform(RoundedCorners(30)))
// .into(holder.imageView)
// }
// override fun onCreateHolder(
// parent: ViewGroup?,
// viewType: Int
// ): BannerImageHolder {
// return super.onCreateHolder(parent, viewType)
// }
// }).addBannerLifecycleObserver(this)
// .setIndicator(CircleIndicator(this), false)
} }
} }
vipViewModel.myVipInfoLiveData.observe(this) { vipViewModel.myVipInfoLiveData.observe(this) {
it?.let { it?.let {
//TODO 处理有 VIP 的情况 //TODO 处理有 VIP 的情况banner 要跳转到对应 index
// bannerView.visibility = View.VISIBLE // bannerView.visibility = View.VISIBLE
// bannerView.post { // bannerView.post {
// binding.bannerView.setPageMargin(UIUtil.dip2px(mContext, 8.0)) // binding.bannerView.setPageMargin(UIUtil.dip2px(mContext, 8.0))
@@ -242,13 +241,37 @@ class VipCenterActivity : BaseViewBindingActivity<ActivityVipCenterBinding>(),
vipViewModel.currVipInfoLiveData.observe(this) { vipViewModel.currVipInfoLiveData.observe(this) {
it?.let { // VipInfo it?.let { // VipInfo
// TODO 根据当前显示的 VIP 信息更新 UI if (it.comingSoon == 2) {
/// 处理敬请期待情况, 补充显示 SVGA
binding.slAuth.isVisible = false
binding.bannerView.isVisible = false
binding.layoutBottomPanel.isVisible = false
// loadSVGA(binding.ivNotOpenIcon, it.vipLogo)
} else {
val myVipInfo = vipViewModel.myVipInfoLiveData.value
// TODO 根据当前显示的 VIP 信息更新 UI
authAdapter.setVipInfo(it)
authAdapter.notifyDataSetChanged()
// handleIdentificationAreaContent(it.vipLevel)
vipIdentificationsAdapter.setVipInfo(it)
}
} ?: run { } ?: run {
getString(R.string.me_failed_to_get_aristocrat_data).toast() getString(R.string.me_failed_to_get_aristocrat_data).toast()
} }
} }
} }
override fun onItemClick(position: Int) {
authAdapter.getItem(position)?.let {
VipAuthDetailsDialog.newInstance(it.descPic, it.authName, it.authIntro).show(this)
}
}
private fun handleIdentificationAreaContent(position: Int) {
// 条件:
}
@SuppressLint("CheckResult") @SuppressLint("CheckResult")
private fun requestChargeList(call: (List<ChargeBean>) -> Unit) { private fun requestChargeList(call: (List<ChargeBean>) -> Unit) {
PayModel.get().vipList PayModel.get().vipList
@@ -400,4 +423,10 @@ class VipCenterActivity : BaseViewBindingActivity<ActivityVipCenterBinding>(),
TODO("Not yet implemented") TODO("Not yet implemented")
} }
override fun needSteepStateBar() = true
override fun setStatusBar() {
super.setStatusBar()
StatusBarUtil.transparencyBar(this)
}
} }

View File

@@ -7,8 +7,15 @@ import android.widget.ImageView
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.chwl.app.R import com.chwl.app.R
import com.chwl.app.ui.utils.loadFromUrl
import com.chwl.core.vip.bean.VipInfo import com.chwl.core.vip.bean.VipInfo
import com.opensource.svgaplayer.SVGADrawable
import com.opensource.svgaplayer.SVGAImageView
import com.opensource.svgaplayer.SVGAParser
import com.opensource.svgaplayer.SVGAVideoEntity
import com.youth.banner.adapter.BannerAdapter import com.youth.banner.adapter.BannerAdapter
import java.net.MalformedURLException
import java.net.URL
class VipCenterBannerAdapter( class VipCenterBannerAdapter(
private val context: Context, private val context: Context,
@@ -25,25 +32,39 @@ class VipCenterBannerAdapter(
override fun onBindView(holder: BannerViewHolder, data: VipInfo, position: Int, size: Int) { override fun onBindView(holder: BannerViewHolder, data: VipInfo, position: Int, size: Int) {
// 加载本地背景图片 // 加载本地背景图片
when(position) { when(position) {
1->holder.imgBackground.setImageResource(R.drawable.vip_center_level_1) 0->holder.imgBackground.setImageResource(R.drawable.vip_center_level_1)
2->holder.imgBackground.setImageResource(R.drawable.vip_center_level_2) 1->holder.imgBackground.setImageResource(R.drawable.vip_center_level_2)
3->holder.imgBackground.setImageResource(R.drawable.vip_center_level_3) 2->holder.imgBackground.setImageResource(R.drawable.vip_center_level_3)
4->holder.imgBackground.setImageResource(R.drawable.vip_center_level_4) 3->holder.imgBackground.setImageResource(R.drawable.vip_center_level_4)
5->holder.imgBackground.setImageResource(R.drawable.vip_center_level_5) 4->holder.imgBackground.setImageResource(R.drawable.vip_center_level_5)
6->holder.imgBackground.setImageResource(R.drawable.vip_center_level_6) 5->holder.imgBackground.setImageResource(R.drawable.vip_center_level_6)
7->holder.imgBackground.setImageResource(R.drawable.vip_center_level_7) 6->holder.imgBackground.setImageResource(R.drawable.vip_center_level_7)
8->holder.imgBackground.setImageResource(R.drawable.vip_center_level_8) 7->holder.imgBackground.setImageResource(R.drawable.vip_center_level_8)
9->holder.imgBackground.setImageResource(R.drawable.vip_center_level_9) 8->holder.imgBackground.setImageResource(R.drawable.vip_center_level_9)
} }
// 加载网络图片 holder.svgaImage.loadFromUrl(data.vipLogo)
Glide.with(context)
.load(data.vipIcon) // data 是图片的 URL
.into(holder.imgForeground)
} }
inner class BannerViewHolder(view: View) : RecyclerView.ViewHolder(view) { inner class BannerViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val imgBackground: ImageView = view.findViewById(R.id.img_background) val imgBackground: ImageView = view.findViewById(R.id.img_background)
val imgForeground: ImageView = view.findViewById(R.id.img_foreground) val svgaImage: SVGAImageView = view.findViewById(R.id.iv_vip_icon)
}
private fun loadSVGA(svgaImageView: SVGAImageView, svgaUrl: String) {
try {
SVGAParser.shareParser()
.decodeFromURL(URL(svgaUrl), object : SVGAParser.ParseCompletion {
override fun onComplete(videoItem: SVGAVideoEntity) {
val drawable = SVGADrawable(videoItem)
svgaImageView.setImageDrawable(drawable)
svgaImageView.startAnimation()
}
override fun onError() {
}
})
} catch (e: MalformedURLException) {
}
} }
} }

View File

@@ -1,4 +1,5 @@
package com.chwl.app.vip.adapter package com.chwl.app.vip.adapter
import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
@@ -9,11 +10,20 @@ import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.chwl.app.R import com.chwl.app.R
import com.chwl.core.vip.bean.VipAuthInfo import com.chwl.core.vip.bean.VipAuthInfo
import com.chwl.core.vip.bean.VipInfo
interface OnItemClickListener {
fun onItemClick(position: Int)
}
class VipCenterIdentificationsAdapter( class VipCenterIdentificationsAdapter(
private val context: Context, private val context: Context,
private val items: List<VipAuthInfo> private val items: List<VipAuthInfo>,
private val listener: OnItemClickListener
) : RecyclerView.Adapter<VipCenterIdentificationsAdapter.ItemViewHolder>() { ) : RecyclerView.Adapter<VipCenterIdentificationsAdapter.ItemViewHolder>() {
private var vipInfo: VipInfo? = null
override fun onCreateViewHolder( override fun onCreateViewHolder(
parent: ViewGroup, parent: ViewGroup,
viewType: Int viewType: Int
@@ -35,10 +45,27 @@ class VipCenterIdentificationsAdapter(
// 设置标题 // 设置标题
holder.titleTextView.text = item.authName holder.titleTextView.text = item.authName
holder.itemView.setOnClickListener {
listener.onItemClick(position)
}
} }
override fun getItemCount(): Int { override fun getItemCount(): Int {
return items.size return vipInfo?.let {
when (it.vipLevel) {
1, 2 -> 3
3 -> 4
else -> 6
}
} ?: 0 // items.size
}
@SuppressLint("NotifyDataSetChanged")
fun setVipInfo(vipInfo: VipInfo?) {
this.vipInfo = vipInfo
// TODO过滤 items 的内容,显示指定的 vip 权益
this.notifyDataSetChanged()
} }
inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) {

View File

@@ -6,7 +6,8 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="#150c00" android:background="#150c00"
android:orientation="vertical"> android:orientation="vertical"
android:fitsSystemWindows="true">
<View <View
android:id="@+id/view_top" android:id="@+id/view_top"
@@ -111,9 +112,7 @@
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view" android:id="@+id/recycler_view"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="match_parent"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:orientation="vertical" android:orientation="vertical"
tools:listitem="@layout/vip_center_idnetifications_layout" tools:listitem="@layout/vip_center_idnetifications_layout"
tools:itemCount="2" /> tools:itemCount="2" />

View File

@@ -1,12 +1,13 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"> xmlns:app="http://schemas.android.com/apk/res-auto">
<FrameLayout <FrameLayout
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="match_parent"
android:layout_weight="1" android:layout_weight="1"
android:gravity="start|center_vertical" android:gravity="start|center_vertical"
android:orientation="horizontal" android:orientation="horizontal"
@@ -26,15 +27,13 @@
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="320:136" app:layout_constraintDimensionRatio="320:136"
android:src="@drawable/vip_center_level_1" /> android:src="@drawable/vip_center_level_1" />
<!-- 网络图片 --> <com.opensource.svgaplayer.SVGAImageView
<ImageView android:id="@+id/iv_vip_icon"
android:id="@+id/img_foreground"
android:layout_width="@dimen/dp_130" android:layout_width="@dimen/dp_130"
android:layout_height="@dimen/dp_130" android:layout_height="@dimen/dp_130"
android:layout_gravity="end|bottom" android:layout_gravity="end|bottom"
android:layout_marginEnd="13dp" android:layout_marginEnd="0dp"
android:layout_marginBottom="25dp" android:layout_marginBottom="25dp" />
android:src="@drawable/vip_center_purchase_button_bg" />
</FrameLayout> </FrameLayout>
<TextView <TextView
android:id="@+id/due_date_textview" android:id="@+id/due_date_textview"

View File

@@ -1,16 +1,18 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="wrap_content" xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
app:layout_constraintDimensionRatio="166:120"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"> android:layout_margin="8dp">
<!-- 背景图片 --> <!-- 背景图片 -->
<ImageView <ImageView
android:id="@+id/item_background" android:id="@+id/item_background"
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="@dimen/dp_120"
android:src="@drawable/vip_center_identification_card" android:src="@drawable/vip_center_identification_card"
android:scaleType="fitCenter" android:scaleType="fitCenter"
app:layout_constraintDimensionRatio="166:120" app:layout_constraintDimensionRatio="166:120"
@@ -19,16 +21,19 @@
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/> app:layout_constraintBottom_toBottomOf="parent"/>
<!-- 内容图片 -->
<ImageView <ImageView
android:id="@+id/item_image" android:id="@+id/item_image"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="0dp" android:layout_height="0dp"
android:scaleType="fitCenter" android:scaleType="fitCenter"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintDimensionRatio="164:90"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="@id/item_background"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintEnd_toEndOf="@id/item_background"
app:layout_constraintTop_toTopOf="@id/item_background"
app:layout_constraintBottom_toTopOf="@+id/item_title" /> app:layout_constraintBottom_toTopOf="@+id/item_title" />
<!-- 标题 -->
<TextView <TextView
android:id="@+id/item_title" android:id="@+id/item_title"
android:layout_width="0dp" android:layout_width="0dp"
@@ -41,9 +46,9 @@
android:textSize="13sp" android:textSize="13sp"
android:gravity="center" android:gravity="center"
tools:text="1234567" tools:text="1234567"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="@id/item_background"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="@id/item_background"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="@id/item_background"
app:layout_constraintTop_toBottomOf="@id/item_image" /> app:layout_constraintTop_toBottomOf="@id/item_image" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>