添加优惠券逻辑(待完善)

This commit is contained in:
wangyu 2026-03-10 18:37:05 +08:00
parent b707c20cd6
commit 9a3edbf0b1
58 changed files with 2709 additions and 274 deletions

Binary file not shown.

Binary file not shown.

View File

@ -126,4 +126,28 @@ object EventConstants {
const val EXIT_APP = "client.exit.app" //退出APP
const val SHOW_DIALOG = "client.show.dialog" //弹出退出app的弹框
const val COUPON_ANIMATION_PLAY = "client.coupon.animation.play" //播放优惠券动画
const val COUPON_ANIMATION_CLOSE = "client.coupon.animation.close" //关闭优惠券动画
const val COUPON_RECEIVE = "client.coupon.receive" //领取优惠券
const val COUPON_REDEEM_ENABLE = "client.coupon.redeem.enable" //优惠券兑换按钮点击
const val COUPON_REDEEM_INFO = "client.coupon.redeem.info" //优惠券兑换详情
const val COUPON_REDEEM = "client.coupon.redeem" //优惠券兑换
const val COUPON_REDEEM_SUCCESS = "client.coupon.redeem.success" //优惠券兑换成功
const val COUPON_REDEEM_SUCCESS_CONFIRM = "client.coupon.redeem.success.confirm" //优惠券兑换成功
const val COUPON_VIEW = "client.coupon.view" //查看优惠券
const val COUPON_DIALOG_CHECK = "client.coupon.dialog.check" //切换优惠券
const val COUPON_DIALOG_CLOSE = "client.coupon.dialog.close" //关闭优惠券
const val COUPON_DIALOG_CONFIRM = "client.coupon.dialog.confirm" //确认优惠券
}

View File

@ -0,0 +1,5 @@
package com.cheng.blzb.event
import com.ylqh.cube.bean.CouponActivityEntity
class RedPacketActivityEvent(var redPacket: CouponActivityEntity, var type: Int)// 0 首页, 1 enter, 2 exit

View File

@ -1,6 +1,5 @@
package com.cheng.blzb.manager
import android.R
import android.os.Build
import android.text.TextUtils
import androidx.lifecycle.MutableLiveData
@ -358,6 +357,17 @@ object UserConfigManager {
return MMKVUtils.getString("guide_countdown_time")
}
/**
* 是否显示商品降价动效
*/
fun hideGoodsCouponAnim() {
MMKVUtils.put("show_goods_coupon", false)
}
fun isShowGoodsCouponAnim(): Boolean {
return MMKVUtils.getBoolean("show_goods_coupon", true)
}
/**
* 保存个推cid
*/

View File

@ -8,20 +8,36 @@ import android.window.OnBackInvokedDispatcher
import androidx.activity.addCallback
import androidx.core.os.BuildCompat
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import com.cheng.blzb.R
import com.cheng.blzb.bean.CouponEntity
import com.cheng.blzb.common.EventConstants
import com.cheng.blzb.event.CouponActivityEvent
import com.cheng.blzb.event.LogoutSuccessEvent
import com.cheng.blzb.event.PushMessageEvent
import com.cheng.blzb.event.RedPacketActivityEvent
import com.cheng.blzb.manager.EventReportManager
import com.cheng.blzb.manager.UserConfigManager
import com.cheng.blzb.net.ApiFactory
import com.cheng.blzb.ui.fragment.main.MainFragment
import com.example.base.common.ActivityManager
import com.example.base.common.RxBus
import com.example.base.extensions.toast
import com.example.base.ui.BaseActivity
import com.example.base.utils.ClipboardUtils
import com.example.base.utils.L
import kotlinx.coroutines.launch
class MainActivity : BaseActivity() {
companion object {
var hasCheckedEnterCouponActivity = false
var hasCheckedExitCouponActivity = false
var hasCheckedVipEnterCouponActivity = false
var hasCheckedVipReturnCouponActivity = false
var hasCheckedVipGuideReturnCouponActivity = false
}
private var lastBackClickTime = 0L
override fun getFragment(): Fragment {
@ -58,15 +74,79 @@ class MainActivity : BaseActivity() {
}
}
override fun onWindowFocusChanged(hasFocus: Boolean) {
super.onWindowFocusChanged(hasFocus)
if (hasFocus) {
checkEnterCouponActivity()
}
}
private fun checkEnterCouponActivity() {
if (hasCheckedEnterCouponActivity || UserConfigManager.userInfo?.vip == "3") {
return
} else {
lifecycleScope.launch {
try {
val response = ApiFactory.apiService.couponActivityList("cli_app_enter")
if (response.status) {
val list = response.data
if (list.isNotEmpty()) {
if (list.size == 1 && list[0].activity_type == CouponEntity.TYPE_CASH) {
RxBus.defaultInstance.post(RedPacketActivityEvent(list[0], 1))
} else {
RxBus.defaultInstance.post(CouponActivityEvent(list, 1))
}
}
}
hasCheckedEnterCouponActivity = true
} catch (e: Exception) {
hasCheckedEnterCouponActivity = true
L.d(e)
}
}
}
}
private fun checkExitCouponActivity() {
if (hasCheckedExitCouponActivity || UserConfigManager.userInfo?.vip == "3") {
exitApp()
} else {
lifecycleScope.launch {
try {
val response = ApiFactory.apiService.couponActivityList("cli_app_exit")
if (response.status) {
val list = response.data
if (list.isNotEmpty()) {
if (list.size == 1 && list[0].activity_type == CouponEntity.TYPE_CASH) {
RxBus.defaultInstance.post(RedPacketActivityEvent(list[0], 2))
} else {
RxBus.defaultInstance.post(CouponActivityEvent(list, 2))
}
} else {
exitApp()
}
} else {
exitApp()
}
hasCheckedExitCouponActivity = true
} catch (e: Exception) {
hasCheckedExitCouponActivity = true
L.d(e)
exitApp()
}
}
}
}
@SuppressLint("UnsafeOptInUsageError")
private fun backApp() {
if (BuildCompat.isAtLeastT()) {
onBackInvokedDispatcher.registerOnBackInvokedCallback(OnBackInvokedDispatcher.PRIORITY_DEFAULT) {
exitApp()
checkExitCouponActivity()
}
} else {
onBackPressedDispatcher.addCallback(this) {
exitApp()
checkExitCouponActivity()
}
}
}

View File

@ -0,0 +1,274 @@
package com.cheng.blzb.ui.dialog
import android.animation.AnimatorSet
import android.animation.ObjectAnimator
import android.animation.PropertyValuesHolder
import android.annotation.SuppressLint
import android.app.Dialog
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.os.Bundle
import android.text.TextUtils
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.animation.LinearInterpolator
import android.widget.TextView
import androidx.core.animation.addListener
import androidx.core.view.marginStart
import androidx.fragment.app.DialogFragment
import androidx.recyclerview.widget.LinearLayoutManager
import com.chad.library.adapter.base.BaseQuickAdapter
import com.chad.library.adapter.base.viewholder.BaseViewHolder
import com.cheng.blzb.R
import com.cheng.blzb.bean.CouponEntity
import com.cheng.blzb.common.Constants
import com.cheng.blzb.databinding.DialogCouponActivityBinding
import com.cheng.blzb.manager.DialogEnum
import com.example.base.extensions.onClick
import com.example.base.extensions.visible
import com.example.base.utils.DensityUtils
import com.example.base.utils.ScreenUtils
import com.example.base.utils.SpanUtils
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.ylqh.cube.bean.CouponActivityEntity
import java.text.DecimalFormat
import kotlin.math.pow
class CouponActivityDialog : DialogFragment() {
private val needOpenAnim by lazy { arguments?.getBoolean("needAnim") ?: true }
private val mAdapter by lazy { ActivityCouponAdapter() }
private var mOnBackListener: ((DialogEnum) -> Unit)? = null //回调事件
lateinit var binding: DialogCouponActivityBinding
override fun onStart() {
super.onStart()
val window = dialog?.window
val windowParams = window?.attributes
windowParams?.dimAmount = 0.7f
windowParams?.width = ScreenUtils.getWindowSize().x
windowParams?.height = ScreenUtils.getWindowSize().y
dialog?.window?.attributes = windowParams
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
dialog?.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
dialog?.setCancelable(false)
return super.onCreateView(inflater, container, savedInstanceState)
}
@SuppressLint("SetTextI18n")
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val view = layoutInflater.inflate(R.layout.dialog_coupon_activity, null)
binding = DialogCouponActivityBinding.bind(view)
binding.tvTitle.typeface = Constants.almmsht
binding.mRecyclerView.adapter = mAdapter
val listStr = arguments?.getString("list")
if (!TextUtils.isEmpty(listStr)) {
val list = Gson().fromJson<List<CouponActivityEntity>>(listStr, object : TypeToken<List<CouponActivityEntity>>() {}.type)
list.forEach { it.enableAnim = needOpenAnim }
mAdapter.setList(list)
}
binding.tvTitle.text = "${ DecimalFormat("0.##").format(mAdapter.data.sumOf { it.activity_value.toDouble() }) }元大促优惠券"
binding.ivBtn.onClick {
mOnBackListener?.invoke(DialogEnum.CLICK_OK)
dismiss()
}
binding.ivClose.onClick {
mOnBackListener?.invoke(DialogEnum.CLICK_CANCEL)
dismiss()
}
startDefaultAnim()
val dialog = Dialog(requireContext())
dialog.setContentView(view)
return dialog
}
private fun startDefaultAnim() {
val scaleX0_1Holder = PropertyValuesHolder.ofFloat("scaleX", 0f, 1f)
val scaleY0_1Holder = PropertyValuesHolder.ofFloat("scaleY", 0f, 1f)
val bg1ScaleAnim = ObjectAnimator.ofPropertyValuesHolder(binding.ivBg1, scaleX0_1Holder, scaleY0_1Holder).setDuration(1000)
val bg1RotateAnim = ObjectAnimator.ofFloat(binding.ivBg1, "rotation", 0f, 360f)
bg1RotateAnim.repeatCount = ObjectAnimator.INFINITE
bg1RotateAnim.duration = 5000
bg1RotateAnim.interpolator = LinearInterpolator()
bg1RotateAnim.addListener(onStart = {
binding.ivBg1.visible()
})
val bg2ScaleAnim = ObjectAnimator.ofPropertyValuesHolder(binding.ivBg2, scaleX0_1Holder, scaleY0_1Holder).setDuration(1000)
val bg2RotateAnim = ObjectAnimator.ofFloat(binding.ivBg2, "rotation", 0f, 360f)
bg2RotateAnim.repeatCount = ObjectAnimator.INFINITE
bg2RotateAnim.duration = 5000
bg2RotateAnim.interpolator = LinearInterpolator()
bg2RotateAnim.addListener(onStart = {
binding.ivBg2.visible()
})
val titleTransYHolder = PropertyValuesHolder.ofFloat(
"translationY",
-DensityUtils.dp2px(200f).toFloat(),
DensityUtils.dp2px(15f).toFloat(),
-DensityUtils.dp2px(15f).toFloat(),
DensityUtils.dp2px(10f).toFloat(),
-DensityUtils.dp2px(10f).toFloat(),
DensityUtils.dp2px(5f).toFloat(),
-DensityUtils.dp2px(5f).toFloat(),
0f)
val titleScaleXHolder = PropertyValuesHolder.ofFloat("scaleX", 1f, 1.2f, 1f)
val titleScaleYHolder = PropertyValuesHolder.ofFloat( "scaleY", 1f, 1.2f, 1f)
val titleTransYAnim = ObjectAnimator.ofPropertyValuesHolder(binding.tvTitle, titleTransYHolder).setDuration(1200)
titleTransYAnim.addListener(onStart = {
binding.tvTitle.visible()
})
val titleZoomAnim = ObjectAnimator.ofPropertyValuesHolder(binding.tvTitle, titleScaleXHolder, titleScaleYHolder)
titleZoomAnim.repeatCount = ObjectAnimator.INFINITE
titleZoomAnim.duration = 500
titleZoomAnim.startDelay = if (needOpenAnim) 1200 else 0
val closeTransAnim = ObjectAnimator.ofFloat(binding.ivClose, "translationX", DensityUtils.dp2px(50f).toFloat(), 0f)
closeTransAnim.duration = 800
closeTransAnim.addListener(onStart = {
binding.ivClose.visible()
})
val btnScaleXHolder = PropertyValuesHolder.ofFloat("scaleX", 1f, 0.8f, 1f)
val btnScaleYHolder = PropertyValuesHolder.ofFloat("scaleY", 1f, 0.8f, 1f)
val btnScaleAnim = ObjectAnimator.ofPropertyValuesHolder(binding.ivBtn, scaleX0_1Holder, scaleY0_1Holder)
btnScaleAnim.duration = 800
btnScaleAnim.addListener(onStart = {
binding.ivBtn.visible()
})
val btnZoomAnim = ObjectAnimator.ofPropertyValuesHolder(binding.ivBtn, btnScaleXHolder, btnScaleYHolder)
btnZoomAnim.repeatCount = ObjectAnimator.INFINITE
btnZoomAnim.duration = 500
btnZoomAnim.startDelay = if (needOpenAnim) 800 else 0
btnZoomAnim.addListener(onStart = {
binding.ivBtn.visible()
})
val animSet = AnimatorSet()
if (needOpenAnim) {
animSet.playTogether(bg1ScaleAnim, bg1RotateAnim, bg2ScaleAnim, bg2RotateAnim, titleTransYAnim, titleZoomAnim, btnScaleAnim, btnZoomAnim, closeTransAnim)
} else {
binding.ivClose.visible()
animSet.playTogether(bg1RotateAnim, bg2RotateAnim, titleZoomAnim, btnZoomAnim)
}
animSet.start()
}
fun setOnBackListener(listener: ((DialogEnum) -> Unit)) {
mOnBackListener = listener
}
companion object {
fun newInstance(list: List<CouponActivityEntity>, needAnim: Boolean = true): CouponActivityDialog {
val arg = Bundle()
arg.putSerializable("list", Gson().toJson(list))
arg.putBoolean("needAnim", needAnim)
val fragment = CouponActivityDialog()
fragment.arguments = arg
return fragment
}
}
class ActivityCouponAdapter : BaseQuickAdapter<CouponActivityEntity, BaseViewHolder>(R.layout.listitem_activity_coupon) {
override fun convert(holder: BaseViewHolder, item: CouponActivityEntity) {
holder.getView<TextView>(R.id.tv_discount_amount).typeface = Constants.dDIN_PRO_M
holder.setText(R.id.tv_type, item.activity_type_name)
when (item.activity_type) {
CouponEntity.TYPE_CASH -> {
SpanUtils.with(holder.getView(R.id.tv_discount_amount))
.append("")
.setFontSize(12, true)
.append(DecimalFormat("0.##").format(item.activity_value.toFloat()))
.create()
if (!TextUtils.isEmpty(item.activity_threshold) && item.activity_threshold.toFloat() > 0) {
holder.setText(R.id.tv_threshold_amount, "${DecimalFormat("0.##").format(item.activity_threshold.toFloat())}可用")
} else {
holder.setText(R.id.tv_threshold_amount, "无门槛")
}
}
CouponEntity.TYPE_DISCOUNT -> {
SpanUtils.with(holder.getView(R.id.tv_discount_amount))
.append(DecimalFormat("0.##").format(item.activity_value.toFloat() * 10))
.append("")
.setFontSize(12, true)
.create()
if (!TextUtils.isEmpty(item.activity_threshold) && item.activity_threshold.toFloat() > 0) {
holder.setText(R.id.tv_threshold_amount, "${DecimalFormat("0.##").format(item.activity_threshold.toFloat())}可用")
} else {
holder.setText(R.id.tv_threshold_amount, "无门槛")
}
}
}
if (data.size <= 3) {
if (item.enableAnim) {
holder.itemView.elevation = 3f - holder.layoutPosition * DensityUtils.dp2px(10f)
holder.itemView.postDelayed({
startTransAnim(holder.itemView, holder.layoutPosition, data.size)
item.enableAnim = false
}, 100)
} else {
holder.itemView.visible()
}
} else {
item.enableAnim = false
holder.itemView.visible()
}
}
private fun startTransAnim(view: View, position: Int, total: Int) {
val originStart = view.measuredWidth * (total - 1) / 2 + view.marginStart * (total - 1)
val start = if (total == 2) ((originStart * (-1.0).pow(position))).toInt() else -originStart * (position - 1)
val scaleXHolder = PropertyValuesHolder.ofFloat("scaleX", 1f, 0.8f, 1f, 0.8f, 1f)
val scaleYHolder = PropertyValuesHolder.ofFloat("scaleY", 1f, 0.8f, 1f, 0.8f, 1f)
val animator1 = ObjectAnimator.ofFloat(view, "translationX", 0f, start.toFloat()).setDuration(0)
val animator2 = ObjectAnimator.ofPropertyValuesHolder(view, scaleXHolder, scaleYHolder).setDuration(800)
val animator3 = ObjectAnimator.ofFloat(view, "translationX", start.toFloat(), 0f).setDuration(500)
animator1.addListener(onStart = { view.visibility = View.VISIBLE }, onEnd = { animator2.start() })
animator2.addListener(onEnd = { animator3.start() })
animator3.addListener(onEnd = { if (position == 0) { startZoomAnim(0) } })
animator1.start()
}
private fun startZoomAnim(position: Int) {
val lm = recyclerView.layoutManager as LinearLayoutManager
val itemView = lm.findViewByPosition(position)
val scaleXHolder = PropertyValuesHolder.ofFloat("scaleX", 1.05f, 1.1f, 1.15f, 1.2f, 1.15f, 1.1f, 1.05f, 1f)
val scaleYHolder = PropertyValuesHolder.ofFloat("scaleY", 1.05f, 1.1f, 1.15f, 1.2f, 1.15f, 1.1f, 1.05f, 1f)
val zoomAnim = ObjectAnimator.ofPropertyValuesHolder(itemView, scaleXHolder, scaleYHolder)
zoomAnim.duration = 300
zoomAnim.interpolator = LinearInterpolator()
zoomAnim.addListener(onEnd = { startZoomAnim((position + 1) % data.size) })
zoomAnim.start()
}
}
}

View File

@ -0,0 +1,208 @@
package com.cheng.blzb.ui.dialog
import android.animation.AnimatorSet
import android.animation.ObjectAnimator
import android.animation.PropertyValuesHolder
import android.animation.ValueAnimator
import android.annotation.SuppressLint
import android.app.Dialog
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.os.Bundle
import android.text.TextUtils
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.animation.addListener
import androidx.fragment.app.DialogFragment
import com.chad.library.adapter.base.BaseQuickAdapter
import com.chad.library.adapter.base.viewholder.BaseViewHolder
import com.cheng.blzb.R
import com.cheng.blzb.bean.VipGoodsEntity
import com.cheng.blzb.databinding.DialogGoodsCouponBinding
import com.cheng.blzb.manager.DialogEnum
import com.example.base.extensions.gone
import com.example.base.extensions.visible
import com.example.base.utils.DensityUtils
import com.example.base.utils.ScreenUtils
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
class GoodsCouponDialog : DialogFragment() {
private val mAdapter by lazy { ActivityCouponAdapter() }
private var mOnBackListener: ((DialogEnum) -> Unit)? = null //回调事件
lateinit var binding: DialogGoodsCouponBinding
override fun onStart() {
super.onStart()
val window = dialog?.window
val windowParams = window?.attributes
windowParams?.dimAmount = 0.7f
windowParams?.width = ScreenUtils.getWindowSize().x
windowParams?.height = ScreenUtils.getWindowSize().y
dialog?.window?.attributes = windowParams
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
dialog?.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
dialog?.setCancelable(false)
return super.onCreateView(inflater, container, savedInstanceState)
}
@SuppressLint("SetTextI18n")
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val view = layoutInflater.inflate(R.layout.dialog_goods_coupon, null)
binding = DialogGoodsCouponBinding.bind(view)
val listStr = arguments?.getString("list")
if (!TextUtils.isEmpty(listStr)) {
val list = Gson().fromJson<List<VipGoodsEntity>>(listStr, object : TypeToken<List<VipGoodsEntity>>() {}.type)
mAdapter.setList(list)
}
startAnim1()
val dialog = Dialog(requireContext())
dialog.setContentView(view)
return dialog
}
private fun startAnim1() {
val scaleXHolder = PropertyValuesHolder.ofFloat("scaleX", 0.85f, 1.15f, 0.9f, 1.1f, 0.95f, 1f)
val scaleYHolder = PropertyValuesHolder.ofFloat("scaleY", 0.85f, 1.15f, 0.9f, 1.1f, 0.95f, 1f)
val descScaleAnim = ObjectAnimator.ofPropertyValuesHolder(binding.ivEffect1Desc, scaleXHolder, scaleYHolder)
descScaleAnim.duration = 500
descScaleAnim.addListener(onStart = {
binding.ivEffect1Desc.visible()
})
val descTransAnim = ObjectAnimator.ofFloat(binding.ivEffect1Desc, "translationY", 0f, -DensityUtils.dp2px(200f).toFloat())
descTransAnim.duration = 1000
descTransAnim.addListener(onStart = {
})
val bgTransAnim = ObjectAnimator.ofFloat(binding.ivEffect1Bg, "translationX", ScreenUtils.getScreenWidth().toFloat(), 0f)
bgTransAnim.duration = 500
bgTransAnim.addListener(onStart = {
binding.ivEffect1Bg.visible()
})
val fgTransAnim = ObjectAnimator.ofFloat(binding.ivEffect1Fg, "translationX", -ScreenUtils.getScreenWidth().toFloat(), 0f)
fgTransAnim.duration = 500
fgTransAnim.addListener(onStart = {
binding.ivEffect1Fg.visible()
}, onEnd = {
descScaleAnim.start()
})
val starRotateAnim = ValueAnimator.ofFloat( 0f, 1f)
starRotateAnim.duration = 1500
starRotateAnim.addUpdateListener { animation: ValueAnimator ->
val value = animation.getAnimatedValue() as Float
val transX = DensityUtils.dp2px(50f) * value
val alpha = 0.5f + 0.5f * value
val rotate = 360f * value
binding.ivEffect1Light1.translationX = transX
binding.ivEffect1Light2.translationX = transX
binding.ivEffect1Light3.translationX = transX
binding.ivEffect1Light4.translationX = transX
binding.ivEffect1Star1.translationX = transX
binding.ivEffect1Star2.translationX = transX
binding.ivEffect1Star3.translationX = transX
binding.ivEffect1Star4.translationX = transX
binding.ivEffect1Light1.alpha = alpha
binding.ivEffect1Light2.alpha = alpha
binding.ivEffect1Light3.alpha = alpha
binding.ivEffect1Light4.alpha = alpha
binding.ivEffect1Star1.alpha = alpha
binding.ivEffect1Star2.alpha = alpha
binding.ivEffect1Star3.alpha = alpha
binding.ivEffect1Star4.alpha = alpha
binding.ivEffect1Star1.rotation = rotate
binding.ivEffect1Star2.rotation = rotate
binding.ivEffect1Star3.rotation = rotate
binding.ivEffect1Star4.rotation = rotate
}
starRotateAnim.addListener(onEnd = {
binding.ivEffect1Bg.gone()
binding.ivEffect1Fg.gone()
binding.ivEffect1Light1.gone()
binding.ivEffect1Light2.gone()
binding.ivEffect1Light3.gone()
binding.ivEffect1Light4.gone()
binding.ivEffect1Star1.gone()
binding.ivEffect1Star2.gone()
binding.ivEffect1Star3.gone()
binding.ivEffect1Star4.gone()
descTransAnim.start()
})
val starTransAnim = ValueAnimator.ofFloat(ScreenUtils.getScreenWidth().toFloat(), 0f)
starTransAnim.duration = 500
starTransAnim.addUpdateListener { animation: ValueAnimator ->
val value = animation.getAnimatedValue() as Float
binding.ivEffect1Light1.translationX = value
binding.ivEffect1Light2.translationX = value
binding.ivEffect1Light3.translationX = value
binding.ivEffect1Light4.translationX = value
binding.ivEffect1Star1.translationX = value
binding.ivEffect1Star2.translationX = value
binding.ivEffect1Star3.translationX = value
binding.ivEffect1Star4.translationX = value
}
starTransAnim.addListener(onStart = {
binding.ivEffect1Light1.setVisibility(View.VISIBLE)
binding.ivEffect1Light2.setVisibility(View.VISIBLE)
binding.ivEffect1Light3.setVisibility(View.VISIBLE)
binding.ivEffect1Light4.setVisibility(View.VISIBLE)
binding.ivEffect1Star1.setVisibility(View.VISIBLE)
binding.ivEffect1Star2.setVisibility(View.VISIBLE)
binding.ivEffect1Star3.setVisibility(View.VISIBLE)
binding.ivEffect1Star4.setVisibility(View.VISIBLE)
}, onEnd = {
starRotateAnim.start()
})
val animSet = AnimatorSet()
animSet.playTogether(
bgTransAnim,
fgTransAnim,
starTransAnim
)
animSet.start()
}
fun setOnBackListener(listener: ((DialogEnum) -> Unit)) {
mOnBackListener = listener
}
companion object {
fun newInstance(list: List<VipGoodsEntity>): GoodsCouponDialog {
val arg = Bundle()
arg.putSerializable("list", Gson().toJson(list))
val fragment = GoodsCouponDialog()
fragment.arguments = arg
return fragment
}
}
class ActivityCouponAdapter : BaseQuickAdapter<VipGoodsEntity, BaseViewHolder>(R.layout.listitem_goods_coupon) {
override fun convert(holder: BaseViewHolder, item: VipGoodsEntity) {
}
}
}

View File

@ -0,0 +1,226 @@
package com.cheng.blzb.ui.dialog
import android.animation.AnimatorSet
import android.animation.ObjectAnimator
import android.animation.PropertyValuesHolder
import android.animation.ValueAnimator
import android.annotation.SuppressLint
import android.app.Dialog
import android.content.res.AssetFileDescriptor
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.media.MediaPlayer
import android.os.Build
import android.os.Bundle
import android.text.TextUtils
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.animation.addListener
import androidx.fragment.app.DialogFragment
import com.cheng.blzb.R
import com.cheng.blzb.common.Constants
import com.cheng.blzb.databinding.DialogRedPacketActivityBinding
import com.cheng.blzb.manager.DialogEnum
import com.example.base.extensions.onClick
import com.example.base.extensions.visible
import com.example.base.utils.DensityUtils
import com.example.base.utils.L
import com.example.base.utils.ScreenUtils
import com.ylqh.cube.bean.CouponActivityEntity
class RedPacketActivityDialog : DialogFragment() {
private val needOpenAnim by lazy { arguments?.getBoolean("needAnim") ?: true }
private var redPacketActivity: CouponActivityEntity? = null
private var mOnBackListener: ((DialogEnum) -> Unit)? = null //回调事件
lateinit var binding: DialogRedPacketActivityBinding
override fun onStart() {
super.onStart()
val window = dialog?.window
val windowParams = window?.attributes
windowParams?.dimAmount = 0.7f
windowParams?.width = ScreenUtils.getWindowSize().x
windowParams?.height = ScreenUtils.getWindowSize().y
dialog?.window?.attributes = windowParams
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
dialog?.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
dialog?.setCancelable(false)
return super.onCreateView(inflater, container, savedInstanceState)
}
@SuppressLint("SetTextI18n")
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val view = layoutInflater.inflate(R.layout.dialog_red_packet_activity, null)
binding = DialogRedPacketActivityBinding.bind(view)
binding.tvDiscountAmount.setNumber("00.00", false)
binding.tvDiscountAmount.setScrollVelocity(80)
binding.tvDiscountAmount.setTextFont(Constants.dDIN_PRO_M)
redPacketActivity = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
arguments?.getSerializable("red_packet", CouponActivityEntity::class.java)
} else {
arguments?.getSerializable("red_packet") as CouponActivityEntity
}
binding.tvThresholdAmount.text =
if (TextUtils.isEmpty(redPacketActivity?.activity_threshold) || redPacketActivity?.activity_threshold == "0") {
"无门槛"
} else {
"${redPacketActivity?.activity_threshold}元可用"
}
binding.ivBtnNext.onClick {
mOnBackListener?.invoke(DialogEnum.CLICK_OK)
dismiss()
}
binding.ivClose.onClick {
mOnBackListener?.invoke(DialogEnum.CLICK_CANCEL)
dismiss()
}
// binding.tvDiscountAmount.setNumber("00.00")
if (!needOpenAnim) {
binding.layoutContent.visible()
}
startAnim()
val dialog = Dialog(requireContext())
dialog.setContentView(view)
return dialog
}
private fun startAnim() {
val pvhScaleXBg = PropertyValuesHolder.ofFloat("ScaleX", 0.8f, 1f)
val pvhScaleYBg = PropertyValuesHolder.ofFloat("ScaleY", 0.8f, 1f)
val pvhScaleX1_11 = PropertyValuesHolder.ofFloat("ScaleX", 1f, 1.1f)
val pvhScaleY1_11 = PropertyValuesHolder.ofFloat("ScaleY", 1f, 1.1f)
val pvhScaleXContent = PropertyValuesHolder.ofFloat("ScaleX", 0f, 1f)
val pvhScaleYContent = PropertyValuesHolder.ofFloat("ScaleY", 0f, 1f)
val bgScaleAnim = ObjectAnimator.ofPropertyValuesHolder(binding.ivBg, pvhScaleXBg, pvhScaleYBg)
bgScaleAnim.duration = 450
bgScaleAnim.startDelay = if (needOpenAnim) 750 else 0
bgScaleAnim.repeatCount = ObjectAnimator.INFINITE
bgScaleAnim.repeatMode = ObjectAnimator.REVERSE
bgScaleAnim.addListener(onStart = { binding.ivBg.visible() })
val contentScaleAnim = ObjectAnimator.ofPropertyValuesHolder(binding.layoutContent, pvhScaleXContent, pvhScaleYContent)
contentScaleAnim.duration = 600
contentScaleAnim.startDelay = 200
contentScaleAnim.addListener(onStart = {
binding.layoutContent.visible()
playOpenAudio()
}, onEnd = {
binding.tvDiscountAmount.setNumber(String.format("%.2f", redPacketActivity!!.activity_value.toFloat()))
})
val coinValueAnim = ValueAnimator.ofFloat(0f, 1f)
coinValueAnim.duration = 500
coinValueAnim.startDelay = if (needOpenAnim) 1200 else 0
coinValueAnim.addUpdateListener { animation: ValueAnimator ->
val i = animation.getAnimatedValue() as Float
binding.ivCoin1.translationX = (1 - i) * -DensityUtils.dp2px(100f)
binding.ivCoin1.translationY = (1 - i) * -DensityUtils.dp2px(100f)
binding.ivCoin1.setAlpha(i)
binding.ivCoin2.translationX = (1 - i) * DensityUtils.dp2px(100f)
binding.ivCoin2.translationY = (1 - i) * -DensityUtils.dp2px(100f)
binding.ivCoin2.setAlpha(i)
binding.ivCoin3.translationX = (1 - i) * DensityUtils.dp2px(100f)
binding.ivCoin3.translationY = (1 - i) * DensityUtils.dp2px(100f)
binding.ivCoin3.setAlpha(i)
binding.ivCoin4.translationX = (1 - i) * -DensityUtils.dp2px(100f)
binding.ivCoin4.translationY = (1 - i) * DensityUtils.dp2px(100f)
binding.ivCoin4.setAlpha(i)
}
coinValueAnim.addListener(onStart = {
binding.ivCoin1.setVisibility(View.VISIBLE)
binding.ivCoin2.setVisibility(View.VISIBLE)
binding.ivCoin3.setVisibility(View.VISIBLE)
binding.ivCoin4.setVisibility(View.VISIBLE)
})
val coinTransAnim = ValueAnimator.ofFloat(0f, DensityUtils.dp2px(10f).toFloat(), 0f, -DensityUtils.dp2px(10f).toFloat(), 0f)
coinTransAnim.repeatCount = ObjectAnimator.INFINITE
coinTransAnim.duration = 800
coinTransAnim.startDelay = if (needOpenAnim) 1700 else 0
coinTransAnim.addUpdateListener { animation: ValueAnimator ->
val i = animation.getAnimatedValue() as Float
binding.ivCoin1.translationY = i
binding.ivCoin2.translationY = i
binding.ivCoin3.translationY = i
binding.ivCoin4.translationY = i
}
coinTransAnim.addListener(onStart = {
binding.ivCoin1.setVisibility(View.VISIBLE)
binding.ivCoin2.setVisibility(View.VISIBLE)
binding.ivCoin3.setVisibility(View.VISIBLE)
binding.ivCoin4.setVisibility(View.VISIBLE)
})
val btnScaleAnim = ObjectAnimator.ofPropertyValuesHolder(binding.ivBtnNext, pvhScaleX1_11, pvhScaleY1_11)
btnScaleAnim.repeatCount = ObjectAnimator.INFINITE
btnScaleAnim.repeatMode = ObjectAnimator.REVERSE
btnScaleAnim.duration = 250
val animSet = AnimatorSet()
if (needOpenAnim) {
animSet.playTogether(
bgScaleAnim,
contentScaleAnim,
coinValueAnim,
coinTransAnim,
btnScaleAnim
)
} else {
animSet.playTogether(
bgScaleAnim,
coinTransAnim,
btnScaleAnim
)
}
animSet.start()
}
private fun playOpenAudio() {
var afd: AssetFileDescriptor? = null
try {
afd = requireContext().assets.openFd("open_red_packet.wav")
val mediaPlayer = MediaPlayer()
mediaPlayer.setDataSource(afd)
mediaPlayer.setOnCompletionListener { it.release() }
mediaPlayer.prepare()
mediaPlayer.start()
} catch (e : Exception) {
L.d(e)
} finally {
try {
afd?.close()
} catch (e: Exception) {
L.d(e)
}
}
}
fun setOnBackListener(listener: ((DialogEnum) -> Unit)) {
mOnBackListener = listener
}
companion object {
fun newInstance(redPacketActivity: CouponActivityEntity, needAnim: Boolean = true): RedPacketActivityDialog {
val arg = Bundle()
arg.putSerializable("red_packet", redPacketActivity)
arg.putBoolean("needAnim", needAnim)
val fragment = RedPacketActivityDialog()
fragment.arguments = arg
return fragment
}
}
}

View File

@ -12,21 +12,26 @@ import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.fragment.app.DialogFragment
import androidx.lifecycle.lifecycleScope
import com.chad.library.adapter.base.BaseQuickAdapter
import com.chad.library.adapter.base.viewholder.BaseViewHolder
import com.cheng.blzb.R
import com.cheng.blzb.bean.CouponEntity
import com.cheng.blzb.common.Constants
import com.cheng.blzb.databinding.DialogSelectCouponBinding
import com.cheng.blzb.net.ApiFactory
import com.example.base.extensions.getColor
import com.example.base.extensions.getYYYYMMDD2
import com.example.base.extensions.gone
import com.example.base.extensions.onClick
import com.example.base.extensions.toast
import com.example.base.extensions.visible
import com.example.base.utils.L
import com.example.base.utils.ScreenUtils
import com.example.base.utils.SpanUtils
import com.example.base.widget.EmptyView
import com.example.base.widget.PageStatus
import com.cheng.blzb.R
import com.cheng.blzb.common.Constants
import com.cheng.blzb.databinding.DialogSelectCouponBinding
import com.cheng.blzb.ui.fragment.mine.vip.VipFragment
import kotlinx.coroutines.launch
import java.text.DecimalFormat
class SelectCouponDialog : DialogFragment() {
@ -35,8 +40,8 @@ class SelectCouponDialog : DialogFragment() {
private val mAdapter by lazy { CouponAdapter(price) }
private val mEmptyView by lazy { EmptyView(requireContext()) }
private var mOnBackListener: ((com.cheng.blzb.bean.CouponEntity?) -> Unit)? = null
private var selectedCoupon: com.cheng.blzb.bean.CouponEntity? = null
private var mOnBackListener: ((CouponEntity?) -> Unit)? = null
private var selectedCoupon: CouponEntity? = null
lateinit var binding: DialogSelectCouponBinding
@ -62,6 +67,8 @@ class SelectCouponDialog : DialogFragment() {
binding = DialogSelectCouponBinding.bind(view)
binding.tvTitle.typeface = Constants.ysbth
binding.mRecyclerView.adapter = mAdapter
mEmptyView.setBtnVisible(false)
mAdapter.setEmptyView(mEmptyView)
@ -89,7 +96,7 @@ class SelectCouponDialog : DialogFragment() {
dismiss()
}
initData()
getCouponList()
val dialog = Dialog(requireContext())
dialog.setContentView(view)
@ -97,18 +104,29 @@ class SelectCouponDialog : DialogFragment() {
}
@SuppressLint("NotifyDataSetChanged")
private fun initData() {
val fragment = requireParentFragment()
if (fragment is VipFragment) {
fragment.mViewModel.couponListLiveData.observe(this) { list ->
mAdapter.setList(list)
mAdapter.data.forEach {
if (it.id == id) {
it.isChecked = true
selectedCoupon = it
private fun getCouponList() {
lifecycleScope.launch {
try {
val params = HashMap<String, String>()
params["page"] = "1"
params["size"] = "50"
params["status"] = "1"
params["expire"] = "1"
val response = ApiFactory.apiService.couponList(params)
if (response.status) {
val list = response.data.items
mAdapter.setList(list)
mAdapter.data.forEach {
if (it.id == id) {
it.isChecked = true
selectedCoupon = it
}
}
}
mAdapter.notifyDataSetChanged()
mAdapter.notifyDataSetChanged()
} else toast(response.message, true)
} catch (e: Exception) {
L.d(e)
} finally {
if (mAdapter.data.isEmpty()) {
mEmptyView.setStatus(PageStatus.NO_DATA)
binding.layoutBottom.gone()
@ -117,11 +135,10 @@ class SelectCouponDialog : DialogFragment() {
binding.layoutBottom.visible()
}
}
fragment.mViewModel.couponList()
}
}
fun setOnBackListener(listener: (com.cheng.blzb.bean.CouponEntity?) -> Unit) {
fun setOnBackListener(listener: (CouponEntity?) -> Unit) {
mOnBackListener = listener
}
@ -136,31 +153,31 @@ class SelectCouponDialog : DialogFragment() {
}
}
internal class CouponAdapter(private val price: String) : BaseQuickAdapter<com.cheng.blzb.bean.CouponEntity, BaseViewHolder>(R.layout.listitem_coupon_dialog) {
internal class CouponAdapter(private val price: String) : BaseQuickAdapter<CouponEntity, BaseViewHolder>(R.layout.listitem_coupon_dialog) {
override fun convert(holder: BaseViewHolder, item: com.cheng.blzb.bean.CouponEntity) {
override fun convert(holder: BaseViewHolder, item: CouponEntity) {
holder.setText(
R.id.tv_name,
if (!TextUtils.isEmpty(item.coupon_name)) item.coupon_name else "${item.coupon_value_name}${item.coupon_type_name}"
)
holder.setText(R.id.tv_expire_time, "有效期至 ${(item.expire_timestamp.toLong() * 1000).getYYYYMMDD2()}")
holder.setText(R.id.tv_type, item.coupon_type_name)
holder.getView<TextView>(R.id.tv_discount_amount).typeface = Constants.dDIN_PRO_M
when (item.coupon_type) {
com.cheng.blzb.bean.CouponEntity.TYPE_CASH -> {
CouponEntity.TYPE_CASH -> {
SpanUtils.with(holder.getView(R.id.tv_discount_amount))
.append("")
.setFontSize(12, true)
.append(DecimalFormat("0.##").format(item.coupon_value.toFloat() / 100))
.create()
if (!TextUtils.isEmpty(item.threshold)) {
if (!TextUtils.isEmpty(item.threshold) && item.threshold.toFloat() > 0f) {
holder.setText(R.id.tv_threshold_amount, "${DecimalFormat("0.##").format(item.threshold.toFloat() / 100)}可用")
holder.setVisible(R.id.tv_threshold_amount, true)
} else {
holder.setText(R.id.tv_threshold_amount, "无门槛")
holder.setGone(R.id.tv_threshold_amount, true)
}
}
com.cheng.blzb.bean.CouponEntity.TYPE_DISCOUNT -> {
CouponEntity.TYPE_DISCOUNT -> {
SpanUtils.with(holder.getView(R.id.tv_discount_amount))
.append(DecimalFormat("0.##").format(item.coupon_value.toFloat() * 10))
.append("")
@ -177,13 +194,15 @@ class SelectCouponDialog : DialogFragment() {
if (TextUtils.isEmpty(item.threshold) || item.threshold.toFloat() / 100 <= price.toFloat()) {
holder.setTextColor(R.id.tv_discount_amount, getColor(R.color.color_ff5846))
holder.setTextColor(R.id.tv_threshold_amount, getColor(R.color.color_ff5846))
holder.setBackgroundResource(R.id.layout_amount, R.drawable.shape_fdf4f2_cor6)
holder.setImageResource(R.id.iv_check, if (item.isChecked) R.mipmap.ic_coupon_check_true else R.mipmap.ic_coupon_check_false)
holder.setTextColor(R.id.tv_name, getColor(R.color.color_1a1a1a))
holder.setTextColor(R.id.tv_expire_time, getColor(R.color.color_999999))
holder.itemView.setBackgroundResource(if (item.isChecked) R.drawable.layer_coupon_dialog_bg_checked else R.mipmap.ic_coupon_dialog_bg_default)
} else {
holder.setTextColor(R.id.tv_discount_amount, getColor(R.color.color_d8d8d8))
holder.setTextColor(R.id.tv_threshold_amount, getColor(R.color.color_d8d8d8))
holder.setBackgroundResource(R.id.layout_amount, R.drawable.shape_f6f6f6_cor6)
holder.setImageResource(R.id.iv_check, R.mipmap.ic_coupon_check_disable)
holder.setTextColor(R.id.tv_discount_amount, getColor(R.color.color_848484))
holder.setTextColor(R.id.tv_threshold_amount, getColor(R.color.color_848484))
holder.setTextColor(R.id.tv_name, getColor(R.color.color_848484))
holder.setTextColor(R.id.tv_expire_time, getColor(R.color.color_a1a1a1))
holder.itemView.setBackgroundResource(R.mipmap.ic_coupon_dialog_bg_disable)
}
}
}

View File

@ -1,19 +1,28 @@
package com.cheng.blzb.ui.fragment.home
import android.annotation.SuppressLint
import android.view.MotionEvent
import android.view.ViewGroup
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.recyclerview.widget.RecyclerView.HORIZONTAL
import com.cheng.blzb.R
import com.cheng.blzb.bean.BidItemEntity
import com.cheng.blzb.bean.CouponEntity
import com.cheng.blzb.bean.MenuEntity
import com.cheng.blzb.bean.VipGoodsEntity
import com.cheng.blzb.common.Constants
import com.cheng.blzb.common.EventConstants
import com.cheng.blzb.databinding.FragmentHomeBinding
import com.cheng.blzb.event.HomeRefreshEvent
import com.cheng.blzb.manager.DialogEnum
import com.cheng.blzb.manager.EventReportManager
import com.cheng.blzb.manager.NotificationHelper
import com.cheng.blzb.manager.SearchHistoryManager
import com.cheng.blzb.manager.UserConfigManager
import com.cheng.blzb.ui.activity.PublicActivity
import com.cheng.blzb.ui.dialog.CouponActivityDialog
import com.cheng.blzb.ui.dialog.GoodsCouponDialog
import com.cheng.blzb.ui.dialog.RedPacketActivityDialog
import com.cheng.blzb.ui.fragment.bid.BidAdapter
import com.cheng.blzb.ui.fragment.bid.detail.BidDetailFragment
import com.cheng.blzb.ui.fragment.home.bszz.BSZZFragment
@ -28,13 +37,22 @@ import com.example.base.common.RxBus
import com.example.base.decoration.GridSpaceItemDecoration
import com.example.base.decoration.SpacesItemDecoration
import com.example.base.extensions.getColor
import com.example.base.extensions.gone
import com.example.base.extensions.onClick
import com.example.base.extensions.toast
import com.example.base.extensions.visible
import com.example.base.ui.list.ListFragment
import com.example.base.utils.BarUtils
import com.example.base.utils.DensityUtils
import com.example.base.utils.L
import com.example.base.utils.MMKVUtils
import com.example.base.utils.ScreenUtils
import com.example.base.utils.SpanUtils
import com.ylqh.cube.bean.CouponActivityEntity
import org.libpag.PAGFile
import java.text.DecimalFormat
import kotlin.math.abs
import kotlin.text.toInt
/**
@ -51,6 +69,18 @@ class HomeFragment : ListFragment<FragmentHomeBinding, HomeViewModel, BidItemEnt
private var item: BidItemEntity? = null
/*****红包优惠券*****/
private var isFirstCheckCouponActivity = true
private var isFirstCheckGoodsCoupon = true
private val goodsList by lazy { mutableListOf<VipGoodsEntity>() }
private val couponActivityList by lazy { mutableListOf<CouponActivityEntity>() }
private var isNoClick = false
private var startX = 0f
private var startY = 0f
private var downX = 0f
private var downY = 0f
/*****红包优惠券*****/
override fun initView() {
super.initView()
binding.tvTitle.typeface = Constants.pmzdbt
@ -81,9 +111,19 @@ class HomeFragment : ListFragment<FragmentHomeBinding, HomeViewModel, BidItemEnt
menuAdapter.setList(MenuEntity.getHomeMenu())
}
mViewModel.getHotKeywordList("")
binding.root.postDelayed({
if (activity != null && UserConfigManager.userInfo?.vip != "3") {
if (UserConfigManager.isShowGoodsCouponAnim()) {
mViewModel.getGoodsList()
} else {
mViewModel.couponActivityList()
}
}
}, 2000)
firstLoad()
}
@SuppressLint("ClickableViewAccessibility")
override fun initListener() {
super.initListener()
binding.appBarLayout.addOnOffsetChangedListener { appBarLayout, verticalOffset ->
@ -140,7 +180,116 @@ class HomeFragment : ListFragment<FragmentHomeBinding, HomeViewModel, BidItemEnt
EventReportManager.eventReport(EventConstants.JUMP_TO_BID_SEARCH, item.title)
}
}
}
binding.pvCouponActivity.onClick {
if (couponActivityList.size == 1 && couponActivityList[0].activity_type == CouponEntity.TYPE_CASH) {
showRedPacketActivityDialog()
EventReportManager.eventReport(EventConstants.COUPON_ANIMATION_PLAY + ".red.packet", "home", "")
} else {
showCouponActivityDialog()
EventReportManager.eventReport(EventConstants.COUPON_ANIMATION_PLAY, "home", "")
}
isFirstCheckCouponActivity = false
}
binding.pvGoodsCoupon.onClick {
if (isFirstCheckGoodsCoupon) {
showGoodsCouponDialog()
} else {
PublicActivity.start(requireContext(), VipFragment::class.java, Pair("origin", "home_coupon"))
}
// isFirstCheckGoodsCoupon = false
}
binding.pvCouponActivity.setOnTouchListener { v, event ->
when (event.action) {
MotionEvent.ACTION_DOWN -> {
isNoClick = false
startX = event.rawX
startY = event.rawY
L.e("当前的初始位置X$startX")
L.e("当前的初始位置Y$startY")
downX = event.rawX
downY = event.rawY
}
MotionEvent.ACTION_MOVE -> {
val diffX: Float = event.rawX - startX
val diffY: Float = event.rawY - startY
L.e("当前的间距X$diffX")
L.e("当前的间距Y$diffY")
var y: Float = v.y + diffY
val parent = v.parent as ViewGroup
if (y <= DensityUtils.dp2px(44f)) {
y = DensityUtils.dp2px(44f).toFloat()
} else if (y >= parent.bottom - (BarUtils.getStatusBarHeight() + DensityUtils.dp2px(30f))) {
y = (parent.bottom - (BarUtils.getStatusBarHeight() + DensityUtils.dp2px(30f))).toFloat()
}
v.x += diffX
v.y = y
startX = (event.rawX.toInt()).toFloat()
startY = (event.rawY.toInt()).toFloat()
if (abs((startX - downX).toDouble()) > 50 || abs((startY - downY).toDouble()) > 50) { //如果移动位置超过了50则不触发点击事件
isNoClick = true
}
}
MotionEvent.ACTION_UP -> {
L.e((("当前的left---" + v.left) + "当前的right" + v.right) + "当前的宽度" + v.width)
if (v.x + v.width / 2 >= ScreenUtils.getScreenWidth() / 2) { //如果在右侧则直接滑动到右侧
v.x = (ScreenUtils.getScreenWidth() - v.width).toFloat()
} else {
v.x = 0f
}
}
}
isNoClick
}
binding.pvGoodsCoupon.setOnTouchListener { v, event ->
when (event.action) {
MotionEvent.ACTION_DOWN -> {
isNoClick = false
startX = event.rawX
startY = event.rawY
L.e("当前的初始位置X$startX")
L.e("当前的初始位置Y$startY")
downX = event.rawX
downY = event.rawY
}
MotionEvent.ACTION_MOVE -> {
val diffX: Float = event.rawX - startX
val diffY: Float = event.rawY - startY
L.e("当前的间距X$diffX")
L.e("当前的间距Y$diffY")
var y: Float = v.y + diffY
val parent = v.parent as ViewGroup
if (y <= DensityUtils.dp2px(44f)) {
y = DensityUtils.dp2px(44f).toFloat()
} else if (y >= parent.bottom - (BarUtils.getStatusBarHeight() + DensityUtils.dp2px(30f))) {
y = (parent.bottom - (BarUtils.getStatusBarHeight() + DensityUtils.dp2px(30f))).toFloat()
}
v.x += diffX
v.y = y
startX = (event.rawX.toInt()).toFloat()
startY = (event.rawY.toInt()).toFloat()
if (abs((startX - downX).toDouble()) > 50 || abs((startY - downY).toDouble()) > 50) { //如果移动位置超过了50则不触发点击事件
isNoClick = true
}
}
MotionEvent.ACTION_UP -> {
L.e((("当前的left---" + v.left) + "当前的right" + v.right) + "当前的宽度" + v.width)
if (v.x + v.width / 2 >= ScreenUtils.getScreenWidth() / 2) { //如果在右侧则直接滑动到右侧
v.x = (ScreenUtils.getScreenWidth() - v.width).toFloat()
} else {
v.x = 0f
}
}
}
isNoClick
}
}
@ -178,9 +327,111 @@ class HomeFragment : ListFragment<FragmentHomeBinding, HomeViewModel, BidItemEnt
}
}
mViewModel.goodsListLiveData.observe(this) {
goodsList.clear()
goodsList.addAll(it)
if (it.isNotEmpty()) {
startCouponActivityAnim(false)
} else {
stopCouponActivityAnim(false)
}
}
mViewModel.couponActivityLiveData.observe(this) {
couponActivityList.clear()
couponActivityList.addAll(it)
if (it.isNotEmpty()) {
startCouponActivityAnim(true)
} else {
stopCouponActivityAnim(true)
}
}
mViewModel.receiveCouponLiveData.observe(this) {
toast("领取成功")
stopCouponActivityAnim(true)
PublicActivity.start(requireContext(), VipFragment::class.java, Pair("origin", "home_coupon"))
}
val homeRefreshEvent = RxBus.defaultInstance.toObservable(HomeRefreshEvent::class.java).subscribe {
firstLoad()
if (activity != null && UserConfigManager.userInfo?.vip != "3") {
if (UserConfigManager.isShowGoodsCouponAnim()) {
mViewModel.getGoodsList()
} else {
mViewModel.couponActivityList()
}
}
}
addDisposable(homeRefreshEvent)
}
private fun showGoodsCouponDialog() {
val f = GoodsCouponDialog.newInstance(goodsList)
f.setOnBackListener { d ->
if (d == DialogEnum.CLICK_OK) {
PublicActivity.start(requireContext(), VipFragment::class.java, Pair("origin", "home_coupon"))
} else {
EventReportManager.eventReport(EventConstants.COUPON_ANIMATION_CLOSE, "home", "")
}
}
f.show(childFragmentManager, CouponActivityDialog::class.java.simpleName)
// UserConfigManager.hideGoodsCouponAnim()
}
private fun showRedPacketActivityDialog() {
val f = RedPacketActivityDialog.newInstance(couponActivityList[0], isFirstCheckCouponActivity)
f.setOnBackListener { d ->
if (d == DialogEnum.CLICK_OK) {
mViewModel.receiveActivityCoupon(couponActivityList[0].id, 0)
EventReportManager.eventReport(EventConstants.COUPON_RECEIVE + ".red.packet", "home", "")
} else {
EventReportManager.eventReport(EventConstants.COUPON_ANIMATION_CLOSE + ".red.packet", "home", "")
}
}
f.show(childFragmentManager, RedPacketActivityDialog::class.java.simpleName)
}
private fun showCouponActivityDialog() {
val f = CouponActivityDialog.newInstance(couponActivityList, isFirstCheckCouponActivity)
f.setOnBackListener { d ->
if (d == DialogEnum.CLICK_OK) {
val idList = mutableListOf<String>()
couponActivityList.forEach { idList.add(it.id) }
mViewModel.receiveActivityCoupon(idList.joinToString(","), 0)
EventReportManager.eventReport(EventConstants.COUPON_RECEIVE, "home", "")
} else {
EventReportManager.eventReport(EventConstants.COUPON_ANIMATION_CLOSE, "home", "")
}
}
f.show(childFragmentManager, CouponActivityDialog::class.java.simpleName)
}
private fun startCouponActivityAnim(isRedPacket: Boolean) {
if (isRedPacket) {
binding.pvCouponActivity.visible()
binding.pvGoodsCoupon.gone()
val pagFile = PAGFile.Load(requireActivity().assets, "effects/red_packet_float.pag")
binding.pvCouponActivity.composition = pagFile
binding.pvCouponActivity.setRepeatCount(0)
binding.pvCouponActivity.play()
} else {
binding.pvGoodsCoupon.visible()
binding.pvCouponActivity.gone()
val pagFile = PAGFile.Load(requireActivity().assets, "effects/coupon_float.pag")
binding.pvGoodsCoupon.composition = pagFile
binding.pvGoodsCoupon.setRepeatCount(0)
binding.pvGoodsCoupon.play()
}
}
private fun stopCouponActivityAnim(isRedPacket: Boolean) {
if (isRedPacket) {
binding.pvCouponActivity.pause()
binding.pvCouponActivity.gone()
} else {
binding.pvGoodsCoupon.pause()
binding.pvCouponActivity.gone()
}
}
}

View File

@ -5,18 +5,23 @@ import androidx.lifecycle.MutableLiveData
import com.cheng.blzb.bean.BidItemEntity
import com.cheng.blzb.bean.BidTypeEntity
import com.cheng.blzb.bean.UserAuthEntity
import com.cheng.blzb.bean.VipGoodsEntity
import com.cheng.blzb.net.ApiFactory
import com.cheng.blzb.net.model.toListResult
import com.example.base.extensions.toast
import com.example.base.utils.L
import com.example.base.viewmodel.ListViewModel
import com.ylqh.cube.bean.CouponActivityEntity
class HomeViewModel : ListViewModel<BidItemEntity>() {
val totalLiveData = MutableLiveData<String>()
val typeLiveData = MutableLiveData<List<BidTypeEntity>>()
val authLiveData = MutableLiveData<UserAuthEntity>()
val recommendLiveData = MutableLiveData<List<String>>()
val goodsListLiveData = MutableLiveData<List<VipGoodsEntity>>()
val couponActivityLiveData = MutableLiveData<List<CouponActivityEntity>>()
val receiveCouponLiveData = MutableLiveData<Int>()
override suspend fun requestApi(params: ArrayMap<String, String>): Result<List<BidItemEntity>> {
params["sort"] = "123"
@ -69,4 +74,40 @@ class HomeViewModel : ListViewModel<BidItemEntity>() {
})
}
fun getGoodsList() {
launchOnUiTryCatch({
val response = ApiFactory.apiService.getGoodsList("member")
if (response.status) {
goodsListLiveData.postValue(response.data)
}
}, {
L.d(it)
})
}
fun couponActivityList() {
launchOnUiTryCatch({
val response = ApiFactory.apiService.couponActivityList("cli_home")
if (response.status) {
couponActivityLiveData.postValue(response.data)
}
},{
L.d(it)
})
}
fun receiveActivityCoupon(ids: String, type: Int) {
showDialog()
launchOnUiTryCatch({
val response = ApiFactory.apiService.getActivityCoupons(ids)
if (response.status) {
receiveCouponLiveData.postValue(type)
} else toast(response.message, true)
dismissDialog()
}, {
dismissDialog()
setError(it)
L.d(it)
})
}
}

View File

@ -4,8 +4,11 @@ import android.animation.ValueAnimator
import android.annotation.SuppressLint
import android.text.TextUtils
import android.view.View
import android.window.OnBackInvokedDispatcher
import androidx.activity.addCallback
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.ContextCompat
import androidx.core.os.BuildCompat
import androidx.core.view.isVisible
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
@ -13,6 +16,7 @@ import androidx.recyclerview.widget.RecyclerView
import com.bytedance.ads.convert.event.ConvertReportHelper
import com.cheng.blzb.R
import com.cheng.blzb.bean.CorpEntity
import com.cheng.blzb.bean.CouponEntity
import com.cheng.blzb.bean.OrderPayEntity
import com.cheng.blzb.bean.UserEntity
import com.cheng.blzb.bean.VipGoodsEntity
@ -26,8 +30,12 @@ import com.cheng.blzb.manager.DialogEnum
import com.cheng.blzb.manager.EventReportManager
import com.cheng.blzb.manager.LoginManager
import com.cheng.blzb.manager.UserConfigManager
import com.cheng.blzb.ui.activity.MainActivity
import com.cheng.blzb.ui.activity.PublicActivity
import com.cheng.blzb.ui.dialog.CouponActivityDialog
import com.cheng.blzb.ui.dialog.PayTipDialog
import com.cheng.blzb.ui.dialog.RedPacketActivityDialog
import com.cheng.blzb.ui.dialog.SelectCouponDialog
import com.cheng.blzb.ui.dialog.TipDialog
import com.cheng.blzb.ui.fragment.mine.order.cert.CertificateFragment
import com.cheng.blzb.utils.DateUtils
@ -48,6 +56,7 @@ import com.example.base.utils.SpanUtils
import com.google.gson.Gson
import com.tencent.mm.opensdk.openapi.IWXAPI
import com.tencent.mm.opensdk.openapi.WXAPIFactory
import com.ylqh.cube.bean.CouponActivityEntity
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.core.Observable
import io.reactivex.rxjava3.disposables.Disposable
@ -89,6 +98,12 @@ class VipFragment : BaseFragment<FragmentVipBinding, VipViewModel>() {
private var countdownDisposable: Disposable? = null
private var scrollTask: Disposable? = null
/******优惠券红包******/
private var selectedCoupon: CouponEntity? = null
private val couponList by lazy { mutableListOf<CouponEntity>() }
private val couponEnterActivityList by lazy { mutableListOf<CouponActivityEntity>() }
private val couponReturnActivityList by lazy { mutableListOf<CouponActivityEntity>() }
override fun initView() {
super.initView()
setBackColor(R.color.white)
@ -114,6 +129,13 @@ class VipFragment : BaseFragment<FragmentVipBinding, VipViewModel>() {
mViewModel.getPayUserTips()
mViewModel.getGoodsList(if (vipType == 0) "member" else "corp")
mViewModel.getCorpInfo()
mViewModel.couponList()
if (!MainActivity.hasCheckedVipEnterCouponActivity) {
mViewModel.couponEnterActivityList()
}
if (!MainActivity.hasCheckedVipReturnCouponActivity) {
mViewModel.couponReturnActivityList()
}
}
@SuppressLint("NotifyDataSetChanged", "SetTextI18n")
@ -121,6 +143,21 @@ class VipFragment : BaseFragment<FragmentVipBinding, VipViewModel>() {
super.initListener()
binding.rvUserTips.onTouch { _, _ -> true }
setBackPressed()
mTitleBar?.setNavigationOnClickListener {
if (MainActivity.hasCheckedVipReturnCouponActivity || MainActivity.hasCheckedVipGuideReturnCouponActivity || couponReturnActivityList.isEmpty()) {
requireActivity().finish()
} else {
if (couponReturnActivityList.size == 1 && couponReturnActivityList[0].activity_type == CouponEntity.TYPE_CASH) {
showRedPacketActivityDialog(false)
EventReportManager.eventReport(EventConstants.COUPON_ANIMATION_PLAY + ".red.packet", "pay_return", "")
} else {
showCouponActivityDialog(false)
EventReportManager.eventReport(EventConstants.COUPON_ANIMATION_PLAY, "pay_return", "")
}
}
}
goodsAdapter.setOnItemClickListener { _, _, i ->
val item = goodsAdapter.getItem(i)
if (item.goods_id == goodsEntity?.goods_id) return@setOnItemClickListener
@ -144,6 +181,8 @@ class VipFragment : BaseFragment<FragmentVipBinding, VipViewModel>() {
setPrice(goodsEntity!!.price.toFloat())
}
releasePayType()
selectedCoupon = null
setCoupon()
}
binding.btnTab1.onClick {
@ -182,19 +221,38 @@ class VipFragment : BaseFragment<FragmentVipBinding, VipViewModel>() {
}
}
binding.tvCoupon.onClick {
if (goodsEntity == null) {
toast("请先选择要开通的会员套餐")
return@onClick
}
val f = SelectCouponDialog.newInstance(selectedCoupon?.id, goodsEntity!!.price)
f.setOnBackListener {
selectedCoupon = it
checkCouponValid()
setCoupon()
EventReportManager.eventReport(EventConstants.COUPON_DIALOG_CHECK, "选择优惠券切换", Gson().toJson(selectedCoupon))
}
f.show(childFragmentManager, SelectCouponDialog::class.java.simpleName)
EventReportManager.eventReport(EventConstants.COUPON_VIEW, "member", "")
}
binding.tvAliPay.onClick {
payType = 1
checkPayType()
EventReportManager.eventReport(EventConstants.PAY_SELECT, "alipay", origin)
}
binding.tvWxPay.onClick {
payType = 0
checkPayType()
EventReportManager.eventReport(EventConstants.PAY_SELECT, "weixin", origin)
}
binding.tvBankPay.onClick {
payType = 2
checkPayType()
EventReportManager.eventReport(EventConstants.PAY_SELECT, "bank", origin)
}
binding.cbAgree.onCheckedChange { _, isChecked ->
@ -219,31 +277,19 @@ class VipFragment : BaseFragment<FragmentVipBinding, VipViewModel>() {
val f = PayTipDialog.newInstance(showAgreement = true, showRenew = !TextUtils.isEmpty(goodsEntity?.sign_value) && payType == 1)
f.setOnSelectListener {
binding.cbAgree.isChecked = true
if (payType == 0) {
if (!TextUtils.isEmpty(goodsEntity!!.weixinMpOriId)) {
mViewModel.payCreateOrder(goodsEntity!!.goods_id, "combo", origin, "${seatCount - seatCountLimit}")
} else {
mViewModel.payCreateOrder(goodsEntity!!.goods_id, "weixin", origin, "${seatCount - seatCountLimit}")
}
} else if (payType == 1) {
mViewModel.payCreateOrder(goodsEntity!!.goods_id, "alipay", origin, "${seatCount - seatCountLimit}")
} else if (payType == 2) {
mViewModel.payCreateOrder(goodsEntity!!.goods_id, "bank", origin, "${seatCount - seatCountLimit}")
if (!checkCouponValid()) {
setCoupon()
return@setOnSelectListener
}
createOrder()
}
f.show(childFragmentManager, PayTipDialog::class.java.simpleName)
} else {
if (payType == 0) {
if (!TextUtils.isEmpty(goodsEntity!!.weixinMpOriId)) {
mViewModel.payCreateOrder(goodsEntity!!.goods_id, "combo", origin, "${seatCount - seatCountLimit}")
} else {
mViewModel.payCreateOrder(goodsEntity!!.goods_id, "weixin", origin, "${seatCount - seatCountLimit}")
}
} else if (payType == 1) {
mViewModel.payCreateOrder(goodsEntity!!.goods_id, "alipay", origin, "${seatCount - seatCountLimit}")
} else if (payType == 2) {
mViewModel.payCreateOrder(goodsEntity!!.goods_id, "bank", origin, "${seatCount - seatCountLimit}")
if (!checkCouponValid()) {
setCoupon()
return@onClick
}
createOrder()
}
EventReportManager.eventReport(
EventConstants.PAY_PAY,
@ -304,9 +350,20 @@ class VipFragment : BaseFragment<FragmentVipBinding, VipViewModel>() {
}
releasePayType()
}
selectedCoupon = null
setCoupon()
setCouponCount()
initPrivacyTv()
}
mViewModel.couponListLiveData.observe(this) { list ->
couponList.clear()
couponList.addAll(list)
if (selectedCoupon == null) {
setCouponCount()
}
}
mViewModel.corpInfoLiveData.observe(this) {
corpInfo = it
if (!TextUtils.isEmpty(it.sub_user_limit)) {
@ -351,6 +408,28 @@ class VipFragment : BaseFragment<FragmentVipBinding, VipViewModel>() {
startScroll()
}
mViewModel.couponEnterActivityLiveData.observe(this) {
couponEnterActivityList.clear()
couponEnterActivityList.addAll(it)
if (couponEnterActivityList.size == 1 && couponEnterActivityList[0].activity_type == CouponEntity.TYPE_CASH) {
showRedPacketActivityDialog(true)
EventReportManager.eventReport(EventConstants.COUPON_ANIMATION_PLAY + ".red.packet", "pay_enter", "")
} else {
showCouponActivityDialog(true)
EventReportManager.eventReport(EventConstants.COUPON_ANIMATION_PLAY, "pay_enter", "")
}
}
mViewModel.couponReturnActivityLiveData.observe(this) { list ->
couponReturnActivityList.clear()
couponReturnActivityList.addAll(list)
}
mViewModel.receiveCouponLiveData.observe(this) {
toast("领取成功")
mViewModel.couponList()
}
val payStatusDisposable = RxBus.defaultInstance.toObservable(PayStatusEvent::class.java).subscribe {
when (it.payStatus) {
PayStatusEnum.PAY_SUCCESS -> {
@ -373,6 +452,20 @@ class VipFragment : BaseFragment<FragmentVipBinding, VipViewModel>() {
addDisposable(payStatusDisposable)
}
private fun createOrder() {
if (payType == 0) {
if (!TextUtils.isEmpty(goodsEntity!!.weixinMpOriId)) {
mViewModel.payCreateOrder(goodsEntity!!.goods_id, "combo", origin, "${seatCount - seatCountLimit}", selectedCoupon?.id)
} else {
mViewModel.payCreateOrder(goodsEntity!!.goods_id, "weixin", origin, "${seatCount - seatCountLimit}", selectedCoupon?.id)
}
} else if (payType == 1) {
mViewModel.payCreateOrder(goodsEntity!!.goods_id, "alipay", origin, "${seatCount - seatCountLimit}", selectedCoupon?.id)
} else if (payType == 2) {
mViewModel.payCreateOrder(goodsEntity!!.goods_id, "bank", origin, "${seatCount - seatCountLimit}", selectedCoupon?.id)
}
}
private fun showQueryTipDialog() {
if (showQueryTip) {
val f = TipDialog.newInstance("温馨提示", "是否已完成支付", "未支付", "已支付", false)
@ -603,6 +696,101 @@ class VipFragment : BaseFragment<FragmentVipBinding, VipViewModel>() {
}
}
private fun setCouponCount() {
val enableCount = couponList.size
if (enableCount > 0) {
SpanUtils.with(binding.tvCoupon)
.append("您有")
.setForegroundColor(getColor(R.color.color_90ffffff))
.append("${enableCount}")
.setForegroundColor(getColor(R.color.color_f0365e))
.append("红包")
.setForegroundColor(getColor(R.color.color_90ffffff))
.create()
} else {
binding.tvCoupon.setTextColor(getColor(R.color.color_50ffffff))
binding.tvCoupon.text = "暂无可用的红包"
}
}
@SuppressLint("SetTextI18n")
private fun setCoupon() {
if (selectedCoupon != null) {
when (selectedCoupon!!.coupon_type) {
CouponEntity.TYPE_CASH -> {
binding.tvCoupon.text = "-¥${DecimalFormat("0.##").format(selectedCoupon!!.coupon_value.toFloat() / 100)}"
val endPrice = goodsEntity!!.price.toFloat() - selectedCoupon!!.coupon_value.toFloat() / 100
setPrice(endPrice)
}
CouponEntity.TYPE_DISCOUNT -> {
binding.tvCoupon.text = "${DecimalFormat("0.##").format(selectedCoupon!!.coupon_value.toFloat() * 10)}"
val endPrice = goodsEntity!!.price.toFloat() * selectedCoupon!!.coupon_value.toFloat()
setPrice(endPrice)
}
}
binding.tvCoupon.setTextColor(getColor(R.color.color_f0365e))
} else {
setPrice(goodsEntity!!.price.toFloat())
setCouponCount()
}
}
private fun checkCouponValid(): Boolean {
if (selectedCoupon != null) {
if (selectedCoupon!!.expire_timestamp.toLong() < System.currentTimeMillis() / 1000) {
selectedCoupon = null
toast("红包已过期")
return false
}
}
return true
}
private fun showRedPacketActivityDialog(isEnter: Boolean) {
val coupon = if (isEnter) {
MainActivity.hasCheckedVipEnterCouponActivity = true
couponEnterActivityList[0]
} else {
MainActivity.hasCheckedVipReturnCouponActivity = true
couponReturnActivityList[0]
}
val f = RedPacketActivityDialog.newInstance(coupon)
f.setOnBackListener { d ->
if (d == DialogEnum.CLICK_OK) {
mViewModel.receiveActivityCoupon(coupon.id)
EventReportManager.eventReport(EventConstants.COUPON_RECEIVE + ".red.packet", if (isEnter) "pay_enter" else "pay_return", "")
} else {
EventReportManager.eventReport(EventConstants.COUPON_ANIMATION_CLOSE + ".red.packet", if (isEnter) "pay_enter" else "pay_return", "")
}
}
f.show(childFragmentManager, RedPacketActivityDialog::class.java.simpleName)
}
private fun showCouponActivityDialog(isEnter: Boolean) {
val couponList = if (isEnter) {
MainActivity.hasCheckedVipEnterCouponActivity = true
couponEnterActivityList
} else {
MainActivity.hasCheckedVipReturnCouponActivity = true
couponReturnActivityList
}
if (couponList.isNotEmpty()) {
val f = CouponActivityDialog.newInstance(couponList)
f.setOnBackListener { d ->
if (d == DialogEnum.CLICK_OK) {
val idList = mutableListOf<String>()
couponList.forEach { idList.add(it.id) }
mViewModel.receiveActivityCoupon(idList.joinToString(","))
EventReportManager.eventReport(EventConstants.COUPON_RECEIVE, if (isEnter) "pay_enter" else "pay_return", "")
} else {
EventReportManager.eventReport(EventConstants.COUPON_ANIMATION_CLOSE, if (isEnter) "pay_enter" else "pay_return", "")
}
}
f.show(childFragmentManager, CouponActivityDialog::class.java.simpleName)
}
}
private fun sendBDReport(isSuccess: Boolean) {
ConvertReportHelper.onEventPurchase(
"member",
@ -666,4 +854,37 @@ class VipFragment : BaseFragment<FragmentVipBinding, VipViewModel>() {
countdownDisposable?.dispose()
super.onDestroyView()
}
@SuppressLint("UnsafeOptInUsageError")
private fun setBackPressed() {
if (BuildCompat.isAtLeastT()) {
requireActivity().onBackInvokedDispatcher.registerOnBackInvokedCallback(OnBackInvokedDispatcher.PRIORITY_DEFAULT) {
if (MainActivity.hasCheckedVipReturnCouponActivity || MainActivity.hasCheckedVipGuideReturnCouponActivity || couponReturnActivityList.isEmpty()) {
requireActivity().finish()
} else {
if (couponReturnActivityList.size == 1 && couponReturnActivityList[0].activity_type == CouponEntity.TYPE_CASH) {
showRedPacketActivityDialog(false)
EventReportManager.eventReport(EventConstants.COUPON_ANIMATION_PLAY + ".red.packet", "pay_return_scroll_back", "")
} else {
showCouponActivityDialog(false)
EventReportManager.eventReport(EventConstants.COUPON_ANIMATION_PLAY, "pay_return_scroll_back", "")
}
}
}
} else {
requireActivity().onBackPressedDispatcher.addCallback(this) {
if (MainActivity.hasCheckedVipReturnCouponActivity || MainActivity.hasCheckedVipGuideReturnCouponActivity || couponReturnActivityList.isEmpty()) {
requireActivity().finish()
} else {
if (couponReturnActivityList.size == 1 && couponReturnActivityList[0].activity_type == CouponEntity.TYPE_CASH) {
showRedPacketActivityDialog(false)
EventReportManager.eventReport(EventConstants.COUPON_ANIMATION_PLAY + ".red.packet", "pay_return_scroll_back", "")
} else {
showCouponActivityDialog(false)
EventReportManager.eventReport(EventConstants.COUPON_ANIMATION_PLAY, "pay_return_scroll_back", "")
}
}
}
}
}
}

View File

@ -20,7 +20,6 @@ import okhttp3.RequestBody.Companion.toRequestBody
class VipViewModel : BaseViewModel() {
var queryOrderJob: Job? = null
val userInfoLiveData = MutableLiveData<UserEntity>()
val goodsListLiveData = MutableLiveData<List<VipGoodsEntity>>()
val corpInfoLiveData = MutableLiveData<CorpEntity>()
@ -28,8 +27,9 @@ class VipViewModel : BaseViewModel() {
val orderInfoLiveData = MutableLiveData<OrderEntity>()
val payTipsLiveData = MutableLiveData<List<String>>()
val couponListLiveData = MutableLiveData<List<CouponEntity>>()
val couponActivityLiveData = MutableLiveData<List<CouponActivityEntity>>()
val getCouponLiveData = MutableLiveData<Any>()
val couponEnterActivityLiveData = MutableLiveData<List<CouponActivityEntity>>()
val couponReturnActivityLiveData = MutableLiveData<List<CouponActivityEntity>>()
val receiveCouponLiveData = MutableLiveData<Any>()
fun userInfo() {
showDialog()
@ -157,23 +157,34 @@ class VipViewModel : BaseViewModel() {
})
}
fun couponActivityList() {
fun couponEnterActivityList() {
launchOnUiTryCatch({
val response = ApiFactory.apiService.couponActivityList("cli_pay_return")
val response = ApiFactory.apiService.couponActivityList("cli_pay_enter")
if (response.status) {
couponActivityLiveData.postValue(response.data)
couponEnterActivityLiveData.postValue(response.data)
}
},{
L.d(it)
})
}
fun getActivityCoupon(ids: String) {
fun couponReturnActivityList() {
launchOnUiTryCatch({
val response = ApiFactory.apiService.couponActivityList("cli_pay_return")
if (response.status) {
couponReturnActivityLiveData.postValue(response.data)
}
},{
L.d(it)
})
}
fun receiveActivityCoupon(ids: String) {
showDialog()
launchOnUiTryCatch({
val response = ApiFactory.apiService.getActivityCoupons(ids)
if (response.status) {
getCouponLiveData.postValue(Any())
receiveCouponLiveData.postValue(Any())
} else toast(response.message, true)
dismissDialog()
}, {

View File

@ -0,0 +1,277 @@
package com.cheng.blzb.widget
import android.content.Context
import android.graphics.Typeface
import android.text.TextUtils
import android.util.AttributeSet
import android.util.TypedValue
import android.view.Gravity
import android.view.ViewGroup
import android.view.animation.AccelerateDecelerateInterpolator
import android.view.animation.Interpolator
import android.widget.LinearLayout
import android.widget.TextView
import androidx.annotation.ColorRes
import androidx.annotation.IntRange
import androidx.core.content.ContextCompat
import androidx.core.content.withStyledAttributes
import com.cheng.blzb.R
import com.devcon.audi.view.ScrollNumber
import com.example.base.extensions.getColor
import java.util.regex.Pattern
class MultiScrollNumber @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : LinearLayout(context, attrs, defStyleAttr) {
private val mTargetNumbers: MutableList<Int> = kotlin.collections.ArrayList()
private val mPrimaryNumbers: MutableList<Int> = kotlin.collections.ArrayList()
private val mScrollNumbers: MutableList<ScrollNumber> = kotlin.collections.ArrayList()
private var mTextSize = 130
private var mTextColors = intArrayOf(R.color.color_ff2422)
private var mInterpolator: Interpolator = AccelerateDecelerateInterpolator()
private var mFontFileName: String? = null
private var mTypeFace: Typeface? = null
private var mVelocity = 15
init {
context.withStyledAttributes(attrs, R.styleable.MultiScrollNumber) {
val primaryNumber = getInteger(R.styleable.MultiScrollNumber_primary_number, 0)
val targetNumber = getInteger(R.styleable.MultiScrollNumber_target_number, 0)
val numberSize = getInteger(R.styleable.MultiScrollNumber_number_size, 130)
setNumber(primaryNumber, targetNumber)
setTextSize(numberSize)
}
orientation = HORIZONTAL
gravity = Gravity.CENTER
}
fun setNumber(str: String, scroll: Boolean = true) {
require(isNumeric(str)) { "number value should >= 0" }
resetView()
val charArray = str.toCharArray()
for (i in charArray.indices.reversed()) {
if (Character.isDigit(charArray[i])) {
mTargetNumbers.add(charArray[i].code - '0'.code)
} else {
mTargetNumbers.add(-1)
}
}
for (i in mTargetNumbers.indices.reversed()) {
// for (int i = 0; i < mTargetNumbers.size(); i++) {
if (mTargetNumbers[i] != -1) {
val scrollNumber = ScrollNumber(context)
scrollNumber.setScrollable(scroll)
scrollNumber.setTextColor(
ContextCompat
.getColor(context, mTextColors[i % mTextColors.size])
)
scrollNumber.setVelocity(mVelocity * (i + 1))
scrollNumber.setTextSize(mTextSize)
scrollNumber.setInterpolator(mInterpolator)
if (!TextUtils.isEmpty(mFontFileName)) scrollNumber.setTextFont(mFontFileName)
if (mTypeFace != null) {
scrollNumber.setTextFont(mTypeFace)
}
scrollNumber.setNumber((mTargetNumbers[i] + 1) % 10, mTargetNumbers[i], 0)
mScrollNumbers.add(scrollNumber)
addView(scrollNumber)
} else {
val params = ViewGroup.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT)
val point = TextView(context)
point.text = "."
point.setGravity(Gravity.BOTTOM)
point.setPadding(0, 0, 0, dp2px(10f))
point.setTextColor(
ContextCompat
.getColor(context, mTextColors[i % mTextColors.size])
)
point.textSize = mTextSize.toFloat()
if (!TextUtils.isEmpty(mFontFileName)) {
val mTypeface = Typeface.createFromAsset(context.assets, mFontFileName)
point.setTypeface(mTypeface)
} else {
point.typeface = mTypeFace
}
addView(point, params)
}
}
val params = LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT)
val unit = TextView(context)
unit.text = ""
unit.setGravity(Gravity.BOTTOM)
params.bottomMargin = dp2px(3f)
unit.setPadding(0, 0, 0, dp2px(10f))
unit.textSize = 20f
unit.setTextColor(getColor(R.color.color_ff2422))
if (!TextUtils.isEmpty(mFontFileName)) {
val mTypeface = Typeface.createFromAsset(context.assets, mFontFileName)
unit.setTypeface(mTypeface)
} else {
unit.typeface = mTypeFace
}
addView(unit, params)
}
fun setNumber(num: Int, scroll: Boolean = true) {
resetView()
var number = num
while (number > 0) {
val i = number % 10
mTargetNumbers.add(i)
number /= 10
}
for (i in mTargetNumbers.indices.reversed()) {
val scrollNumber = ScrollNumber(context)
scrollNumber.setScrollable(scroll)
scrollNumber.setTextColor(
ContextCompat
.getColor(context, mTextColors[i % mTextColors.size])
)
scrollNumber.setVelocity(mVelocity * (i + 1))
scrollNumber.setTextSize(mTextSize)
scrollNumber.setInterpolator(mInterpolator)
if (!TextUtils.isEmpty(mFontFileName)) scrollNumber.setTextFont(mFontFileName)
if (mTypeFace != null) {
scrollNumber.setTextFont(mTypeFace)
}
scrollNumber.setNumber((mTargetNumbers[i] + 1) % 10, mTargetNumbers[i], 0)
mScrollNumbers.add(scrollNumber)
addView(scrollNumber)
}
val params = LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT)
val unit = TextView(context)
unit.text = ""
unit.setGravity(Gravity.BOTTOM)
params.bottomMargin = dp2px(3f)
unit.setPadding(0, 0, 0, dp2px(10f))
unit.textSize = 20f
unit.setTextColor(getColor(R.color.color_ff2422))
if (!TextUtils.isEmpty(mFontFileName)) {
val mTypeface = Typeface.createFromAsset(context.assets, mFontFileName)
unit.setTypeface(mTypeface)
} else {
unit.typeface = mTypeFace
}
addView(unit, params)
}
private fun resetView() {
mTargetNumbers.clear()
mScrollNumbers.clear()
removeAllViews()
}
fun setNumber(from: Int, to: Int, scroll: Boolean = true) {
if (to < from) throw kotlin.UnsupportedOperationException("'to' value must > 'from' value")
resetView()
// operate to
var number = to
var count = 0
while (number > 0) {
val i = number % 10
mTargetNumbers.add(i)
number /= 10
count++
}
// operate from
number = from
while (count > 0) {
val i = number % 10
mPrimaryNumbers.add(i)
number /= 10
count--
}
for (i in mTargetNumbers.indices.reversed()) {
val scrollNumber = ScrollNumber(context)
scrollNumber.setScrollable(scroll)
scrollNumber.setTextColor(
ContextCompat
.getColor(context, mTextColors[i % mTextColors.size])
)
scrollNumber.setTextSize(mTextSize)
if (!TextUtils.isEmpty(mFontFileName)) scrollNumber.setTextFont(mFontFileName)
if (mTypeFace != null) {
scrollNumber.setTextFont(mTypeFace)
}
scrollNumber.setNumber(mPrimaryNumbers[i], mTargetNumbers[i], (i * 10).toLong())
mScrollNumbers.add(scrollNumber)
addView(scrollNumber)
}
}
fun setTextColors(@ColorRes textColors: IntArray?) {
require(!(textColors == null || textColors.isEmpty())) { "color array couldn't be empty!" }
mTextColors = textColors
for (i in mScrollNumbers.indices.reversed()) {
val scrollNumber = mScrollNumbers[i]
scrollNumber.setTextColor(
ContextCompat
.getColor(context, mTextColors[i % mTextColors.size])
)
}
}
fun setTextSize(textSize: Int) {
require(textSize > 0) { "text size must > 0!" }
mTextSize = textSize
for (s in mScrollNumbers) {
s.setTextSize(textSize)
}
}
fun setInterpolator(interpolator: Interpolator?) {
if (interpolator == null) throw kotlin.IllegalArgumentException("interpolator couldn't be null")
mInterpolator = interpolator
for (s in mScrollNumbers) {
s.setInterpolator(interpolator)
}
}
fun setTextFont(fileName: String?) {
if (TextUtils.isEmpty(fileName)) throw kotlin.IllegalArgumentException("file name is null")
mFontFileName = fileName
for (s in mScrollNumbers) {
s.setTextFont(fileName)
}
}
fun setTextFont(typeface: Typeface?) {
mTypeFace = typeface
for (s in mScrollNumbers) {
s.setTextFont(mTypeFace)
}
}
fun setScrollVelocity(@IntRange(from = 0, to = 1000) velocity: Int) {
mVelocity = velocity
for (s in mScrollNumbers) {
s.setVelocity(velocity)
}
}
private fun dp2px(dpVal: Float): Int {
return TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
dpVal, resources.displayMetrics
).toInt()
}
private fun sp2px(dpVal: Float): Int {
return TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_SP,
dpVal, resources.displayMetrics
).toInt()
}
companion object {
fun isNumeric(str: String?): Boolean {
if (TextUtils.isEmpty(str)) return false
val pattern = Pattern.compile("[0-9]*\\.?[0-9]+")
val isNum = pattern.matcher(str!!)
return isNum.matches()
}
}
}

View File

@ -0,0 +1,242 @@
package com.devcon.audi.view
import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.Rect
import android.graphics.Typeface
import android.text.TextUtils
import android.util.AttributeSet
import android.util.TypedValue
import android.view.View
import android.view.animation.AccelerateDecelerateInterpolator
import android.view.animation.Interpolator
import androidx.annotation.IntRange
import kotlin.math.min
/**
* @Author zhengdaquan
* @Date 2024/10/27 15:25
* @Describe
*/
class ScrollNumber @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0) : View(context, attrs, defStyleAttr) {
/**
* number to - number from
*/
private var mDeltaNum = 0
/**
* the current showing number
*/
private var mCurNum = 0
/**
* the next showing number
*/
private var mNextNum = 0
/**
* the target number
*/
private var mTargetNum = 0
/**
* number offset
*/
private var mOffset = 0f
private val mPaint: Paint
private var mInterpolator: Interpolator = AccelerateDecelerateInterpolator()
private var mTextCenterX = 0f
private var mTextHeight = 0
private val mTextBounds = Rect()
private var mTextSize = sp2px(130f)
private var mTextColor = -0x1000000
private var mTypeface: Typeface? = null
private var mVelocity = DEFAULT_VELOCITY
private var mScrollable = true
fun setVelocity(@IntRange(from = 0, to = 1000) velocity: Int) {
mVelocity = velocity
}
fun setNumber(from: Int, to: Int, delay: Long) {
postDelayed({
setFromNumber(from)
setTargetNumber(to)
mDeltaNum = to - from
}, delay)
}
fun setTextSize(textSize: Int) {
mTextSize = sp2px(textSize.toFloat())
mPaint.textSize = mTextSize.toFloat()
measureTextHeight()
requestLayout()
invalidate()
}
fun setTextFont(fileName: String?) {
require(!TextUtils.isEmpty(fileName)) { "please check file name end with '.ttf' or '.otf'" }
mTypeface = Typeface.createFromAsset(context.assets, fileName)
if (mTypeface == null) throw kotlin.RuntimeException("please check your font!")
mPaint.setTypeface(mTypeface)
requestLayout()
invalidate()
}
fun setTextFont(typeface: Typeface?) {
mTypeface = typeface
if (mTypeface == null) throw kotlin.RuntimeException("please check your font!")
mPaint.setTypeface(mTypeface)
requestLayout()
invalidate()
}
fun setTextColor(mTextColor: Int) {
this.mTextColor = mTextColor
mPaint.setColor(mTextColor)
invalidate()
}
fun setInterpolator(interpolator: Interpolator) {
mInterpolator = interpolator
}
private fun measureTextHeight() {
mPaint.getTextBounds(mCurNum.toString() + "", 0, 1, mTextBounds)
mTextHeight = mTextBounds.height()
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
val width = measureWidth(widthMeasureSpec)
val height = measureHeight(heightMeasureSpec)
setMeasuredDimension(width, height)
mTextCenterX = (measuredWidth - getPaddingLeft() - getPaddingRight() ushr 1).toFloat()
}
private fun measureHeight(measureSpec: Int): Int {
val mode = MeasureSpec.getMode(measureSpec)
val `val` = MeasureSpec.getSize(measureSpec)
var result = 0
when (mode) {
MeasureSpec.EXACTLY -> result = `val`
MeasureSpec.AT_MOST, MeasureSpec.UNSPECIFIED -> {
mPaint.getTextBounds("0", 0, 1, mTextBounds)
result = mTextBounds.height()
}
}
result = if (mode == MeasureSpec.AT_MOST) min(result.toDouble(), `val`.toDouble()).toInt() else result
return result + paddingTop + paddingBottom + dp2px(40f)
}
private fun measureWidth(measureSpec: Int): Int {
val mode = MeasureSpec.getMode(measureSpec)
val `val` = MeasureSpec.getSize(measureSpec)
var result = 0
when (mode) {
MeasureSpec.EXACTLY -> result = `val`
MeasureSpec.AT_MOST, MeasureSpec.UNSPECIFIED -> {
mPaint.getTextBounds("0", 0, 1, mTextBounds)
result = mTextBounds.width()
}
}
result = if (mode == MeasureSpec.AT_MOST) min(result.toDouble(), `val`.toDouble()).toInt() else result
return result + getPaddingLeft() + getPaddingRight() + 15
}
override fun onDraw(canvas: Canvas) {
if (mScrollable) {
if (mCurNum != mTargetNum) {
postDelayed(mScrollRunnable, 0)
}
// Log.d(TAG, "onDraw: curr=" + mCurNum + " target=" + mTargetNum + " offset=" + mOffset);
canvas.translate(0f, mOffset * measuredHeight)
drawSelf(canvas)
drawNext(canvas)
// canvas.restore();
} else {
val y = measuredHeight / 2
canvas.drawText(mTargetNum.toString() + "", mTextCenterX, (y + mTextHeight / 2).toFloat(), mPaint)
}
}
private fun setFromNumber(number: Int) {
if (number < 0 || number > 9) throw kotlin.RuntimeException("invalidate number , should in [0,9]")
calNum(number)
mOffset = 0f
invalidate()
}
private fun calNum(num: Int) {
var number = num
number = if (number == -1) 9 else number
number = if (number == 10) 0 else number
mCurNum = number
mNextNum = if (number + 1 == 10) 0 else number + 1
}
private val mScrollRunnable = Runnable {
val x = (1 - 1.0 * (mTargetNum - mCurNum) / mDeltaNum).toFloat()
// mOffset -= 0.15f * (1 - mInterpolator.getInterpolation(x) + 0.1);
mOffset -= (mVelocity * 0.01f * (1 - mInterpolator.getInterpolation(x) + 0.1)).toFloat()
invalidate()
if (mOffset <= -1) {
mOffset = 0f
calNum(mCurNum + 1)
}
}
init {
mPaint = Paint(Paint.ANTI_ALIAS_FLAG)
mPaint.textAlign = Paint.Align.CENTER
mPaint.textSize = mTextSize.toFloat()
mPaint.setColor(mTextColor)
if (mTypeface != null) mPaint.setTypeface(mTypeface)
measureTextHeight()
}
private fun drawNext(canvas: Canvas) {
val y = (measuredHeight * 1.5).toFloat()
canvas.drawText(mNextNum.toString() + "", mTextCenterX, y + mTextHeight / 2, mPaint)
}
private fun drawSelf(canvas: Canvas) {
val y = measuredHeight / 2
canvas.drawText(mCurNum.toString() + "", mTextCenterX, (y + mTextHeight / 2).toFloat(), mPaint)
}
fun setTargetNumber(nextNum: Int) {
mTargetNum = nextNum
invalidate()
}
fun setScrollable(scroll: Boolean) {
mScrollable = scroll
}
private fun dp2px(dpVal: Float): Int {
return TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
dpVal, resources.displayMetrics
).toInt()
}
private fun sp2px(dpVal: Float): Int {
return TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_SP,
dpVal, resources.displayMetrics
).toInt()
}
companion object {
const val TAG = "ScrollNumber"
/**
* default animation velocity
*/
const val DEFAULT_VELOCITY = 15
}
}

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<bitmap android:src="@mipmap/ic_coupon_dialog_bg_checked" />
</item>
<item
android:width="@dimen/dp_46"
android:height="@dimen/dp_46"
android:gravity="top|end">
<bitmap android:src="@mipmap/ic_coupon_dialog_checked_arrow" />
</item>
<item
android:width="@dimen/dp_16"
android:height="@dimen/dp_16"
android:end="@dimen/dp_6"
android:gravity="top|end"
android:top="@dimen/dp_9">
<bitmap android:src="@mipmap/ic_coupon_dialog_checked_right" />
</item>
</layer-list>

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:left="-300dp"
android:right="-300dp">
<rotate
android:fromDegrees="90"
android:visible="true">
<shape android:shape="line">
<stroke
android:width="@dimen/dp_2"
android:color="#FF827D"
android:dashWidth="@dimen/dp_3"
android:dashGap="@dimen/dp_3" />
</shape>
</rotate>
</item>
</layer-list>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/white" />
<corners
android:topLeftRadius="@dimen/dp_30"
android:topRightRadius="@dimen/dp_30" />
</shape>

View File

@ -0,0 +1,97 @@
<?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">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/layout_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipChildren="false"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_bg1"
android:layout_width="535dp"
android:layout_height="535dp"
android:src="@mipmap/ic_activity_coupon_anim1"
android:visibility="invisible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="h,1200:1203"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_bg2"
android:layout_width="421dp"
android:layout_height="421dp"
android:src="@mipmap/ic_activity_coupon_anim2"
android:visibility="invisible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="h,1200:1203"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_close"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_40"
android:layout_marginEnd="@dimen/dp_40"
android:src="@mipmap/ic_close_dialog2"
android:visibility="invisible"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/dp_30"
android:text="1800元大促优惠券"
android:textColor="#FFEAC9"
android:shadowColor="#EB2A35"
android:shadowDy="3"
android:shadowRadius="1"
android:textSize="@dimen/sp_28"
app:layout_constraintBottom_toTopOf="@id/mRecyclerView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/mRecyclerView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dp_20"
android:layout_marginTop="@dimen/dp_40"
android:layout_marginEnd="@dimen/dp_20"
android:layout_marginBottom="@dimen/dp_20"
android:orientation="horizontal"
android:overScrollMode="never"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.497"
tools:itemCount="3"
tools:listitem="@layout/listitem_activity_coupon" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_40"
android:src="@mipmap/ic_activity_coupon_btn"
android:visibility="invisible"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/mRecyclerView" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,154 @@
<?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">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_effect1_bg"
android:layout_width="match_parent"
android:layout_height="0dp"
android:scaleType="fitXY"
android:src="@mipmap/ic_goods_coupon_bg"
android:visibility="invisible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="h,1125:320"
app:layout_constraintTop_toTopOf="parent"
tools:visibility="visible" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_effect1_fg"
android:layout_width="match_parent"
android:layout_height="0dp"
android:scaleType="fitXY"
android:src="@mipmap/ic_goods_coupon_fg"
android:visibility="invisible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="h,1125:245"
app:layout_constraintTop_toTopOf="parent"
tools:visibility="visible" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_effect1_desc"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginStart="@dimen/dp_50"
android:layout_marginEnd="@dimen/dp_50"
android:src="@mipmap/ic_goods_coupon_desc"
android:visibility="invisible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="h,963:174"
app:layout_constraintTop_toTopOf="parent"
tools:visibility="visible" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_effect1_light1"
android:layout_width="194dp"
android:layout_height="60dp"
android:layout_marginStart="-30dp"
android:layout_marginTop="-30dp"
android:alpha="0.5"
android:src="@mipmap/ic_goods_coupon_light"
android:visibility="invisible"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/iv_effect1_bg"
tools:visibility="visible" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_effect1_star1"
android:layout_width="43dp"
android:layout_height="43dp"
android:layout_marginStart="-30dp"
android:layout_marginBottom="@dimen/dp_5"
android:alpha="0.5"
android:src="@mipmap/ic_goods_coupon_star"
android:visibility="invisible"
app:layout_constraintBottom_toBottomOf="@id/iv_effect1_light1"
app:layout_constraintStart_toEndOf="@id/iv_effect1_light1"
app:layout_constraintTop_toTopOf="@id/iv_effect1_light1"
tools:visibility="visible" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_effect1_light2"
android:layout_width="194dp"
android:layout_height="60dp"
android:layout_marginStart="-30dp"
android:layout_marginTop="-10dp"
android:layout_marginEnd="@dimen/dp_20"
android:alpha="0.5"
android:src="@mipmap/ic_goods_coupon_light"
android:visibility="invisible"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/iv_effect1_bg"
tools:visibility="visible" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_effect1_star2"
android:layout_width="43dp"
android:layout_height="43dp"
android:layout_marginStart="-30dp"
android:layout_marginBottom="@dimen/dp_5"
android:alpha="0.5"
android:src="@mipmap/ic_goods_coupon_star"
android:visibility="invisible"
app:layout_constraintBottom_toBottomOf="@id/iv_effect1_light2"
app:layout_constraintStart_toEndOf="@id/iv_effect1_light2"
app:layout_constraintTop_toTopOf="@id/iv_effect1_light2"
tools:visibility="visible" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_effect1_light3"
android:layout_width="194dp"
android:layout_height="60dp"
android:layout_marginStart="-80dp"
android:layout_marginBottom="-20dp"
android:alpha="0.5"
android:src="@mipmap/ic_goods_coupon_light"
android:visibility="invisible"
app:layout_constraintBottom_toBottomOf="@id/iv_effect1_bg"
app:layout_constraintStart_toStartOf="parent"
tools:visibility="visible" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_effect1_star3"
android:layout_width="43dp"
android:layout_height="43dp"
android:layout_marginStart="-30dp"
android:layout_marginBottom="@dimen/dp_5"
android:alpha="0.5"
android:src="@mipmap/ic_goods_coupon_star"
android:visibility="invisible"
app:layout_constraintBottom_toBottomOf="@id/iv_effect1_light3"
app:layout_constraintStart_toEndOf="@id/iv_effect1_light3"
app:layout_constraintTop_toTopOf="@id/iv_effect1_light3"
tools:visibility="visible" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_effect1_light4"
android:layout_width="194dp"
android:layout_height="60dp"
android:layout_marginEnd="70dp"
android:layout_marginBottom="-36dp"
android:alpha="0.5"
android:src="@mipmap/ic_goods_coupon_light"
android:visibility="invisible"
app:layout_constraintBottom_toBottomOf="@id/iv_effect1_bg"
app:layout_constraintEnd_toEndOf="parent"
tools:visibility="visible" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_effect1_star4"
android:layout_width="43dp"
android:layout_height="43dp"
android:layout_marginStart="-30dp"
android:layout_marginBottom="@dimen/dp_5"
android:alpha="0.5"
android:src="@mipmap/ic_goods_coupon_star"
android:visibility="invisible"
app:layout_constraintBottom_toBottomOf="@id/iv_effect1_light4"
app:layout_constraintStart_toEndOf="@id/iv_effect1_light4"
app:layout_constraintTop_toTopOf="@id/iv_effect1_light4"
tools:visibility="visible" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,134 @@
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/layout_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="invisible">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_bg"
android:layout_width="893dp"
android:layout_height="972dp"
android:src="@mipmap/ic_red_packet_anim"
android:visibility="invisible"
android:layout_marginEnd="@dimen/dp_38"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_red_packet"
android:layout_width="272dp"
android:layout_height="371dp"
android:layout_marginBottom="@dimen/dp_50"
android:src="@mipmap/ic_red_packet2"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="115dp"
android:text="恭喜获得红包"
android:textColor="#B56112"
android:textSize="@dimen/sp_18"
app:layout_constraintEnd_toEndOf="@id/iv_red_packet"
app:layout_constraintStart_toStartOf="@id/iv_red_packet"
app:layout_constraintTop_toTopOf="@id/iv_red_packet" />
<com.cheng.blzb.widget.MultiScrollNumber
android:id="@+id/tv_discount_amount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:number_size="60"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_title" />
<TextView
android:id="@+id/tv_threshold_amount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="满200元可用"
android:textColor="#FF9837"
android:textSize="@dimen/sp_16"
app:layout_constraintEnd_toEndOf="@id/iv_red_packet"
app:layout_constraintStart_toStartOf="@id/iv_red_packet"
app:layout_constraintTop_toBottomOf="@id/tv_discount_amount" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_coin1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="-7dp"
android:layout_marginBottom="43dp"
android:src="@mipmap/ic_red_packet_coin1"
android:visibility="invisible"
app:layout_constraintBottom_toBottomOf="@id/iv_red_packet"
app:layout_constraintEnd_toEndOf="@id/iv_red_packet" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_coin2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="-16dp"
android:layout_marginBottom="108dp"
android:src="@mipmap/ic_red_packet_coin2"
android:visibility="invisible"
app:layout_constraintBottom_toBottomOf="@id/iv_red_packet"
app:layout_constraintStart_toStartOf="@id/iv_red_packet" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_coin3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="-16dp"
android:layout_marginTop="57dp"
android:src="@mipmap/ic_red_packet_coin3"
android:visibility="invisible"
app:layout_constraintStart_toStartOf="@id/iv_red_packet"
app:layout_constraintTop_toTopOf="@id/iv_red_packet" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_coin4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="103dp"
android:layout_marginEnd="-36dp"
android:src="@mipmap/ic_red_packet_coin4"
android:visibility="invisible"
app:layout_constraintEnd_toEndOf="@id/iv_red_packet"
app:layout_constraintTop_toTopOf="@id/iv_red_packet" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_btn_next"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/dp_5"
android:src="@mipmap/ic_red_packet_btn2"
app:layout_constraintBottom_toBottomOf="@id/iv_red_packet"
app:layout_constraintEnd_toEndOf="@id/iv_red_packet"
app:layout_constraintStart_toStartOf="@id/iv_red_packet" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_close"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_close_dialog2"
android:layout_marginTop="@dimen/dp_40"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/iv_red_packet" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,82 +1,113 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/shape_fbfbfd_top_cor14">
android:layout_height="wrap_content">
<androidx.constraintlayout.widget.ConstraintLayout
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_close"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/dp_20"
android:layout_marginTop="@dimen/dp_10"
android:src="@mipmap/ic_close_dialog2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_top_bg"
android:layout_width="match_parent"
android:layout_height="520dp">
android:layout_height="0dp"
android:layout_marginStart="@dimen/dp_12"
android:layout_marginEnd="@dimen/dp_12"
app:layout_constraintTop_toBottomOf="@id/iv_close"
android:layout_marginTop="@dimen/dp_40"
android:background="@mipmap/ic_coupon_dialog_top"
app:layout_constraintDimensionRatio="h,1053:390" />
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_18"
android:text="优惠券"
android:textColor="@color/color_1a1a1a"
android:textSize="@dimen/sp_16"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dp_16"
android:layout_marginTop="@dimen/dp_11"
android:text="使用现金红包"
android:textColor="#790C0C"
android:textSize="@dimen/sp_22"
app:layout_constraintStart_toStartOf="@id/iv_top_bg"
app:layout_constraintTop_toTopOf="@id/iv_top_bg" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_close"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/dp_12"
android:src="@mipmap/ic_close"
app:layout_constraintBottom_toBottomOf="@id/tv_title"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/tv_title" />
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/dp_5"
android:layout_marginTop="-5dp"
android:src="@mipmap/ic_coupon_dialog_indicator"
app:layout_constraintEnd_toEndOf="@id/tv_title"
app:layout_constraintTop_toBottomOf="@id/tv_title" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/mRecyclerView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="@dimen/dp_12"
app:layout_constraintVertical_weight="1"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toTopOf="@id/layout_bottom"
app:layout_constraintTop_toBottomOf="@id/tv_title"
tools:listitem="@layout/listitem_coupon_dialog" />
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_6"
android:src="@mipmap/ic_coupon_dialog_icon"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/iv_close" />
<View
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:background="@color/color_eeeeee"
app:layout_constraintBottom_toTopOf="@id/layout_bottom" />
<FrameLayout
android:id="@+id/layout_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_22"
android:background="@drawable/shape_white_top_cor30"
app:layout_constraintTop_toBottomOf="@id/tv_title">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/layout_bottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:paddingBottom="@dimen/dp_9"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent">
android:layout_height="420dp">
<com.cheng.blzb.widget.CommonShapeView
android:id="@+id/btn_next"
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/mRecyclerView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginStart="@dimen/dp_16"
android:layout_marginTop="@dimen/dp_9"
android:layout_marginEnd="@dimen/dp_16"
android:text="确定"
android:textColor="@color/white"
android:textSize="@dimen/sp_15"
android:textStyle="bold"
app:csb_activeEnable="true"
app:csb_cornerRadius="@dimen/dp_50"
app:csb_fillColor="@color/color_ff5846"
app:layout_constraintDimensionRatio="h,343:46"
app:layout_constraintTop_toTopOf="parent" />
android:layout_marginTop="@dimen/dp_6"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toTopOf="@id/layout_bottom"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_weight="1"
tools:listitem="@layout/listitem_coupon_dialog" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/layout_bottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="@dimen/dp_30"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent">
<com.cheng.blzb.widget.CommonShapeView
android:id="@+id/btn_next"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginStart="@dimen/dp_16"
android:layout_marginTop="@dimen/dp_9"
android:layout_marginEnd="@dimen/dp_16"
android:text="确定"
android:textColor="@color/white"
android:textSize="@dimen/sp_15"
android:textStyle="bold"
app:csb_activeEnable="true"
app:csb_cornerRadius="@dimen/dp_50"
app:csb_orientation="LEFT_RIGHT"
app:csb_startColor="#FF775B"
app:csb_endColor="#F34D44"
app:layout_constraintDimensionRatio="h,343:46"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -208,4 +208,24 @@
</androidx.coordinatorlayout.widget.CoordinatorLayout>
<org.libpag.PAGImageView
android:id="@+id/pv_coupon_activity"
android:layout_width="@dimen/dp_76"
android:layout_height="@dimen/dp_76"
android:layout_marginBottom="@dimen/dp_200"
android:visibility="gone"
android:clickable="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<org.libpag.PAGImageView
android:id="@+id/pv_goods_coupon"
android:layout_width="@dimen/dp_76"
android:layout_height="@dimen/dp_76"
android:layout_marginBottom="@dimen/dp_200"
android:visibility="gone"
android:clickable="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -323,87 +323,44 @@
</androidx.constraintlayout.widget.ConstraintLayout>
<LinearLayout
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/layout_coupon_redpacket"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_height="@dimen/dp_44"
android:layout_marginTop="@dimen/dp_12"
android:layout_marginEnd="@dimen/dp_12"
android:background="@drawable/shape_vip_coupon_bg"
android:orientation="vertical"
android:visibility="gone"
app:layout_constraintTop_toBottomOf="@id/layout_seat"
app:layout_goneMarginTop="@dimen/dp_42">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/layout_coupon"
android:layout_width="match_parent"
android:layout_height="@dimen/dp_44">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dp_12"
android:drawableStart="@mipmap/ic_vip_redpacket"
android:drawablePadding="@dimen/dp_8"
android:gravity="center"
android:text="现金红包"
android:textColor="@color/white"
android:textSize="@dimen/sp_14"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dp_12"
android:drawableStart="@mipmap/ic_vip_coupon"
android:drawablePadding="@dimen/dp_8"
android:gravity="center"
android:text="折扣优惠券"
android:textColor="@color/white"
android:textSize="@dimen/sp_14"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/dp_6"
android:drawableEnd="@mipmap/ic_arrow_dp16"
android:text="暂无可用的优惠券"
android:textColor="@color/color_fffaef"
android:textSize="@dimen/sp_12"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<View
android:layout_width="match_parent"
android:layout_height="@dimen/dp_1"
android:background="#39443F" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/layout_red_packet"
android:layout_width="match_parent"
android:layout_height="@dimen/dp_44">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dp_12"
android:drawableStart="@mipmap/ic_vip_redpacket"
android:drawablePadding="@dimen/dp_8"
android:gravity="center"
android:text="现金红包"
android:textColor="@color/white"
android:textSize="@dimen/sp_14"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/dp_6"
android:drawableEnd="@mipmap/ic_arrow_dp16"
android:text="暂无可用的红包"
android:textColor="@color/color_fffaef"
android:textSize="@dimen/sp_12"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
<TextView
android:id="@+id/tv_coupon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/dp_6"
android:drawableEnd="@mipmap/ic_arrow_dp16"
android:text="暂无可用的红包"
android:textColor="@color/color_fffaef"
android:textSize="@dimen/sp_12"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<TextView
android:id="@+id/tv_wx_pay"

View File

@ -0,0 +1,54 @@
<?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"
android:layout_width="@dimen/dp_100"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dp_6"
android:layout_marginEnd="@dimen/dp_6"
android:background="@mipmap/ic_activity_coupon_bg"
android:visibility="invisible">
<TextView
android:id="@+id/tv_discount_amount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_16"
android:gravity="center"
android:text="¥10"
android:textColor="@color/color_ef2833"
android:textSize="@dimen/sp_30"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_4"
android:background="@drawable/shape_10fb7528_cor2"
android:fontFamily="sans-serif-medium"
android:text="现金券"
android:textColor="@color/color_ef2833"
android:textSize="@dimen/sp_10"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_discount_amount" />
<TextView
android:id="@+id/tv_threshold_amount"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_17"
android:layout_marginBottom="@dimen/dp_14"
android:fontFamily="sans-serif-medium"
android:gravity="center"
android:text="满500减"
android:textColor="@color/color_ef2833"
android:textSize="@dimen/sp_13"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_type" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,61 +1,73 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView 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"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dp_20"
android:layout_marginTop="@dimen/dp_2"
android:layout_marginEnd="@dimen/dp_20"
android:layout_marginBottom="@dimen/dp_8"
android:elevation="@dimen/dp_1"
app:cardCornerRadius="@dimen/dp_8">
android:layout_height="@dimen/dp_80"
android:layout_marginStart="@dimen/dp_12"
android:layout_marginTop="@dimen/dp_14"
android:layout_marginEnd="@dimen/dp_12"
android:background="@mipmap/ic_coupon_dialog_bg_default">
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/layout_amount"
android:layout_width="0dp"
android:layout_height="0dp"
android:gravity="center"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_percent="0.27">
<TextView
android:id="@+id/tv_discount_amount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="¥100"
android:textColor="@color/color_f03d36"
android:textSize="@dimen/sp_24" />
<TextView
android:id="@+id/tv_threshold_amount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_6"
android:text="满999可用"
android:visibility="gone"
android:textColor="@color/color_f03d36"
android:textSize="@dimen/sp_12" />
</androidx.appcompat.widget.LinearLayoutCompat>
<View
android:layout_width="@dimen/dp_1"
android:layout_height="@dimen/dp_54"
android:background="@drawable/shape_ff827d_dash_divider_v"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/layout_info"
app:layout_constraintStart_toEndOf="@id/layout_amount"
app:layout_constraintTop_toTopOf="parent" />
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/dp_4">
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/layout_amount"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="@drawable/shape_fdf4f2_cor6"
android:gravity="center"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="w,1:1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/tv_discount_amount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="¥100"
android:textColor="@color/color_ff5846"
android:textSize="@dimen/sp_24" />
<TextView
android:id="@+id/tv_threshold_amount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_6"
android:text="满999可用"
android:textColor="@color/color_ff5846"
android:textSize="@dimen/sp_12" />
</androidx.appcompat.widget.LinearLayoutCompat>
android:id="@+id/layout_info"
android:layout_width="0dp"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/layout_amount"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dp_10"
android:layout_marginTop="@dimen/dp_8"
android:layout_marginStart="@dimen/dp_20"
android:layout_marginTop="@dimen/dp_18"
android:text="满减现金券"
android:textColor="@color/color_1a1a1a"
android:textSize="@dimen/sp_15"
android:textStyle="bold"
app:layout_constraintStart_toEndOf="@id/layout_amount"
android:textSize="@dimen/sp_16"
android:fontFamily="sans-serif-medium"
app:layout_constraintBottom_toTopOf="@id/tv_expire_time"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
@ -63,39 +75,14 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_4"
android:layout_marginBottom="@dimen/dp_18"
android:text="有效期至 2024.09.25"
android:textColor="@color/color_999999"
android:textSize="@dimen/sp_12"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="@id/tv_name"
app:layout_constraintTop_toBottomOf="@id/tv_name" />
<TextView
android:id="@+id/tv_type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_10"
android:layout_marginBottom="@dimen/dp_8"
android:background="@drawable/shape_10fb7528_cor2"
android:paddingStart="@dimen/dp_4"
android:paddingTop="@dimen/dp_2"
android:paddingEnd="@dimen/dp_4"
android:paddingBottom="@dimen/dp_2"
android:text="现金券"
android:textColor="@color/color_fb7528"
android:textSize="@dimen/sp_10"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="@id/tv_name"
app:layout_constraintTop_toBottomOf="@id/tv_expire_time" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_check"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/dp_12"
android:src="@mipmap/ic_coupon_check_false"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,54 @@
<?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"
android:layout_width="@dimen/dp_100"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dp_6"
android:layout_marginEnd="@dimen/dp_6"
android:background="@mipmap/ic_activity_coupon_bg"
android:visibility="invisible">
<TextView
android:id="@+id/tv_discount_amount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_16"
android:gravity="center"
android:text="¥10"
android:textColor="@color/color_ef2833"
android:textSize="@dimen/sp_30"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_4"
android:background="@drawable/shape_10fb7528_cor2"
android:fontFamily="sans-serif-medium"
android:text="现金券"
android:textColor="@color/color_ef2833"
android:textSize="@dimen/sp_10"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_discount_amount" />
<TextView
android:id="@+id/tv_threshold_amount"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_17"
android:layout_marginBottom="@dimen/dp_14"
android:fontFamily="sans-serif-medium"
android:gravity="center"
android:text="满500减"
android:textColor="@color/color_ef2833"
android:textSize="@dimen/sp_13"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_type" />
</androidx.constraintlayout.widget.ConstraintLayout>

Binary file not shown.

After

Width:  |  Height:  |  Size: 977 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 876 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 800 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 538 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 189 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 211 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 596 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -44,4 +44,12 @@
<enum name="LEFT_RIGHT" value="1" />
</attr>
</declare-styleable>
<!--MultiScrollNumber-->
<declare-styleable name="MultiScrollNumber">
<attr name="primary_number" format="integer" />
<attr name="target_number" format="integer" />
<attr name="number_size" format="integer" />
<!--<attr name="number_color" format="color"/>-->
</declare-styleable>
</resources>

View File

@ -70,7 +70,7 @@
<color name="color_727686">#727686</color>
<color name="color_676e87">#676E87</color>
<color name="color_54230c">#54230C</color>
<color name="color_f94747">#F94747</color>
<color name="color_f03d36">#F03D36</color>
<color name="color_896451">#896451</color>
<color name="color_54220b">#54220B</color>
<color name="color_d5dae5">#D5DAE5</color>
@ -136,4 +136,8 @@
<color name="color_05ace8">#05ACE8</color>
<color name="color_6dd9f2">#6DD9F2</color>
<color name="color_e6ffff">#E6FFFF</color>
<color name="color_ff2422">#FF2422</color>
<color name="color_ef2833">#EF2833</color>
<color name="color_848484">#848484</color>
<color name="color_a1a1a1">#A1A1A1</color>
</resources>

View File

@ -93,5 +93,6 @@
<dimen name="dp_190">190dp</dimen>
<dimen name="dp_180">180dp</dimen>
<dimen name="dp_280">280dp</dimen>
<dimen name="sp_28">28sp</dimen>
</resources>