feat: 更新 VIP 页面 UI & 功能

This commit is contained in:
eggmanQQQ
2024-08-23 19:29:38 +08:00
parent f58701a2d6
commit cb4dac8e81
32 changed files with 900 additions and 9 deletions

View File

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

View File

@@ -734,7 +734,10 @@
android:screenOrientation="portrait" /> android:screenOrientation="portrait" />
<activity <activity
android:name=".vip.VipMainActivity" android:name=".vip.VipMainActivity"
android:screenOrientation="portrait" /> <!-- 隐私设置 --> android:screenOrientation="portrait" />
<activity
android:name=".vip.VipCenterActivity"
android:screenOrientation="portrait" />
<activity <activity
android:name=".vip.VipSettingActivity" android:name=".vip.VipSettingActivity"
android:screenOrientation="portrait" /> <!-- 通知提醒设置 --> android:screenOrientation="portrait" /> <!-- 通知提醒设置 -->

View File

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

View File

@@ -0,0 +1,403 @@
package com.chwl.app.vip
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.util.Log
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.TextView
import androidx.activity.viewModels
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.view.isVisible
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.bitmap.RoundedCorners
import com.bumptech.glide.request.RequestOptions
import com.chwl.app.R
import com.chwl.app.base.BaseViewBindingActivity
import com.chwl.app.base.TitleBar
import com.chwl.app.common.EmptyViewHelper
import com.chwl.app.databinding.ActivityVipCenterBinding
import com.chwl.app.ui.pay.ChargeActivity
import com.chwl.app.ui.utils.RVDelegate
import com.chwl.app.ui.webview.CommonWebViewActivity
import com.chwl.app.vip.adapter.VipAuthAdapter
import com.chwl.app.vip.adapter.VipCenterBannerAdapter
import com.chwl.app.vip.adapter.VipCenterIdentificationsAdapter
import com.chwl.app.vip.adapter.VipMagicIndicatorAdapter
import com.chwl.app.vip.adapter.VipRebateAdapter
import com.chwl.app.vip.dialog.SelectPayTypeDialog
import com.chwl.app.vip.dialog.VipAuthDetailsDialog
import com.chwl.core.UriProvider
import com.chwl.core.pay.PayModel
import com.chwl.core.pay.bean.ChargeBean
import com.chwl.core.utils.extension.toast
import com.chwl.core.vip.bean.VipAuthInfo
import com.chwl.core.vip.bean.VipInfo
import com.example.module_base.support.billing.IBillingService
import com.example.module_base.support.billing.IProductDetails
import com.example.module_base.support.billing.IPurchase
import com.youth.banner.Banner
import com.youth.banner.adapter.BannerImageAdapter
import com.youth.banner.holder.BannerImageHolder
import com.youth.banner.indicator.CircleIndicator
import com.youth.banner.transformer.AlphaPageTransformer
import com.youth.banner.transformer.DepthPageTransformer
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.greenrobot.eventbus.EventBus
class VipCenterActivity : BaseViewBindingActivity<ActivityVipCenterBinding>(),
VipMagicIndicatorAdapter.OnItemSelectListener, IBillingService.Listener {
private val authAdapter = VipAuthAdapter() // 用户权限
private val vipViewModel: VipViewModel by viewModels()
private var chargeList: List<ChargeBean>? = null
private val rebateAdapter = VipRebateAdapter()
private var currentChargeInfo: ChargeBean? = null
private lateinit var rvDelegate: RVDelegate<VipAuthInfo>
private lateinit var banner:Banner<VipInfo, VipCenterBannerAdapter>
private lateinit var recyclerView: RecyclerView
private lateinit var vipIdentificationsAdapter: VipCenterIdentificationsAdapter
// protected var banner: Banner? = null
companion object {
@JvmStatic
fun start(context: Context) {
val starter = Intent(context, VipCenterActivity::class.java)
context.startActivity(starter)
}
private const val BIND_CODE_GOLD = 200
private const val TAG = "VipCenterActivity"
}
@SuppressLint("SetTextI18N")
override fun init() {
EventBus.getDefault().register(this)
initWhiteTitleBar(getString(R.string.vip_center))
initView()
initObserve()
handleAuthAdapter()
handleViewModel()
handleBinding()
rvDelegate = RVDelegate.Builder<VipAuthInfo>()
.setLayoutManager(GridLayoutManager(this, 3))
.setRecyclerView(binding.recyclerViewBottom)
.setEmptyView(
EmptyViewHelper.createEmptyTextView(
context,
getString(R.string.me_no_search_results)
)
)
.setAdapter(authAdapter)
.build()
authAdapter.setOnItemClickListener { _, _, position ->
authAdapter.getItem(position)?.let {
VipAuthDetailsDialog.newInstance(it.descPic, it.authName, it.authIntro).show(this)
}
}
requestChargeList{
loadChargeList(it)
}
}
private fun initView() {
banner = findViewById(R.id.banner_view)
banner.isAutoLoop(false)
banner.setBannerGalleryEffect(25, 25,25)
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()
}
override fun initWhiteTitleBar(title: String?) {
mTitleBar = findViewById(R.id.title_bar)
if (mTitleBar != null) {
mTitleBar.setTitle(title)
mTitleBar.setImmersive(false)
mTitleBar.setTitleColor(resources.getColor(R.color.color_FFE3AF))
mTitleBar.setLeftImageResource(R.drawable.vip_center_back_button)
mTitleBar.setBackgroundResource(R.color.transparent)
mTitleBar.setLeftClickListener { onLeftClickListener() }
mTitleBar.addAction(object : TitleBar.ImageAction(R.drawable.vip_center_help_button) {
override fun performAction(view: View) {
CommonWebViewActivity.start(
this@VipCenterActivity,
UriProvider.getVipHelpUrl())
}
})
}
}
private fun handleAuthAdapter() {
authAdapter.setOnItemClickListener { _, _, position ->
authAdapter.getItem(position)?.let {
VipAuthDetailsDialog.newInstance(it.descPic, it.authName, it.authIntro).show(this)
}
}
}
private fun handleBinding() {
binding.layoutOpenVip.setOnClickListener {
checkBuyVip {
buyVip()
}
}
binding.recyclerViewBottom.isNestedScrollingEnabled = false
}
private fun handleViewModel() {
vipViewModel.getVipPageInfo()
vipViewModel.loadingLiveData.observe(this) {
if (it == true) {
dialogManager.showProgressDialog(this)
} else {
dialogManager.dismissDialog()
}
}
vipViewModel.authInfosLiveData.observe(this) {
// ArrayList[VipAuthInfo] // 全部特权列表
authAdapter.setNewData(it)
it?.let {
vipIdentificationsAdapter = VipCenterIdentificationsAdapter(this, it)
recyclerView.adapter = vipIdentificationsAdapter
}
}
vipViewModel.pageLiveData.observe(this) {
it?.let { // 当前显示的 index
// binding.magicIndicator.onPageSelected(it)
// TODO 处理轮播组件 index 更新
}
}
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)
}
}
vipViewModel.myVipInfoLiveData.observe(this) {
it?.let {
//TODO 处理有 VIP 的情况
// bannerView.visibility = View.VISIBLE
// bannerView.post {
// binding.bannerView.setPageMargin(UIUtil.dip2px(mContext, 8.0))
// .setScrollDuration(800)
// .setOnPageClickListener { _: View?, position: Int ->
// }
// .create(it)
// }
} ?: run {
// binding.layoutLevelInfo.isVisible = false
// binding.layoutLevelProgress.isVisible = false
binding.slAuth.isVisible = true
// binding.tvNotOpen.text = getString(R.string.me_no_aristocracy_yet)
}
}
vipViewModel.currVipInfoLiveData.observe(this) {
it?.let { // VipInfo
// TODO 根据当前显示的 VIP 信息更新 UI
} ?: run {
getString(R.string.me_failed_to_get_aristocrat_data).toast()
}
}
}
@SuppressLint("CheckResult")
private fun requestChargeList(call: (List<ChargeBean>) -> Unit) {
PayModel.get().vipList
.compose(bindToLifecycle())
.subscribe(
{
call.invoke(it)
}, {
it.printStackTrace()
}
)
}
private fun initObserve(){
lifecycleScope.launch(Dispatchers.Main) {
vipViewModel.getVipRebateSuccessFlow.collect {
rebateAdapter.notifyItemRangeChanged(0, rebateAdapter.itemCount, true)
}
}
}
private fun loadChargeList(list: List<ChargeBean>) {
this.chargeList = list
refreshOpenVipState()
}
private fun checkBuyVip(block: () -> Unit) {
val myVipInfo = vipViewModel.myVipInfoLiveData.value
val currentVipInfo = vipViewModel.currVipInfoLiveData.value
if (currentVipInfo != null && myVipInfo != null && currentVipInfo.vipLevel > myVipInfo.vipLevel) {
val message = context.getString(R.string.vip_buy_tips).format(
myVipInfo.vipName,currentVipInfo.vipName
)
dialogManager.showOkCancelDialog(message,
context.getString(R.string.miniworld_activity_mwteamroommessageact_07),
context.getString(R.string.miniworld_activity_mwteamroommessageact_08),
true
) { block.invoke() }
} else {
block.invoke()
}
}
private fun buyVip() {
val googleUnavailable = ((currentChargeInfo?.productDetails?.getOneTimePurchaseOfferDetails()
?.getPriceAmountMicros()
?: "0") == "0")
var text =
currentChargeInfo?.productDetails?.getOneTimePurchaseOfferDetails()?.getFormattedPrice()
if (text.isNullOrEmpty()) {
text = ((currentChargeInfo?.money ?: 0.0) * 1000).toInt().toString()
}
SelectPayTypeDialog.newInstance(
text,
!googleUnavailable,
currentChargeInfo?.getMoney() ?: 0.0
)
.apply {
setOnDiamondChargeClick {
vipViewModel.openVipWithDiamond(
currentChargeInfo?.getProdDesc()?.toIntOrNull() ?: -1
)
}
setOnGoogleChargeClick {
if (googleUnavailable) {
toast(getString(R.string.Recharge_failure))
return@setOnGoogleChargeClick
}
currentChargeInfo?.let { charge ->
buyProduct(charge.productDetails)
}
}
setOnChargeClick {
ChargeActivity.start(this@VipCenterActivity)
}
}
.show(context)
}
/*购买商品*/
@SuppressLint("CheckResult")
fun buyProduct(productDetails: IProductDetails?) {
if (productDetails != null) {
Log.d(VipCenterActivity.TAG, "BuyProduct:" + productDetails.getProductId())
// PayModel.get().placeOrder(productDetails.getProductId())
// .compose(bindToLifecycle())
// .subscribe(
// { recordId: PayRecordId ->
// billingManager?.initiatePurchaseFlow(
// productDetails,
// recordId.recordId
// )
// }
// ) { throwable: Throwable ->
// SingleToastUtil.showToast(
// throwable.message
// )
// }
} else {
Log.w(VipCenterActivity.TAG, "skuDetails ==null")
}
}
private fun refreshOpenVipState() {
val currentVipInfo = vipViewModel.currVipInfoLiveData.value
val myVipInfo = vipViewModel.myVipInfoLiveData.value
if (currentVipInfo != null) {
currentChargeInfo = chargeList?.firstOrNull {
it.prodDesc?.toIntOrNull() == currentVipInfo.vipLevel
}
if (currentChargeInfo != null && (myVipInfo == null || myVipInfo.vipLevel < currentVipInfo.vipLevel)) {
"${currentChargeInfo?.getMoney()} ${
getString(R.string.vip_buy_format).format(
currentVipInfo.vipName
)
}".also { binding.tvOpenVip.text = it }
binding.layoutOpenVip.isVisible = true
} else {
binding.layoutOpenVip.isVisible = false
}
} else {
currentChargeInfo = null
// binding.layoutOpenVip.isVisible = false
}
// if (binding.layoutOpenVip.isVisible && binding.layoutLevelProgress.isVisible) {
// binding.layoutBottomPanel.setBackgroundDrawable(binding.layoutLevelProgress.background)
// } else {
// binding.layoutBottomPanel.setBackgroundDrawable(null)
// }
}
override fun onItemSelect(position: Int, view: TextView?) {
TODO("Not yet implemented")
}
override fun onBillingClientSetupFinished() {
TODO("Not yet implemented")
}
override fun onPurchasesUpdated(purchases: List<IPurchase>) {
TODO("Not yet implemented")
}
override fun onConsumeFinished(token: String?, result: Int) {
TODO("Not yet implemented")
}
override fun onFailedHandle(result: Int) {
TODO("Not yet implemented")
}
}

View File

@@ -546,12 +546,11 @@ class VipMainActivity : BaseViewBindingActivity<ActivityVipMainBinding>(),
it.prodDesc?.toIntOrNull() == currentVipInfo.vipLevel it.prodDesc?.toIntOrNull() == currentVipInfo.vipLevel
} }
if (currentChargeInfo != null && (myVipInfo == null || myVipInfo.vipLevel < currentVipInfo.vipLevel)) { if (currentChargeInfo != null && (myVipInfo == null || myVipInfo.vipLevel < currentVipInfo.vipLevel)) {
binding.tvOpenVip.text = "${currentChargeInfo?.getMoney()} ${
"${currentChargeInfo?.getMoney()} ${ getString(R.string.vip_buy_format).format(
getString(R.string.vip_buy_format).format( currentVipInfo.vipName
currentVipInfo.vipName )
) }".also { binding.tvOpenVip.text = it }
}"
binding.layoutOpenVip.isVisible = true binding.layoutOpenVip.isVisible = true
} else { } else {
binding.layoutOpenVip.isVisible = false binding.layoutOpenVip.isVisible = false

View File

@@ -0,0 +1,49 @@
package com.chwl.app.vip.adapter
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.chwl.app.R
import com.chwl.core.vip.bean.VipInfo
import com.youth.banner.adapter.BannerAdapter
class VipCenterBannerAdapter(
private val context: Context,
private val vipInfos: List<VipInfo>
) : BannerAdapter<VipInfo, VipCenterBannerAdapter.BannerViewHolder>(vipInfos) {
override fun onCreateHolder(parent: ViewGroup, viewType: Int): BannerViewHolder {
val view = LayoutInflater.from(context).inflate(
R.layout.banner_vip_center_custom,
parent,
false)
return BannerViewHolder(view)
}
override fun onBindView(holder: BannerViewHolder, data: VipInfo, position: Int, size: Int) {
// 加载本地背景图片
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)
}
// 加载网络图片
Glide.with(context)
.load(data.vipIcon) // data 是图片的 URL
.into(holder.imgForeground)
}
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)
}
}

View File

@@ -0,0 +1,50 @@
package com.chwl.app.vip.adapter
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.chwl.app.R
import com.chwl.core.vip.bean.VipAuthInfo
class VipCenterIdentificationsAdapter(
private val context: Context,
private val items: List<VipAuthInfo>
) : RecyclerView.Adapter<VipCenterIdentificationsAdapter.ItemViewHolder>() {
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): VipCenterIdentificationsAdapter.ItemViewHolder {
val view = LayoutInflater.from(context).inflate(R.layout.vip_center_idnetifications_layout, parent, false)
return ItemViewHolder(view)
}
override fun onBindViewHolder(
holder: VipCenterIdentificationsAdapter.ItemViewHolder,
position: Int
) {
val item = items[position]
// 加载内容图片
Glide.with(context)
.load(item.authIcon)
.into(holder.contentImageView)
// 设置标题
holder.titleTextView.text = item.authName
}
override fun getItemCount(): Int {
return items.size
}
inner class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) {
// val backgroundImageView: ImageView = view.findViewById(R.id.background_image)
val contentImageView: ImageView = view.findViewById(R.id.item_image)
val titleTextView: TextView = view.findViewById(R.id.item_title)
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 642 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

View File

@@ -0,0 +1,255 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
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="#150c00"
android:orientation="vertical">
<View
android:id="@+id/view_top"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="@drawable/vip_center_background"
app:layout_constraintDimensionRatio="750:820"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.chwl.app.base.TitleBar
android:id="@+id/title_bar"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.youth.banner.Banner
android:id="@+id/banner_view"
android:layout_width="match_parent"
android:layout_height="150dp"
android:layout_marginTop="20dp"
app:layout_constraintTop_toBottomOf="@id/title_bar"
android:visibility="visible"
app:bvp_auto_play="false"
app:bvp_can_loop="false"
app:bvp_indicator_visibility="gone"
app:bvp_page_style="multi_page_scale"
app:layout_constraintDimensionRatio="351:80"
app:layout_goneMarginTop="@dimen/dp_16"
tools:visibility="visible" />
<androidx.core.widget.NestedScrollView
android:id="@+id/sl_auth"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="20dp"
android:layout_marginBottom="@dimen/dp_80"
android:fillViewport="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/banner_view">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_gravity="center_horizontal">
<!-- 这部分是你的标题和左右两侧图片 -->
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:layout_gravity="center">
<!-- 左侧图片 -->
<ImageView
android:id="@+id/left_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="18dp"
android:src="@drawable/vip_center_label_decorate"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
<!-- 右侧图片 -->
<ImageView
android:id="@+id/right_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="18dp"
android:scaleX="-1"
android:src="@drawable/vip_center_label_decorate"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
<!-- 中央标题 -->
<TextView
android:id="@+id/center_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="Identification"
android:text="@string/vip_center_3"
android:textColor="@android:color/white"
android:textSize="16sp"
android:textStyle="bold"
android:layout_marginStart="@dimen/dp_8"
android:layout_marginEnd="@dimen/dp_8"
app:layout_constraintStart_toEndOf="@id/left_image"
app:layout_constraintEnd_toStartOf="@id/right_image"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<!-- 新增的 RecyclerView用于显示 API 数据 -->
<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:orientation="vertical"
tools:listitem="@layout/vip_center_idnetifications_layout"
tools:itemCount="2" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/vip_center_title_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:layout_gravity="center">
<!-- 左侧图片 -->
<ImageView
android:id="@+id/left_image_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="18dp"
android:src="@drawable/vip_center_label_decorate"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
<!-- 右侧图片 -->
<ImageView
android:id="@+id/right_image_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="18dp"
android:scaleX="-1"
android:src="@drawable/vip_center_label_decorate"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
<!-- 中央标题 -->
<TextView
android:id="@+id/center_title_2"
android:maxLines="2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="Exclusive Privileges\n(3/13)"
android:text="@string/vip_center_4"
android:textColor="@android:color/white"
android:textSize="16sp"
android:textStyle="bold"
android:gravity="center"
android:layout_marginStart="@dimen/dp_8"
android:layout_marginEnd="@dimen/dp_8"
app:layout_constraintStart_toEndOf="@id/left_image_2"
app:layout_constraintEnd_toStartOf="@id/right_image_2"
app:layout_constraintTop_toTopOf="parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view_bottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="25dp"
android:layout_marginBottom="165dp"
android:overScrollMode="never"
android:scrollbars="none"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/vip_center_title_2"
app:layout_constraintVertical_bias="0" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
<LinearLayout
android:id="@+id/layout_bottom_panel"
android:layout_width="0dp"
android:layout_height="53dp"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="26dp"
android:orientation="horizontal"
android:gravity="center_vertical"
android:background="@drawable/vip_center_purchase_bg"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:visibility="visible"
tools:visibility="visible">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginStart="16dp"
android:gravity="start|center_vertical"
android:orientation="vertical"
android:visibility="visible"
tools:visibility="visible">
<TextView
android:id="@+id/tv_open_vip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawablePadding="4dp"
android:gravity="start|center_vertical"
android:textColor="@color/color_FFE3AF"
android:textSize="@dimen/sp_13"
android:textStyle="bold"
app:drawableLeftCompat="@drawable/vip_center_purchase_coin"
tools:text="19.99/30Days"
android:text="@string/vip_center_5"/>
<TextView
android:id="@+id/tv_additional_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="5dp"
android:gravity="start|center_vertical"
android:textColor="@color/color_FFE3AF"
android:textSize="@dimen/sp_11"
tools:text="Date to Expires"
android:text="@string/vip_center_6"/>
</LinearLayout>
<!-- 右侧按钮 -->
<Button
android:id="@+id/layout_open_vip"
android:layout_width="147dp"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_marginEnd="4dp"
android:layout_marginBottom="4dp"
android:background="@drawable/vip_center_purchase_button_bg"
android:textColor="@color/color_633000"
android:textSize="@dimen/sp_16"
android:text="@string/vip_center_7"
tools:text="Renew" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<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"
xmlns:app="http://schemas.android.com/apk/res-auto">
<FrameLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="start|center_vertical"
android:orientation="horizontal"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:visibility="visible"
tools:visibility="visible">
<!-- 本地背景图片 -->
<ImageView
android:id="@+id/img_background"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="320:136"
android:src="@drawable/vip_center_level_1" />
<!-- 网络图片 -->
<ImageView
android:id="@+id/img_foreground"
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" />
</FrameLayout>
<TextView
android:id="@+id/due_date_textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/vip_center_2"
android:textColor="@android:color/white"
android:textSize="14sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginStart="18dp"
android:layout_marginBottom="26dp" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,49 @@
<?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"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_margin="8dp">
<!-- 背景图片 -->
<ImageView
android:id="@+id/item_background"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/vip_center_identification_card"
android:scaleType="fitCenter"
app:layout_constraintDimensionRatio="166:120"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
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_constraintBottom_toTopOf="@+id/item_title" />
<TextView
android:id="@+id/item_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
android:layout_marginTop="8dp"
android:textColor="@color/color_FFE3AF"
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_constraintTop_toBottomOf="@id/item_image" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -5343,4 +5343,11 @@
<string name="game_team_18">%s ساعة</string> <string name="game_team_18">%s ساعة</string>
<string name="game_team_19">تم تقديم الطلب بنجاح</string> <string name="game_team_19">تم تقديم الطلب بنجاح</string>
<string name="vip_center_1">Activate VIP</string>
<string name="vip_center_2">Due on:</string>
<string name="vip_center_3">Identification</string>
<string name="vip_center_4">Exclusive Privileges/n</string>
<string name="vip_center_5">Days</string>
<string name="vip_center_6"> Expires</string>
<string name="vip_center_7">Renew</string>
</resources> </resources>

View File

@@ -5283,4 +5283,13 @@
<string name="game_team_17">和我一起玩遊戲吧~</string> <string name="game_team_17">和我一起玩遊戲吧~</string>
<string name="game_team_18">%s小時</string> <string name="game_team_18">%s小時</string>
<string name="game_team_19">下單成功~</string> <string name="game_team_19">下單成功~</string>
<string name="vip_center_1">Activate VIP</string>
<string name="vip_center_2">Due on:</string>
<string name="vip_center_3">Identification</string>
<string name="vip_center_4">Exclusive Privileges/n</string>
<string name="vip_center_5">Days</string>
<string name="vip_center_6"> Expires</string>
<string name="vip_center_7">Renew</string>
</resources> </resources>

View File

@@ -747,4 +747,7 @@
<color name="color_002512">#002512</color> <color name="color_002512">#002512</color>
<color name="color_3FDDAC">#3FDDAC</color> <color name="color_3FDDAC">#3FDDAC</color>
<color name="color_0FCA81">#0FCA81</color> <color name="color_0FCA81">#0FCA81</color>
<color name="color_FFE3AF">#FFE3AF</color>
<color name="color_633000">#633000</color>
</resources> </resources>

View File

@@ -5323,6 +5323,14 @@ You cannot join again within 24 hours after leaving</string>
<string name="game_team_18">%s Hour</string> <string name="game_team_18">%s Hour</string>
<string name="game_team_19">successfully ordered</string> <string name="game_team_19">successfully ordered</string>
<string name="vip_center_1">Activate VIP</string>
<string name="vip_center_2">Due on:</string>
<string name="vip_center_3">Identification</string>
<string name="vip_center_4">Exclusive Privileges/n</string>
<string name="vip_center_5">Days</string>
<string name="vip_center_6"> Expires</string>
<string name="vip_center_7">Renew</string>
</resources> </resources>

View File

@@ -1,5 +1,6 @@
<?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:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"