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.utils.RVDelegate
import com.chwl.app.ui.webview.CommonWebViewActivity
import com.chwl.app.vip.adapter.OnItemClickListener
import com.chwl.app.vip.adapter.VipAuthAdapter
import com.chwl.app.vip.adapter.VipCenterBannerAdapter
import com.chwl.app.vip.adapter.VipCenterIdentificationsAdapter
@@ -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.IProductDetails
import com.example.module_base.support.billing.IPurchase
import com.netease.nim.uikit.StatusBarUtil
import com.youth.banner.Banner
import com.youth.banner.adapter.BannerImageAdapter
import com.youth.banner.holder.BannerImageHolder
@@ -50,10 +52,11 @@ import com.youth.banner.transformer.DepthPageTransformer
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.greenrobot.eventbus.EventBus
import com.youth.banner.listener.OnPageChangeListener
class VipCenterActivity : BaseViewBindingActivity<ActivityVipCenterBinding>(),
VipMagicIndicatorAdapter.OnItemSelectListener, IBillingService.Listener {
VipMagicIndicatorAdapter.OnItemSelectListener, OnItemClickListener, IBillingService.Listener {
private val authAdapter = VipAuthAdapter() // 用户权限
private val vipViewModel: VipViewModel by viewModels()
@@ -66,7 +69,7 @@ class VipCenterActivity : BaseViewBindingActivity<ActivityVipCenterBinding>(),
private lateinit var recyclerView: RecyclerView
private lateinit var vipIdentificationsAdapter: VipCenterIdentificationsAdapter
// protected var banner: Banner? = null
private var currentIndex = 0
companion object {
@@ -88,10 +91,6 @@ class VipCenterActivity : BaseViewBindingActivity<ActivityVipCenterBinding>(),
initView()
initObserve()
handleAuthAdapter()
handleViewModel()
handleBinding()
rvDelegate = RVDelegate.Builder<VipAuthInfo>()
.setLayoutManager(GridLayoutManager(this, 3))
.setRecyclerView(binding.recyclerViewBottom)
@@ -110,6 +109,10 @@ class VipCenterActivity : BaseViewBindingActivity<ActivityVipCenterBinding>(),
}
}
handleAuthAdapter()
handleViewModel()
handleBinding()
requestChargeList{
loadChargeList(it)
}
@@ -117,17 +120,30 @@ class VipCenterActivity : BaseViewBindingActivity<ActivityVipCenterBinding>(),
private fun initView() {
banner = findViewById(R.id.banner_view)
banner.isAutoLoop(false)
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.layoutManager = GridLayoutManager(this, 2)
// val identificationTitle = findViewById<TextView>(R.id.center_title)
// identificationTitle.text = R.string.vip_center_2.toString()
//
// val exclusivePrivilegesTitle = findViewById<TextView>(R.id.center_title_2)
// exclusivePrivilegesTitle.text = R.string.vip_center_4.toString()
val identificationTitle = findViewById<TextView>(R.id.center_title)
identificationTitle.text = R.string.vip_center_2.toString()
val exclusivePrivilegesTitle = findViewById<TextView>(R.id.center_title_2)
exclusivePrivilegesTitle.text = R.string.vip_center_4.toString()
}
override fun initWhiteTitleBar(title: String?) {
@@ -182,48 +198,31 @@ class VipCenterActivity : BaseViewBindingActivity<ActivityVipCenterBinding>(),
// ArrayList[VipAuthInfo] // 全部特权列表
authAdapter.setNewData(it)
it?.let {
vipIdentificationsAdapter = VipCenterIdentificationsAdapter(this, it)
vipIdentificationsAdapter = VipCenterIdentificationsAdapter(this, it, this)
recyclerView.adapter = vipIdentificationsAdapter
}
}
vipViewModel.pageLiveData.observe(this) {
it?.let { // 当前显示的 index
// binding.magicIndicator.onPageSelected(it)
// TODO 处理轮播组件 index 更新
currentIndex = it
handleIdentificationAreaContent(it)
}
}
vipViewModel.vipInfosLiveData.observe(this) {
it?.let { // ArrayList[VipInfo] 每个等级的 VIP 内容
// initTitleTab(it)
// TODO 初始化轮播组件
val adapter = VipCenterBannerAdapter(this, it)
banner.setAdapter(adapter)
// 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)
banner.setAdapter(adapter, false)
handleIdentificationAreaContent(0)
}
}
vipViewModel.myVipInfoLiveData.observe(this) {
it?.let {
//TODO 处理有 VIP 的情况
//TODO 处理有 VIP 的情况banner 要跳转到对应 index
// bannerView.visibility = View.VISIBLE
// bannerView.post {
// binding.bannerView.setPageMargin(UIUtil.dip2px(mContext, 8.0))
@@ -242,13 +241,37 @@ class VipCenterActivity : BaseViewBindingActivity<ActivityVipCenterBinding>(),
vipViewModel.currVipInfoLiveData.observe(this) {
it?.let { // VipInfo
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 {
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")
private fun requestChargeList(call: (List<ChargeBean>) -> Unit) {
PayModel.get().vipList
@@ -400,4 +423,10 @@ class VipCenterActivity : BaseViewBindingActivity<ActivityVipCenterBinding>(),
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 com.bumptech.glide.Glide
import com.chwl.app.R
import com.chwl.app.ui.utils.loadFromUrl
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 java.net.MalformedURLException
import java.net.URL
class VipCenterBannerAdapter(
private val context: Context,
@@ -25,25 +32,39 @@ class VipCenterBannerAdapter(
override fun onBindView(holder: BannerViewHolder, data: VipInfo, position: Int, size: Int) {
// 加载本地背景图片
when(position) {
1->holder.imgBackground.setImageResource(R.drawable.vip_center_level_1)
2->holder.imgBackground.setImageResource(R.drawable.vip_center_level_2)
3->holder.imgBackground.setImageResource(R.drawable.vip_center_level_3)
4->holder.imgBackground.setImageResource(R.drawable.vip_center_level_4)
5->holder.imgBackground.setImageResource(R.drawable.vip_center_level_5)
6->holder.imgBackground.setImageResource(R.drawable.vip_center_level_6)
7->holder.imgBackground.setImageResource(R.drawable.vip_center_level_7)
8->holder.imgBackground.setImageResource(R.drawable.vip_center_level_8)
9->holder.imgBackground.setImageResource(R.drawable.vip_center_level_9)
0->holder.imgBackground.setImageResource(R.drawable.vip_center_level_1)
1->holder.imgBackground.setImageResource(R.drawable.vip_center_level_2)
2->holder.imgBackground.setImageResource(R.drawable.vip_center_level_3)
3->holder.imgBackground.setImageResource(R.drawable.vip_center_level_4)
4->holder.imgBackground.setImageResource(R.drawable.vip_center_level_5)
5->holder.imgBackground.setImageResource(R.drawable.vip_center_level_6)
6->holder.imgBackground.setImageResource(R.drawable.vip_center_level_7)
7->holder.imgBackground.setImageResource(R.drawable.vip_center_level_8)
8->holder.imgBackground.setImageResource(R.drawable.vip_center_level_9)
}
// 加载网络图片
Glide.with(context)
.load(data.vipIcon) // data 是图片的 URL
.into(holder.imgForeground)
holder.svgaImage.loadFromUrl(data.vipLogo)
}
inner class BannerViewHolder(view: View) : RecyclerView.ViewHolder(view) {
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
import android.annotation.SuppressLint
import android.content.Context
import android.view.LayoutInflater
import android.view.View
@@ -9,11 +10,20 @@ import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.chwl.app.R
import com.chwl.core.vip.bean.VipAuthInfo
import com.chwl.core.vip.bean.VipInfo
interface OnItemClickListener {
fun onItemClick(position: Int)
}
class VipCenterIdentificationsAdapter(
private val context: Context,
private val items: List<VipAuthInfo>
private val items: List<VipAuthInfo>,
private val listener: OnItemClickListener
) : RecyclerView.Adapter<VipCenterIdentificationsAdapter.ItemViewHolder>() {
private var vipInfo: VipInfo? = null
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
@@ -35,10 +45,27 @@ class VipCenterIdentificationsAdapter(
// 设置标题
holder.titleTextView.text = item.authName
holder.itemView.setOnClickListener {
listener.onItemClick(position)
}
}
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) {

View File

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

View File

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

View File

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