diff --git a/app/build.gradle b/app/build.gradle index 0903507..c965dcc 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -20,8 +20,8 @@ android { applicationId "com.cheng.BoLe" minSdk 26 targetSdk 34 - versionCode 273 - versionName "2.7.3" + versionCode 280 + versionName "2.8.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables { diff --git a/app/src/main/java/com/cheng/blzb/net/ApiService.kt b/app/src/main/java/com/cheng/blzb/net/ApiService.kt index 3c62576..314c8a3 100644 --- a/app/src/main/java/com/cheng/blzb/net/ApiService.kt +++ b/app/src/main/java/com/cheng/blzb/net/ApiService.kt @@ -15,7 +15,6 @@ import com.cheng.blzb.bean.LoginEntity import com.cheng.blzb.bean.MerchantGoodsEntity import com.cheng.blzb.bean.OrderEntity import com.cheng.blzb.bean.OrderPayEntity -import com.cheng.blzb.bean.ZZDBInfoEntity import com.cheng.blzb.bean.SeatItemEntity import com.cheng.blzb.bean.SendCodeEntity import com.cheng.blzb.bean.SourceEntity @@ -27,6 +26,7 @@ import com.cheng.blzb.bean.UserConfigEntity import com.cheng.blzb.bean.UserEntity import com.cheng.blzb.bean.VipGoodsEntity import com.cheng.blzb.bean.WxServiceEntity +import com.cheng.blzb.bean.ZZDBInfoEntity import com.cheng.blzb.net.model.HttpBaseResult import com.cheng.blzb.net.model.HttpListResult import com.ylqh.cube.bean.CouponActivityEntity @@ -183,6 +183,12 @@ interface ApiService { @GET("/api/order") suspend fun getOrderInfo(@Query("order_id") orderId: String): HttpBaseResult + /** + * 支付提示 + */ + @GET("/api/pay/tips") + suspend fun getPayTips(): HttpBaseResult> + /** * 更新订单 */ diff --git a/app/src/main/java/com/cheng/blzb/ui/activity/LauncherActivity.kt b/app/src/main/java/com/cheng/blzb/ui/activity/LauncherActivity.kt index 41cc61f..e5c97df 100644 --- a/app/src/main/java/com/cheng/blzb/ui/activity/LauncherActivity.kt +++ b/app/src/main/java/com/cheng/blzb/ui/activity/LauncherActivity.kt @@ -93,7 +93,6 @@ class LauncherActivity : BaseActivity() { private fun intentMain() { if (UserConfigManager.isFirstUseApp()) { - UserConfigManager.saveFirstUseApp(false) if (UserConfigManager.getGuideEnable()) { startActivity() } else { diff --git a/app/src/main/java/com/cheng/blzb/ui/dialog/GoodsCouponDialog.kt b/app/src/main/java/com/cheng/blzb/ui/dialog/GoodsCouponDialog.kt deleted file mode 100644 index ba88084..0000000 --- a/app/src/main/java/com/cheng/blzb/ui/dialog/GoodsCouponDialog.kt +++ /dev/null @@ -1,208 +0,0 @@ -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>(listStr, object : TypeToken>() {}.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): GoodsCouponDialog { - val arg = Bundle() - arg.putSerializable("list", Gson().toJson(list)) - val fragment = GoodsCouponDialog() - fragment.arguments = arg - return fragment - } - } - - class ActivityCouponAdapter : BaseQuickAdapter(R.layout.listitem_goods_coupon) { - - override fun convert(holder: BaseViewHolder, item: VipGoodsEntity) { - - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/cheng/blzb/ui/dialog/GoodsPromotionDialog.kt b/app/src/main/java/com/cheng/blzb/ui/dialog/GoodsPromotionDialog.kt new file mode 100644 index 0000000..6b21a3d --- /dev/null +++ b/app/src/main/java/com/cheng/blzb/ui/dialog/GoodsPromotionDialog.kt @@ -0,0 +1,545 @@ +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.Context +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.BaseAdapter +import android.widget.ImageView +import android.widget.TextView +import androidx.constraintlayout.widget.ConstraintLayout +import androidx.core.animation.addListener +import androidx.core.view.marginStart +import androidx.fragment.app.DialogFragment +import androidx.lifecycle.lifecycleScope +import coil.load +import coil.transform.CircleCropTransformation +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.common.Constants +import com.cheng.blzb.databinding.DialogGoodsPromotionBinding +import com.cheng.blzb.manager.DialogEnum +import com.cheng.blzb.net.ApiFactory +import com.example.base.extensions.gone +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.example.base.utils.SpanUtils +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import kotlinx.coroutines.launch +import org.jetbrains.anko.find +import java.text.DecimalFormat +import kotlin.math.pow + +class GoodsPromotionDialog : DialogFragment() { + private val goodsAdapter by lazy { GoodsAdapter() } + + private val tipsAdapter by lazy { PayTipsAdapter(requireContext()) } + + private var mOnBackListener: ((DialogEnum) -> Unit)? = null //回调事件 + + lateinit var binding: DialogGoodsPromotionBinding + + 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_promotion, null) + + binding = DialogGoodsPromotionBinding.bind(view) + + binding.rvGoods.adapter = goodsAdapter + binding.viewFlipper.adapter = tipsAdapter + + val listStr = arguments?.getString("list") + if (!TextUtils.isEmpty(listStr)) { + val list = Gson().fromJson>(listStr, object : TypeToken>() {}.type) + for (i in 0 until list.size.coerceAtMost(3)) { + goodsAdapter.addData(list[i]) + } + } + + binding.ivClose.onClick { + dismiss() + } + + binding.layoutNext.onClick { + mOnBackListener?.invoke(DialogEnum.CLICK_OK) + dismiss() + } + + getPayTips() + startAnim1() + + val dialog = Dialog(requireContext()) + dialog.setContentView(view) + return dialog + } + + private fun getPayTips() { + lifecycleScope.launch { + try { + val response = ApiFactory.apiService.getPayTips() + if (response.status) { + tipsAdapter.setList(response.data) + } + } catch (e: Exception) { + L.d(e) + } + } + } + + 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 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() + + startAnim2() + }) + + 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() + } + + private fun startAnim2() { + val scaleXHolder1 = PropertyValuesHolder.ofFloat("scaleX", 0f, 1f) + val scaleYHolder1 = PropertyValuesHolder.ofFloat("scaleY", 0f, 1f) + + val scaleXHolder2 = PropertyValuesHolder.ofFloat("scaleX", 1f, 1.1f) + val scaleYHolder2 = PropertyValuesHolder.ofFloat("scaleY", 1f, 1.1f) + + val descTransAnim = ObjectAnimator.ofFloat(binding.ivEffect1Desc, "translationY", 0f, -DensityUtils.dp2px(200f).toFloat()).setDuration(1000) + + val coverTransAnim = ObjectAnimator.ofFloat(binding.ivGoodsCover, "translationY", 0f, -ScreenUtils.getScreenHeight().toFloat()) + coverTransAnim.duration = 1000 + coverTransAnim.addListener(onEnd = { + binding.ivGoodsCover.gone() + }) + + val baseAlphaAnim = ObjectAnimator.ofFloat(binding.ivGoodsBase, "alpha", 1f, 0f) + baseAlphaAnim.duration = 1000 + baseAlphaAnim.addListener(onEnd = { + binding.ivGoodsBase.gone() + }) + + val userCountTransAnim1 = ObjectAnimator.ofFloat(binding.tvAdd1, "translationY", 0f, -DensityUtils.dp2px(5f).toFloat()) + userCountTransAnim1.duration = 1000 + userCountTransAnim1.repeatCount = -1 + userCountTransAnim1.startDelay = 3000 + + val userCountTransAnim2 = ObjectAnimator.ofFloat(binding.tvAdd2, "translationY", 0f, -DensityUtils.dp2px(5f).toFloat()) + userCountTransAnim2.duration = 1000 + userCountTransAnim2.repeatCount = -1 + userCountTransAnim2.startDelay = 3500 + + val userCountAlphaAnim1 = ObjectAnimator.ofFloat(binding.tvAdd1, "alpha", 0f, 1f, 0f) + userCountAlphaAnim1.duration = 1000 + userCountAlphaAnim1.repeatCount = -1 + userCountAlphaAnim1.startDelay = 3000 + userCountAlphaAnim1.addListener(onStart = { + binding.tvAdd1.visible() + }) + + val userCountAlphaAnim2 = ObjectAnimator.ofFloat(binding.tvAdd2, "alpha", 0f, 1f, 0f) + userCountAlphaAnim2.duration = 1000 + userCountAlphaAnim2.repeatCount = -1 + userCountAlphaAnim2.startDelay = 3500 + userCountAlphaAnim2.addListener(onStart = { + binding.tvAdd2.visible() + }) + + val lightScaleAnim = ObjectAnimator.ofPropertyValuesHolder(binding.ivGoodsLight, scaleXHolder1, scaleYHolder1) + lightScaleAnim.duration = 2000 + lightScaleAnim.startDelay = 3000 + lightScaleAnim.addListener(onStart = { + binding.ivGoodsLight.visible() + }) + + val lightRotateAnim = ObjectAnimator.ofFloat(binding.ivGoodsLight, "rotation", 0f, 360f) + lightRotateAnim.duration = 6000 + lightRotateAnim.repeatCount = -1 + lightRotateAnim.interpolator = LinearInterpolator() + lightScaleAnim.startDelay = 2800 + + val goodsScaleAnim = ObjectAnimator.ofPropertyValuesHolder(binding.layoutGoods, scaleXHolder1, scaleYHolder1) + goodsScaleAnim.duration = 1000 + goodsScaleAnim.startDelay = 600 + goodsScaleAnim.addListener(onStart = { + binding.rvGoods.visible() + binding.ivGoodsCover.visible() + binding.ivGoodsBase.visible() + }, onEnd = { + coverTransAnim.start() + baseAlphaAnim.start() + }) + + val btnScaleAnim = ObjectAnimator.ofPropertyValuesHolder(binding.layoutNext, scaleXHolder2, scaleYHolder2) + btnScaleAnim.duration = 600 + btnScaleAnim.repeatCount = -1 + btnScaleAnim.repeatMode = ValueAnimator.REVERSE + + val btnAlphaAnim = ObjectAnimator.ofFloat(binding.layoutNext, "alpha", 0f, 1f) + btnAlphaAnim.duration = 1000 + btnAlphaAnim.startDelay = 3000 + btnAlphaAnim.addListener(onStart = { + binding.layoutNext.visible() + binding.viewFlipper.visible() + }, onEnd = { + btnScaleAnim.start() + }) + + val closeAlphaAnim = ObjectAnimator.ofFloat(binding.ivClose, "alpha", 0f, 1f) + closeAlphaAnim.duration = 1000 + closeAlphaAnim.startDelay = 4000 + closeAlphaAnim.addListener(onStart = { + binding.ivClose.visible() + }) + + val animSet = AnimatorSet() + animSet.playTogether( + descTransAnim, + goodsScaleAnim, + lightScaleAnim, + lightRotateAnim, + userCountTransAnim1, + userCountAlphaAnim1, + userCountTransAnim2, + userCountAlphaAnim2, + btnAlphaAnim, + closeAlphaAnim + ) + animSet.start() + } + + fun setOnBackListener(listener: ((DialogEnum) -> Unit)) { + mOnBackListener = listener + } + + companion object { + fun newInstance(list: List): GoodsPromotionDialog { + val arg = Bundle() + arg.putSerializable("list", Gson().toJson(list)) + val fragment = GoodsPromotionDialog() + fragment.arguments = arg + return fragment + } + } + + class GoodsAdapter : BaseQuickAdapter(R.layout.listitem_promotion_goods) { + + @SuppressLint("SetTextI18n") + override fun convert(holder: BaseViewHolder, item: VipGoodsEntity) { + val tvName = holder.getView(R.id.tv_name) + val tvPrice = holder.getView(R.id.tv_price) + val tvSavedPrice = holder.getView(R.id.tv_saved_price) + val tvOriginPrice = holder.getView(R.id.tv_origin_price) + tvName.typeface = Constants.douyinsansB + tvPrice.typeface = Constants.dDIN_PRO_M + + tvName.text = item.goods_name + SpanUtils.with(tvPrice) + .append("¥") + .setFontSize(16, true) + .append(DecimalFormat("0.##").format(item.origin_price.toFloat())) + .create() + tvSavedPrice.text = "立减${DecimalFormat("0.##").format(item.origin_price.toFloat() - item.price.toFloat())}" + SpanUtils.with(tvOriginPrice) + .append("¥${DecimalFormat("0.##").format(item.origin_price.toFloat())}") + .setStrikethrough() + .create() + holder.setText(R.id.tv_tag, item.tips) + + if (data.size == 3) { + val contentView = holder.getView(R.id.layout_content) + if (holder.layoutPosition == 1) { + val lp = contentView.layoutParams as ConstraintLayout.LayoutParams + lp.width = DensityUtils.dp2px(110f * 0.9f) + lp.height = DensityUtils.dp2px(140f * 0.9f) + contentView.layoutParams = lp + + tvName.textSize = 16f + } else { + val lp = contentView.layoutParams as ConstraintLayout.LayoutParams + lp.width = DensityUtils.dp2px(90f) + lp.height = DensityUtils.dp2px(115f) + contentView.layoutParams = lp + + tvName.textSize = 12f + } + + holder.itemView.elevation = if (holder.layoutPosition == 1) 2f else 1f + holder.itemView.postDelayed({ + startTransAnim(holder.itemView, holder.layoutPosition, data.size, item) + }, 100) + } else { + holder.itemView.visible() + } + } + + @SuppressLint("Recycle") + private fun startTransAnim(view: View, position: Int, total: Int, item: VipGoodsEntity) { + val contentView = view.find(R.id.layout_content) + val tvName = view.find(R.id.tv_name) + val tvPrice = view.find(R.id.tv_price) + val tvSavedPrice = view.find(R.id.tv_saved_price) + val tvOriginPrice = view.find(R.id.tv_origin_price) + val tvTag = view.find(R.id.tv_tag) + + + 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) + + view.translationX = start.toFloat() + tvName.translationY = DensityUtils.dp2px(15f).toFloat() + tvPrice.translationY = DensityUtils.dp2px(15f).toFloat() + + val animator1 = if (position == 1) { + val lp = contentView.layoutParams as ConstraintLayout.LayoutParams + + val valueAnim = ValueAnimator.ofFloat(0.9f, 1f).setDuration(1000) + valueAnim.addUpdateListener { animator -> + val value = animator.animatedValue as Float + lp.width = DensityUtils.dp2px(110f * value) + lp.height = DensityUtils.dp2px(140f * value) + contentView.layoutParams = lp + } + valueAnim + } else { + ObjectAnimator.ofFloat(view, "translationX", start.toFloat(), 0f).setDuration(1000) + } + animator1.startDelay = 3500 + + val animator2 = ValueAnimator.ofFloat(0f, 1f).setDuration(1000) + animator2.addUpdateListener { animator -> + val value = animator.animatedValue as Float + val savedPrice = item.origin_price.toFloat() - item.price.toFloat() + val price = if (value == 1f) { + DecimalFormat("0.##").format(item.origin_price.toFloat() - savedPrice * value) + } else { + "${(item.origin_price.toFloat() - savedPrice * value).toInt()}" + } + SpanUtils.with(tvPrice) + .append("¥") + .setFontSize(16, true) + .append(price) + .create() + } + animator2.startDelay = 800 + + val animator3 = ObjectAnimator.ofFloat(tvTag, "alpha", 0f, 1f).setDuration(1000) + animator3.repeatCount = -1 + animator3.repeatMode = ValueAnimator.REVERSE + + val alphaAnim1 = ObjectAnimator.ofFloat(tvOriginPrice, "alpha", 0f, 1f) + alphaAnim1.duration = 1500 + alphaAnim1.addListener(onStart = { + tvOriginPrice.visible() + animator2.start() + }) + + val alphaAnim2 = ObjectAnimator.ofFloat(tvSavedPrice, "alpha", 0f, 1f) + alphaAnim2.duration = 1500 + alphaAnim2.addListener(onStart = { + tvSavedPrice.visible() + }) + + val transAnim1 = ObjectAnimator.ofFloat(tvName, "translationY", DensityUtils.dp2px(15f).toFloat(), 0f) + transAnim1.duration = 300 + + val transAnim2 = ObjectAnimator.ofFloat(tvPrice, "translationY", DensityUtils.dp2px(15f).toFloat(), 0f) + transAnim2.duration = 300 + + animator1.addListener(onEnd = { + transAnim1.start() + transAnim2.start() + alphaAnim1.start() + }) + + animator2.addListener(onStart = { + alphaAnim2.start() + }, onEnd = { + if (!TextUtils.isEmpty(item.tips)) { + animator3.start() + } + }) + + animator3.addListener(onStart = { + tvTag.visible() + }) + + animator1.start() + } + } + + class PayTipsAdapter(val context: Context): BaseAdapter() { + val data: MutableList = mutableListOf() + + override fun getCount(): Int { + return data.size + } + + override fun getItem(position: Int): String { + return data[position] + } + + override fun getItemId(position: Int): Long { + return position.toLong() + } + + override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View { + val view: View + val viewHolder: ViewHolder + if (convertView == null) { + view = View.inflate(context, R.layout.listitem_goods_promotion_tips, null) + viewHolder = ViewHolder(view) + view.tag = viewHolder + } else { + view = convertView + viewHolder = convertView.tag as ViewHolder + } + viewHolder.ivAvatar.load(context.resources.getIdentifier("yq_${position % 51}", "mipmap", context.packageName)) { + transformations(CircleCropTransformation()) + } + viewHolder.tvContent.text = getItem(position) + return view + } + + fun setList(list: List) { + data.clear() + data.addAll(list) + notifyDataSetChanged() + } + + inner class ViewHolder(val view: View) { + val ivAvatar: ImageView = view.findViewById(R.id.iv_avatar) + val tvContent: TextView = view.findViewById(R.id.tv_content) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/cheng/blzb/ui/fragment/guide/adapter/GuideItem3Adapter.kt b/app/src/main/java/com/cheng/blzb/ui/fragment/guide/adapter/GuideItem3Adapter.kt index 825e1c3..f414c28 100644 --- a/app/src/main/java/com/cheng/blzb/ui/fragment/guide/adapter/GuideItem3Adapter.kt +++ b/app/src/main/java/com/cheng/blzb/ui/fragment/guide/adapter/GuideItem3Adapter.kt @@ -18,6 +18,7 @@ import com.example.base.extensions.onClick import com.example.base.utils.DensityUtils import com.example.base.utils.SpanUtils import kotlin.math.ceil +import kotlin.random.Random class GuideItem3Adapter(val context: Context): RecyclerView.Adapter() { val data: MutableList = mutableListOf() @@ -54,24 +55,11 @@ class GuideItem3Adapter(val context: Context): RecyclerView.Adapter() - for (i in 0 until 15) { - keywordList.add(item.children[i]) - } - keywordAdapter.setList(keywordList) + keywordAdapter.setList(getKeywordList(item)) holder.getView(R.id.iv_refresh).onClick { view -> startRotate(view) - if (ceil(item.children.size / 15.0) > keywordAdapter.page + 1) { - keywordAdapter.page++ - } else { - keywordAdapter.page = 0 - } - val keywordList = mutableListOf() - for (i in keywordAdapter.page * 15 until ((keywordAdapter.page + 1) * 15).coerceAtMost(item.children.size)) { - keywordList.add(item.children[i]) - } - keywordAdapter.setList(keywordList) + keywordAdapter.setList(getKeywordList(item)) } } @@ -88,6 +76,17 @@ class GuideItem3Adapter(val context: Context): RecyclerView.Adapter { + val list = mutableListOf() + while (list.size < 12) { + val keyword = item.children[Random.nextInt(item.children.size)] + if (!list.contains(keyword)) { + list.add(keyword) + } + } + return list + } + @SuppressLint("NotifyDataSetChanged") fun setList(list: List) { data.clear() diff --git a/app/src/main/java/com/cheng/blzb/ui/fragment/guide/item/GuideItem1Fragment.kt b/app/src/main/java/com/cheng/blzb/ui/fragment/guide/item/GuideItem1Fragment.kt index d8ad972..7eb5c5e 100644 --- a/app/src/main/java/com/cheng/blzb/ui/fragment/guide/item/GuideItem1Fragment.kt +++ b/app/src/main/java/com/cheng/blzb/ui/fragment/guide/item/GuideItem1Fragment.kt @@ -61,6 +61,7 @@ class GuideItem1Fragment : BaseFragment @@ -193,13 +196,13 @@ class HomeFragment : ListFragment @@ -247,7 +250,7 @@ class HomeFragment : ListFragment + binding.layoutGoodsCoupon.setOnTouchListener { v, event -> when (event.action) { MotionEvent.ACTION_DOWN -> { isNoClick = false @@ -359,6 +362,7 @@ class HomeFragment : ListFragment if (d == DialogEnum.CLICK_OK) { PublicActivity.start(requireContext(), VipFragment::class.java, Pair("origin", "home_coupon")) @@ -375,8 +379,8 @@ class HomeFragment : ListFragment() { mViewModel.getGoodsList(if (vipType == 0) "member" else "corp") mViewModel.getCorpInfo() mViewModel.couponList() - if (!MainActivity.hasCheckedVipEnterCouponActivity) { - mViewModel.couponEnterActivityList() + if (!UserConfigManager.isShowGoodsCouponAnim()) { + if (!MainActivity.hasCheckedVipEnterCouponActivity) { + mViewModel.couponEnterActivityList() + } } if (!MainActivity.hasCheckedVipReturnCouponActivity) { mViewModel.couponReturnActivityList() @@ -354,6 +357,10 @@ class VipFragment : BaseFragment() { setCoupon() setCouponCount() initPrivacyTv() + + if (UserConfigManager.isShowGoodsCouponAnim()) { + showGoodsCouponDialog() + } } mViewModel.couponListLiveData.observe(this) { list -> @@ -747,6 +754,12 @@ class VipFragment : BaseFragment() { return true } + private fun showGoodsCouponDialog() { + val f = GoodsPromotionDialog.newInstance(goodsAdapter.data) + f.show(childFragmentManager, GoodsPromotionDialog::class.java.simpleName) + UserConfigManager.hideGoodsCouponAnim() + } + private fun showRedPacketActivityDialog(isEnter: Boolean) { val coupon = if (isEnter) { MainActivity.hasCheckedVipEnterCouponActivity = true diff --git a/app/src/main/res/layout/dialog_goods_coupon.xml b/app/src/main/res/layout/dialog_goods_coupon.xml deleted file mode 100644 index c645fdf..0000000 --- a/app/src/main/res/layout/dialog_goods_coupon.xml +++ /dev/null @@ -1,154 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_goods_promotion.xml b/app/src/main/res/layout/dialog_goods_promotion.xml new file mode 100644 index 0000000..af4e670 --- /dev/null +++ b/app/src/main/res/layout/dialog_goods_promotion.xml @@ -0,0 +1,305 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml index 0d9dcee..0ab8486 100644 --- a/app/src/main/res/layout/fragment_home.xml +++ b/app/src/main/res/layout/fragment_home.xml @@ -143,8 +143,8 @@ android:layout_width="match_parent" android:layout_height="0dp" android:background="@color/windowBackground" - app:layout_constraintTop_toBottomOf="@id/iv_title_bg" - app:layout_constraintBottom_toBottomOf="parent"/> + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintTop_toBottomOf="@id/iv_title_bg" /> - + app:layout_constraintEnd_toEndOf="parent"> + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/listitem_goods_promotion_tips.xml b/app/src/main/res/layout/listitem_goods_promotion_tips.xml new file mode 100644 index 0000000..701e1cc --- /dev/null +++ b/app/src/main/res/layout/listitem_goods_promotion_tips.xml @@ -0,0 +1,21 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/listitem_promotion_goods.xml b/app/src/main/res/layout/listitem_promotion_goods.xml new file mode 100644 index 0000000..6a3a9fb --- /dev/null +++ b/app/src/main/res/layout/listitem_promotion_goods.xml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-xxhdpi/ic_coupon_dialog_icon.png b/app/src/main/res/mipmap-xxhdpi/ic_coupon_dialog_icon.png deleted file mode 100644 index 543f024..0000000 Binary files a/app/src/main/res/mipmap-xxhdpi/ic_coupon_dialog_icon.png and /dev/null differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_coupon_dialog_icon.webp b/app/src/main/res/mipmap-xxhdpi/ic_coupon_dialog_icon.webp new file mode 100644 index 0000000..b8d9368 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_coupon_dialog_icon.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_goods_coupon_bg.png b/app/src/main/res/mipmap-xxhdpi/ic_goods_coupon_bg.png deleted file mode 100644 index 754febb..0000000 Binary files a/app/src/main/res/mipmap-xxhdpi/ic_goods_coupon_bg.png and /dev/null differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_goods_coupon_desc.png b/app/src/main/res/mipmap-xxhdpi/ic_goods_coupon_desc.png deleted file mode 100644 index 58332ea..0000000 Binary files a/app/src/main/res/mipmap-xxhdpi/ic_goods_coupon_desc.png and /dev/null differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_goods_coupon_fg.png b/app/src/main/res/mipmap-xxhdpi/ic_goods_coupon_fg.png deleted file mode 100644 index 94d4104..0000000 Binary files a/app/src/main/res/mipmap-xxhdpi/ic_goods_coupon_fg.png and /dev/null differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_goods_coupon_light.png b/app/src/main/res/mipmap-xxhdpi/ic_goods_coupon_light.png deleted file mode 100644 index 4b061ee..0000000 Binary files a/app/src/main/res/mipmap-xxhdpi/ic_goods_coupon_light.png and /dev/null differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_goods_coupon_star.png b/app/src/main/res/mipmap-xxhdpi/ic_goods_coupon_star.png deleted file mode 100644 index bfbe6f3..0000000 Binary files a/app/src/main/res/mipmap-xxhdpi/ic_goods_coupon_star.png and /dev/null differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_goods_promotion_bg.webp b/app/src/main/res/mipmap-xxhdpi/ic_goods_promotion_bg.webp new file mode 100644 index 0000000..f63a5cf Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_goods_promotion_bg.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_goods_promotion_bg_light.webp b/app/src/main/res/mipmap-xxhdpi/ic_goods_promotion_bg_light.webp new file mode 100644 index 0000000..6dce84f Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_goods_promotion_bg_light.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_goods_promotion_btn.webp b/app/src/main/res/mipmap-xxhdpi/ic_goods_promotion_btn.webp new file mode 100644 index 0000000..80c10e3 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_goods_promotion_btn.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_goods_promotion_desc.webp b/app/src/main/res/mipmap-xxhdpi/ic_goods_promotion_desc.webp new file mode 100644 index 0000000..d363d07 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_goods_promotion_desc.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_goods_promotion_fg.webp b/app/src/main/res/mipmap-xxhdpi/ic_goods_promotion_fg.webp new file mode 100644 index 0000000..80b133a Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_goods_promotion_fg.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_goods_promotion_goods_base.webp b/app/src/main/res/mipmap-xxhdpi/ic_goods_promotion_goods_base.webp new file mode 100644 index 0000000..cf97fe3 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_goods_promotion_goods_base.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_goods_promotion_goods_bg.webp b/app/src/main/res/mipmap-xxhdpi/ic_goods_promotion_goods_bg.webp new file mode 100644 index 0000000..46ce7d8 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_goods_promotion_goods_bg.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_goods_promotion_goods_cover.webp b/app/src/main/res/mipmap-xxhdpi/ic_goods_promotion_goods_cover.webp new file mode 100644 index 0000000..33b5dcc Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_goods_promotion_goods_cover.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_goods_promotion_goods_tag_bg.webp b/app/src/main/res/mipmap-xxhdpi/ic_goods_promotion_goods_tag_bg.webp new file mode 100644 index 0000000..5f2a9e7 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_goods_promotion_goods_tag_bg.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_goods_promotion_light.webp b/app/src/main/res/mipmap-xxhdpi/ic_goods_promotion_light.webp new file mode 100644 index 0000000..0948975 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_goods_promotion_light.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_goods_promotion_star.webp b/app/src/main/res/mipmap-xxhdpi/ic_goods_promotion_star.webp new file mode 100644 index 0000000..3b7c50c Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_goods_promotion_star.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_goods_promotion_user_bg.webp b/app/src/main/res/mipmap-xxhdpi/ic_goods_promotion_user_bg.webp new file mode 100644 index 0000000..0d27f4e Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_goods_promotion_user_bg.webp differ