diff --git a/app/src/main/java/com/cheng/blzb/bean/ConfigEntity.kt b/app/src/main/java/com/cheng/blzb/bean/ConfigEntity.kt index dbc4aa1..69a4655 100644 --- a/app/src/main/java/com/cheng/blzb/bean/ConfigEntity.kt +++ b/app/src/main/java/com/cheng/blzb/bean/ConfigEntity.kt @@ -36,4 +36,7 @@ class ConfigEntity { @SerializedName("client.invoice.urgent.interval.minutes") //加急开票间隔分钟数 var invoiceIntervalMinutes: String? = null + + @SerializedName("client.guide.pay.countdown.time") //引导页支付倒计时 + var guideCountdownTime: String? = null } \ No newline at end of file diff --git a/app/src/main/java/com/cheng/blzb/manager/UserConfigManager.kt b/app/src/main/java/com/cheng/blzb/manager/UserConfigManager.kt index 80b9fd8..a950404 100644 --- a/app/src/main/java/com/cheng/blzb/manager/UserConfigManager.kt +++ b/app/src/main/java/com/cheng/blzb/manager/UserConfigManager.kt @@ -85,6 +85,7 @@ object UserConfigManager { saveServicePhoneList(data.config!!.servicePhoneList) savePayType(data.config!!.payType) saveInvoiceIntervalTime(data.config!!.invoiceIntervalMinutes) + saveGuideCountdownTime(data.config!!.guideCountdownTime) } } catch (e : Exception) { e.printStackTrace() @@ -301,6 +302,17 @@ object UserConfigManager { return emptyList() } + /** + * 引导页支付倒计时 + */ + private fun saveGuideCountdownTime(time: String?) { + MMKVUtils.put("guide_countdown_time", time) + } + + fun getGuideCountdownTime(): String? { + return MMKVUtils.getString("guide_countdown_time") + } + /** * 保存个推cid */ diff --git a/app/src/main/java/com/cheng/blzb/ui/dialog/GuideSaleDialog.kt b/app/src/main/java/com/cheng/blzb/ui/dialog/GuideSaleDialog.kt new file mode 100644 index 0000000..df4048e --- /dev/null +++ b/app/src/main/java/com/cheng/blzb/ui/dialog/GuideSaleDialog.kt @@ -0,0 +1,82 @@ +package com.cheng.blzb.ui.dialog + +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.fragment.app.DialogFragment +import com.cheng.blzb.R +import com.cheng.blzb.common.Constants +import com.cheng.blzb.databinding.DialogGuideSaleBinding +import com.cheng.blzb.manager.UserConfigManager +import com.example.base.extensions.onClick +import com.example.base.utils.ScreenUtils + +class GuideSaleDialog : DialogFragment() { + private var totalSeconds = 0L + + private var mOnBackListener: ((Long) -> Unit)? = null //回调事件 + + lateinit var binding: DialogGuideSaleBinding + + 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)) + setCancelable(false) + return super.onCreateView(inflater, container, savedInstanceState) + } + + @SuppressLint("SetTextI18n") + override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { + val view = layoutInflater.inflate(R.layout.dialog_guide_sale, null) + + binding = DialogGuideSaleBinding.bind(view) + + binding.tvEndTip2.typeface = Constants.almmsht + binding.tvOriginPrice.typeface = Constants.dDIN_PRO_M + binding.tvPrice.typeface = Constants.dDIN_PRO_M + binding.tvNext.typeface = Constants.almmsht + + val countDownTime = UserConfigManager.getGuideCountdownTime() + if (!TextUtils.isEmpty(countDownTime)) { + totalSeconds = countDownTime!!.split(",")[1].toLong() + binding.tvNext.text = "考虑${totalSeconds}秒" + } + + binding.tvNext.onClick { + mOnBackListener?.invoke(totalSeconds) + dismiss() + } + + val dialog = Dialog(requireContext()) + dialog.setContentView(view) + return dialog + } + + fun setOnSelectListener(listener: ((Long) -> Unit)) { + mOnBackListener = listener + } + + companion object { + fun newInstance(): GuideSaleDialog { + val arg = Bundle() + val fragment = GuideSaleDialog() + fragment.arguments = arg + return fragment + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/cheng/blzb/ui/fragment/guide/item/GuideItem5Fragment.kt b/app/src/main/java/com/cheng/blzb/ui/fragment/guide/item/GuideItem5Fragment.kt index dd3fc5b..ccdc227 100644 --- a/app/src/main/java/com/cheng/blzb/ui/fragment/guide/item/GuideItem5Fragment.kt +++ b/app/src/main/java/com/cheng/blzb/ui/fragment/guide/item/GuideItem5Fragment.kt @@ -3,6 +3,7 @@ package com.cheng.blzb.ui.fragment.guide.item import android.animation.AnimatorSet import android.animation.ObjectAnimator import android.animation.ValueAnimator +import android.annotation.SuppressLint import android.view.animation.AccelerateDecelerateInterpolator import android.view.animation.LinearInterpolator import androidx.constraintlayout.widget.ConstraintLayout @@ -28,6 +29,7 @@ import com.yy.mobile.rollingtextview.strategy.Strategy import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers import io.reactivex.rxjava3.core.Observable import io.reactivex.rxjava3.disposables.Disposable +import org.jetbrains.anko.sdk27.listeners.onTouch import org.libpag.PAGFile import java.util.concurrent.TimeUnit @@ -51,6 +53,7 @@ class GuideItem5Fragment : BaseFragment true } + } + private fun startAnim() { val bgTransAnim = ObjectAnimator.ofFloat(binding.ivBg, "translationY", 0f, -DensityUtils.dp2px(75f).toFloat()) bgTransAnim.duration = 2000 diff --git a/app/src/main/java/com/cheng/blzb/ui/fragment/guide/vip/GuideVipAdapter.kt b/app/src/main/java/com/cheng/blzb/ui/fragment/guide/vip/GuideVipAdapter.kt new file mode 100644 index 0000000..95216a0 --- /dev/null +++ b/app/src/main/java/com/cheng/blzb/ui/fragment/guide/vip/GuideVipAdapter.kt @@ -0,0 +1,82 @@ +package com.cheng.blzb.ui.fragment.guide.vip + +import android.util.TypedValue +import android.view.ViewGroup +import android.widget.TextView +import androidx.constraintlayout.widget.ConstraintLayout +import androidx.core.graphics.toColorInt +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.example.base.extensions.getColor +import com.example.base.utils.DensityUtils +import com.example.base.utils.SpanUtils +import com.flyjingfish.gradienttextviewlib.GradientTextView +import java.text.DecimalFormat + +class GuideVipAdapter: BaseQuickAdapter(R.layout.listitem_guide_vip_goods) { + + override fun convert(holder: BaseViewHolder, item: VipGoodsEntity) { + holder.setGone(R.id.tv_tag, true) + if (item.tips.isNotEmpty()) { + holder.setVisible(R.id.tv_tag, true) + holder.setText(R.id.tv_tag, item.tips) + } + + holder.setText(R.id.tv_goods_name, item.goods_name) + SpanUtils.with(holder.getView(R.id.tv_price)) + .append("¥") + .setFontSize(if (item.checked) 14 else 11, true) + .append(DecimalFormat("0.##").format(item.price.toFloat())) + .setFontSize(if (item.checked) 34 else 29, true) + .create() + SpanUtils.with(holder.getView(R.id.tv_origin_price)) + .append("¥${item.origin_price}") + .setStrikethrough() + .create() + + holder.setBackgroundResource(R.id.layout_content, if (item.checked) R.mipmap.ic_guide_vip_goods_checked else R.mipmap.ic_guide_vip_goods_default) + + holder.getView(R.id.tv_tag).setTextSize(TypedValue.COMPLEX_UNIT_SP, if (item.checked) 10f else 8f) + holder.getView(R.id.tv_goods_name).setTextSize(TypedValue.COMPLEX_UNIT_SP, if (item.checked) 20f else 16f) + holder.getView(R.id.tv_origin_price).setTextSize(TypedValue.COMPLEX_UNIT_SP, if (item.checked) 10f else 8f) + + holder.getView(R.id.tv_goods_name).typeface = Constants.pmzdbt + holder.getView(R.id.tv_price).typeface = Constants.dDIN_PRO_M + + val parentWidth = recyclerView.width + val minWidth = (0.3 * parentWidth).toInt() + + val layoutContent = holder.getView(R.id.layout_content) + val layoutParams = layoutContent.layoutParams as ConstraintLayout.LayoutParams + if (item.checked) { + layoutParams.dimensionRatio = "h,122:148" + layoutContent.layoutParams = layoutParams + + holder.itemView.layoutParams = ViewGroup.LayoutParams(parentWidth - minWidth * 2 - DensityUtils.dp2px(20f), ViewGroup.LayoutParams.MATCH_PARENT) + + holder.getView(R.id.tv_tag).setPadding(DensityUtils.dp2px(6f), DensityUtils.dp2px(2f), DensityUtils.dp2px(6f), DensityUtils.dp2px(2f)) + + val tvGoodsName = holder.getView(R.id.tv_goods_name) + tvGoodsName.angle = 270f + tvGoodsName.gradientColors = intArrayOf("#20F3E6".toColorInt(), "#05ACE8".toColorInt()) + holder.setTextColor(R.id.tv_price, getColor(R.color.white)) + holder.setTextColor(R.id.tv_origin_price, getColor(R.color.color_a6acb5)) + } else { + layoutParams.dimensionRatio = "h,100:118" + layoutContent.layoutParams = layoutParams + + holder.itemView.layoutParams = ViewGroup.LayoutParams(minWidth, ViewGroup.LayoutParams.MATCH_PARENT) + + holder.getView(R.id.tv_tag).setPadding(DensityUtils.dp2px(4f), DensityUtils.dp2px(1f), DensityUtils.dp2px(4f), DensityUtils.dp2px(1f)) + + val tvGoodsName = holder.getView(R.id.tv_goods_name) + tvGoodsName.angle = 0f + tvGoodsName.gradientColors = intArrayOf("#FFFFFF".toColorInt(), "#61D0FC".toColorInt()) + holder.setTextColor(R.id.tv_price, getColor(R.color.color_9bbbdf)) + holder.setTextColor(R.id.tv_origin_price, getColor(R.color.color_a6acb5)) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/cheng/blzb/ui/fragment/guide/vip/GuideVipFragment.kt b/app/src/main/java/com/cheng/blzb/ui/fragment/guide/vip/GuideVipFragment.kt index 44652a9..2842ae3 100644 --- a/app/src/main/java/com/cheng/blzb/ui/fragment/guide/vip/GuideVipFragment.kt +++ b/app/src/main/java/com/cheng/blzb/ui/fragment/guide/vip/GuideVipFragment.kt @@ -1,37 +1,605 @@ package com.cheng.blzb.ui.fragment.guide.vip +import android.animation.AnimatorSet +import android.animation.ObjectAnimator import android.annotation.SuppressLint +import android.os.Build +import android.text.TextUtils +import android.view.View +import android.view.ViewTreeObserver.OnGlobalLayoutListener import android.window.OnBackInvokedDispatcher import androidx.activity.addCallback +import androidx.core.animation.addListener +import androidx.core.content.ContextCompat import androidx.core.os.BuildCompat +import androidx.core.view.isVisible +import androidx.recyclerview.widget.RecyclerView +import com.cheng.blzb.R +import com.cheng.blzb.bean.GuideTotalBidEntity +import com.cheng.blzb.bean.GuideUpdateEntity +import com.cheng.blzb.bean.HotWordEntity +import com.cheng.blzb.bean.OrderPayEntity +import com.cheng.blzb.bean.VipGoodsEntity +import com.cheng.blzb.common.Constants +import com.cheng.blzb.common.EventConstants import com.cheng.blzb.databinding.FragmentGuideVipBinding +import com.cheng.blzb.event.PayStatusEnum +import com.cheng.blzb.event.PayStatusEvent +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.fragment.guide.GuideViewModel +import com.cheng.blzb.ui.activity.PublicActivity +import com.cheng.blzb.ui.dialog.GuideSaleDialog +import com.cheng.blzb.ui.dialog.PayTipDialog +import com.cheng.blzb.ui.fragment.mine.order.cert.CertificateFragment +import com.cheng.blzb.utils.DateUtils +import com.cheng.blzb.utils.UrlHelper +import com.cheng.blzb.utils.pay.PayUtils +import com.cheng.blzb.widget.BarChartView +import com.example.base.common.RxBus +import com.example.base.common.RxCountDown +import com.example.base.decoration.SpacesItemDecoration +import com.example.base.extensions.getColor +import com.example.base.extensions.getDD +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.BaseFragment +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.tencent.mm.opensdk.openapi.IWXAPI +import com.tencent.mm.opensdk.openapi.WXAPIFactory +import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers +import io.reactivex.rxjava3.core.Observable +import io.reactivex.rxjava3.disposables.Disposable +import org.jetbrains.anko.sdk27.listeners.onCheckedChange +import org.jetbrains.anko.sdk27.listeners.onTouch import org.jetbrains.anko.startActivity +import java.text.DecimalFormat +import java.util.Calendar +import java.util.concurrent.TimeUnit +import kotlin.collections.forEachIndexed -class GuideVipFragment: BaseFragment() { +class GuideVipFragment: BaseFragment() { + private val userTipsAdapter by lazy { GuideVipUserAdapter(requireContext(), userTipsList) } + private val industryAdapter by lazy { GuideVipIndustryAdapter(requireContext(), hotWordChildList) } + + private val userTipsList = mutableListOf() + private val hotWordChildList = mutableListOf() + private var totalInfo: GuideTotalBidEntity? = null + + private val updateInfoList = mutableListOf() + + private var payType = 0 // 0 微信 1 支付宝 2 对公转账 + + private lateinit var api: IWXAPI + private var isAgree = false + private var totalPrice = 0f + + private val goodsAdapter by lazy { GuideVipAdapter() } + + private var goodsEntity: VipGoodsEntity? = null + private var orderEntity: OrderPayEntity? = null + + private var totalSeconds = 0L + private var countdownDisposable: Disposable? = null + private var scrollTask: Disposable? = null override fun initView() { super.initView() + binding.tvTotalInfoCount1.typeface = Constants.dDIN_PRO_M + binding.tvTotalInfoCount2.typeface = Constants.dDIN_PRO_M + binding.tvTotalInfoCount3.typeface = Constants.dDIN_PRO_M + binding.tvTotalInfoCount4.typeface = Constants.dDIN_PRO_M + binding.tvPrice.typeface = Constants.dDIN_PRO_M + + binding.rvUser.adapter = userTipsAdapter + + binding.viewFlipper.adapter = industryAdapter + + binding.rvGoods.adapter = goodsAdapter + binding.rvGoods.addItemDecoration(SpacesItemDecoration(DensityUtils.dp2px(10f), RecyclerView.HORIZONTAL)) + + binding.cbAgree.visibility = if (UserConfigManager.isPayAgreementEnable()) View.VISIBLE else View.GONE + binding.tvAgree.visibility = if (UserConfigManager.isPayAgreementEnable()) View.VISIBLE else View.GONE + + binding.layoutContent.viewTreeObserver.addOnGlobalLayoutListener(object : OnGlobalLayoutListener { + override fun onGlobalLayout() { + mViewModel.getGoodsList() + binding.layoutContent.viewTreeObserver.removeOnGlobalLayoutListener(this) + } + }) } override fun initData() { super.initData() + api = WXAPIFactory.createWXAPI(requireContext(), Constants.WechatAppId) + + mViewModel.getPayUserTips() + mViewModel.getUpdateNum() + + setData() } + @SuppressLint("NotifyDataSetChanged") override fun initListener() { super.initListener() setBackPressed() + binding.rvUser.onTouch { _, _ -> true } + + goodsAdapter.setOnItemClickListener { _, _, i -> + val item = goodsAdapter.getItem(i) + if (item.goods_id == goodsEntity?.goods_id) return@setOnItemClickListener + goodsAdapter.data.forEach { it.checked = it.goods_id == item.goods_id } + goodsAdapter.notifyDataSetChanged() + + goodsEntity = item + setPrice(goodsEntity!!.price.toFloat()) + releasePayType() + } + binding.ivClose.onClick { requireActivity().startActivity() } + + binding.tvAliPay.onClick { + payType = 1 + checkPayType() + } + + binding.tvWxPay.onClick { + payType = 0 + checkPayType() + } + + binding.tvBankPay.onClick { + payType = 2 + checkPayType() + } + + binding.cbAgree.onCheckedChange { _, isChecked -> + isAgree = isChecked + } + + binding.tvAgree.onClick { + binding.cbAgree.isChecked = !binding.cbAgree.isChecked + } + + binding.tvPay.onClick { + if (goodsEntity == null) return@onClick + if (!UserConfigManager.getNoLoginPay() && !LoginManager.isLogin()) { + toast("请登录后支付") + return@onClick + } + if (payType == 0 && !api.isWXAppInstalled) { + toast("您没有安装微信客户端,请先下载安装") + return@onClick + } + if (UserConfigManager.isPayAgreementEnable() && !isAgree) { + val f = PayTipDialog.newInstance(showAgreement = true, showRenew = !TextUtils.isEmpty(goodsEntity?.sign_value) && payType == 1) + f.setOnSelectListener { + binding.cbAgree.isChecked = true + if (payType == 0) { + mViewModel.payCreateOrder(goodsEntity!!.goods_id, "weixin") + } else if (payType == 1) { + mViewModel.payCreateOrder(goodsEntity!!.goods_id, "alipay") + } else if (payType == 2) { + mViewModel.payCreateOrder(goodsEntity!!.goods_id, "bank") + } + } + f.show(childFragmentManager, PayTipDialog::class.java.simpleName) + } else { + if (payType == 0) { + mViewModel.payCreateOrder(goodsEntity!!.goods_id, "weixin") + } else if (payType == 1) { + mViewModel.payCreateOrder(goodsEntity!!.goods_id, "alipay") + } else if (payType == 2) { + mViewModel.payCreateOrder(goodsEntity!!.goods_id, "bank") + } + } + EventReportManager.eventReport( + EventConstants.PAY_PAY, + if (payType == 0) "weixin" else if (payType == 1) "alipay" else "bank", + Gson().toJson(goodsEntity) + ) + } } + @SuppressLint("NotifyDataSetChanged") override fun initObserve() { super.initObserve() + mViewModel.goodsListLiveData.observe(this) { list -> + goodsAdapter.setList(list) + + goodsEntity = list.find { it.checked } + if (goodsEntity == null && list.isNotEmpty()) { + goodsEntity = list[0] + } + if (goodsEntity != null) { + setPrice(goodsEntity!!.price.toFloat()) + releasePayType() + } + initPrivacyTv() + startAnim() + } + + mViewModel.createOrderLiveData.observe(this) { + orderEntity = it + if (payType == 0) { + PayUtils.toWXPay(requireActivity(), it) + } else if (payType == 1) { + PayUtils.toAliPay(requireActivity(), it.payParam, "") + } else { + PublicActivity.start(requireContext(), CertificateFragment::class.java, Pair("orderId", orderEntity!!.orderId)) + } + } + + mViewModel.payTipsLiveData.observe(this) { + userTipsList.addAll(it) + userTipsAdapter.notifyDataSetChanged() + } + + mViewModel.updateLiveData.observe(this) { + updateInfoList.clear() + updateInfoList.addAll(it) + setChartData() + binding.tvChartTitle.text = "月份:${Calendar.getInstance().get(Calendar.MONTH) + 1}月 单位:条" + } + + val payStatusDisposable = RxBus.defaultInstance.toObservable(PayStatusEvent::class.java).subscribe { + when (it.payStatus) { + PayStatusEnum.PAY_SUCCESS -> { + toast("支付成功") + EventReportManager.eventReport( + EventConstants.PAY_SUCCESS, + if (payType == 0) "weixin" else "alipay", + "{isGuide: true, orderId:${orderEntity?.orderId}, meal:${Gson().toJson(goodsEntity)}}" + ) + requireActivity().startActivity() + } + + PayStatusEnum.PAY_CANCEL -> { + toast("已取消支付") + EventReportManager.eventReport(EventConstants.PAY_CANCEL, if (payType == 0) "weixin" else "alipay", "{isGuide: true, orderId:${orderEntity?.orderId}") + } + + else -> { + toast("已取消支付") + EventReportManager.eventReport(if (payType == 0) EventConstants.ERROR_CLIENT_WXPAY_ERR else EventConstants.ERROR_CLIENT_ALIPAY_ERR, "{isGuide: true, orderId:${orderEntity?.orderId}", it.message) + } + } + } + addDisposable(payStatusDisposable) + } + + private fun setData() { + totalInfo = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + arguments?.getSerializable("total", GuideTotalBidEntity::class.java) + } else { + arguments?.getSerializable("total") as? GuideTotalBidEntity + } + + SpanUtils.with(binding.tvTotalInfoCount1) + .append("${totalInfo?.bidCount}") + .append("条") + .setFontSize(10, true) + .create() + SpanUtils.with(binding.tvTotalInfoCount2) + .append("${totalInfo?.hasContact}") + .append("条") + .setFontSize(10, true) + .create() + SpanUtils.with(binding.tvTotalInfoCount3) + .append("${totalInfo?.maxMoney}") + .append("亿元") + .setFontSize(10, true) + .create() + SpanUtils.with(binding.tvTotalInfoCount4) + .append("${totalInfo?.yesterdayCount}") + .append("条") + .setFontSize(10, true) + .create() + + val hotWordListStr = arguments?.getString("hotWords") + if (!TextUtils.isEmpty(hotWordListStr)) { + hotWordChildList.addAll(Gson().fromJson>(hotWordListStr, object : TypeToken>() {}.type)) + industryAdapter.notifyDataSetChanged() + } + + val countDownTime = UserConfigManager.getGuideCountdownTime() + if (!TextUtils.isEmpty(countDownTime)) { + totalSeconds = countDownTime!!.split(",")[0].toLong() + startCountdown() + } + } + + private fun setChartData() { + val dateList = getDateList(updateInfoList, System.currentTimeMillis()) + val valueList = mutableListOf() + updateInfoList.forEachIndexed { index, item -> + valueList.add(BarChartView.XAxisValue(item.count.toFloat(), dateList[index])) + } + binding.barChart.setData(valueList) + } + + private fun startAnim() { + val closeAlphaAnim = ObjectAnimator.ofFloat(binding.ivClose, "alpha", 0f, 1f) + closeAlphaAnim.duration = 1000 + closeAlphaAnim.startDelay = 1800 + closeAlphaAnim.addListener(onStart = { + binding.ivClose.visible() + }) + + val userTransAnim = ObjectAnimator.ofFloat(binding.rvUser, "translationX", ScreenUtils.getScreenWidth().toFloat(), 0f) + userTransAnim.duration = 2000 + userTransAnim.startDelay = 1800 + userTransAnim.addListener(onStart = { + binding.rvUser.visible() + }, onEnd = { + startScroll() + }) + + val industryTransAnim = ObjectAnimator.ofFloat(binding.layoutIndustry, "translationY", ScreenUtils.getScreenHeight().toFloat(), 0f) + industryTransAnim.duration = 1000 + industryTransAnim.addListener(onStart = { + binding.layoutIndustry.visible() + }) + + val tabTransAnim = ObjectAnimator.ofFloat(binding.layoutTab, "translationY", ScreenUtils.getScreenHeight().toFloat(), 0f) + tabTransAnim.duration = 1000 + tabTransAnim.addListener(onStart = { + binding.layoutTab.visible() + }) + + val infoWidth = binding.layoutInfo.measuredWidth + val lineWidth = binding.ivInfoLight1.measuredWidth + val infoLine1TransAnim = ObjectAnimator.ofFloat(binding.ivInfoLight1, "translationX", 0f, -(infoWidth - lineWidth).toFloat()).setDuration(1000) + val infoLine2TransAnim = ObjectAnimator.ofFloat(binding.ivInfoLight2, "translationX", 0f, (infoWidth - lineWidth).toFloat()).setDuration(1000) + + val infoRotateAnim = ObjectAnimator.ofFloat(binding.layoutInfo, "rotationX", 90f, -10f, 10f, 0f) + infoRotateAnim.duration = 1000 + infoRotateAnim.startDelay = 800 + infoRotateAnim.addListener(onStart = { + binding.layoutInfo.visible() + }, onEnd = { + infoLine1TransAnim.start() + infoLine2TransAnim.start() + }) + + val timeTransAnim = ObjectAnimator.ofFloat(binding.layoutCountdown, "translationY", ScreenUtils.getScreenHeight().toFloat(), 0f) + timeTransAnim.duration = 1000 + timeTransAnim.startDelay = 1000 + timeTransAnim.addListener(onStart = { + binding.layoutCountdown.visible() + }) + + val goodsTransAnim = ObjectAnimator.ofFloat(binding.rvGoods, "translationY", ScreenUtils.getScreenHeight().toFloat(), 0f) + goodsTransAnim.duration = 1000 + goodsTransAnim.startDelay = 1200 + goodsTransAnim.addListener(onStart = { + binding.rvGoods.visible() + }) + + val payTypeTransAnim = ObjectAnimator.ofFloat(binding.layoutPay, "translationY", ScreenUtils.getScreenHeight().toFloat(), 0f) + payTypeTransAnim.duration = 1000 + payTypeTransAnim.startDelay = 1400 + payTypeTransAnim.addListener(onStart = { + binding.layoutPay.visible() + }) + + val payBtnTransAnim = ObjectAnimator.ofFloat(binding.layoutPayBtn, "translationY", ScreenUtils.getScreenHeight().toFloat(), 0f) + payBtnTransAnim.duration = 1000 + payBtnTransAnim.startDelay = 1400 + payBtnTransAnim.addListener(onStart = { + binding.layoutPayBtn.visible() + }) + + val animSet = AnimatorSet() + animSet.playTogether( + closeAlphaAnim, + userTransAnim, + industryTransAnim, + tabTransAnim, + infoRotateAnim, + timeTransAnim, + goodsTransAnim, + payTypeTransAnim, + payBtnTransAnim + ) + animSet.start() + } + + private fun checkPayType() { + if (payType == 0) { + val start1 = ContextCompat.getDrawable(requireContext(), R.mipmap.ic_wx_pay) + val end1 = ContextCompat.getDrawable(requireContext(), R.mipmap.ic_guide_pay_checked) + binding.tvWxPay.setCompoundDrawablesRelativeWithIntrinsicBounds(start1, null, end1, null) + + val start2 = ContextCompat.getDrawable(requireContext(), R.mipmap.ic_ali_pay) + val end2 = ContextCompat.getDrawable(requireContext(), R.mipmap.ic_guide_pay_default) + binding.tvAliPay.setCompoundDrawablesRelativeWithIntrinsicBounds(start2, null, end2, null) + + val start3 = ContextCompat.getDrawable(requireContext(), R.mipmap.ic_transfer_pay) + val end3 = ContextCompat.getDrawable(requireContext(), R.mipmap.ic_guide_pay_default) + binding.tvBankPay.setCompoundDrawablesRelativeWithIntrinsicBounds(start3, null, end3, null) + } else if (payType == 1) { + val start1 = ContextCompat.getDrawable(requireContext(), R.mipmap.ic_ali_pay) + val end1 = ContextCompat.getDrawable(requireContext(), R.mipmap.ic_guide_pay_checked) + binding.tvAliPay.setCompoundDrawablesRelativeWithIntrinsicBounds(start1, null, end1, null) + + val start2 = ContextCompat.getDrawable(requireContext(), R.mipmap.ic_wx_pay) + val end2 = ContextCompat.getDrawable(requireContext(), R.mipmap.ic_guide_pay_default) + binding.tvWxPay.setCompoundDrawablesRelativeWithIntrinsicBounds(start2, null, end2, null) + + val start3 = ContextCompat.getDrawable(requireContext(), R.mipmap.ic_transfer_pay) + val end3 = ContextCompat.getDrawable(requireContext(), R.mipmap.ic_guide_pay_default) + binding.tvBankPay.setCompoundDrawablesRelativeWithIntrinsicBounds(start3, null, end3, null) + } else { + val start1 = ContextCompat.getDrawable(requireContext(), R.mipmap.ic_transfer_pay) + val end1 = ContextCompat.getDrawable(requireContext(), R.mipmap.ic_guide_pay_checked) + binding.tvBankPay.setCompoundDrawablesRelativeWithIntrinsicBounds(start1, null, end1, null) + + val start2 = ContextCompat.getDrawable(requireContext(), R.mipmap.ic_ali_pay) + val end2 = ContextCompat.getDrawable(requireContext(), R.mipmap.ic_guide_pay_default) + binding.tvAliPay.setCompoundDrawablesRelativeWithIntrinsicBounds(start2, null, end2, null) + + val start3 = ContextCompat.getDrawable(requireContext(), R.mipmap.ic_wx_pay) + val end3 = ContextCompat.getDrawable(requireContext(), R.mipmap.ic_guide_pay_default) + binding.tvWxPay.setCompoundDrawablesRelativeWithIntrinsicBounds(start3, null, end3, null) + } + initPrivacyTv() + } + + private fun releasePayType() { + val list = goodsEntity?.pay_type?.split(",")?.map { it.trim() }?.toList() + val globalPayType = UserConfigManager.getPayType() + if (list?.find { it == "weixin" } != null && globalPayType.find { it == "weixin" } != null) { + binding.tvWxPay.visible() + } else { + binding.tvWxPay.gone() + } + if (list?.find { it == "alipay" } != null && globalPayType.find { it == "alipay" } != null) { + binding.tvAliPay.visible() + } else { + binding.tvAliPay.gone() + } + if (list?.find { it == "bank" } != null && globalPayType.find { it == "bank" } != null) { + binding.tvBankPay.visible() + } else { + binding.tvBankPay.gone() + } + + if (goodsEntity?.pay_type!!.startsWith("weixin") && binding.tvWxPay.isVisible) { + payType = 0 + } + if (goodsEntity?.pay_type!!.startsWith("alipay") && binding.tvAliPay.isVisible) { + payType = 1 + } + if (goodsEntity?.pay_type!!.startsWith("bank") && binding.tvBankPay.isVisible) { + payType = 2 + } + + checkPayType() + } + + private fun initPrivacyTv() { + val spanUtils = SpanUtils.with(binding.tvAgree) + .append("我已阅读并同意") + .append("《会员服务协议规则》") + .setClickSpan(getColor(R.color.color_a6e8f7), false) { + UrlHelper.startUserAgreement(requireContext(), "会员服务协议规则") + } + if (!TextUtils.isEmpty(goodsEntity?.sign_value) && payType == 1) { + spanUtils.append("和") + spanUtils.append("《自动续费服务规则》") + spanUtils.setClickSpan(getColor(R.color.color_a6e8f7), false) { + UrlHelper.startRenewAgreement(requireContext()) + } + } + spanUtils.create() + } + + @SuppressLint("SetTextI18n") + private fun setPrice(price: Float) { + totalPrice = if (price < 0) 0f else price + SpanUtils.with(binding.tvPrice) + .append("¥") + .setFontSize(12, true) + .append(DecimalFormat("0.##").format(totalPrice)) + .append(formatPricePeriod(goodsEntity!!.value)) + .setFontSize(12, true) + .create() + binding.tvSavedPrice.text = "已优惠${DecimalFormat("0.##").format(goodsEntity!!.origin_price.toFloat() - totalPrice)}" + } + + private fun formatPricePeriod(value: String): String { + if (value == "#") { + return "/终生" + } else if (value.endsWith("m")) { + val monthStr = value.replace("m", "") + if (!TextUtils.isEmpty(monthStr)) { + val month = monthStr.toInt() + return if (month >= 12) { + "/${if (month / 12 > 1) "${month / 12}" else ""}年" + } else if (month % 3 == 0) { + "/${if (month / 3 > 1) "${month / 3}" else ""}季" + } else { + "/${if (month > 1) "$month" else ""}月" + } + } + } + return "" + } + + private fun getDateList(dataList: List, selectedWeekTime: Long): ArrayList { + val dateList = ArrayList() + for (i in dataList.indices) { + dateList.add(DateUtils.getDayOfWeekTimeMillisByEndTime(selectedWeekTime, i + 1).getDD()) + } + return dateList + } + + private fun startCountdown() { + countdownDisposable = RxCountDown.countdown(totalSeconds) + .subscribe { + setCountdownTime(it) + if (it == 0L) { + val f = GuideSaleDialog.newInstance() + f.setOnSelectListener { seconds -> + totalSeconds = seconds + startCountdown() + } + f.show(childFragmentManager, GuideSaleDialog::class.java.simpleName) + } + } + } + + //格式化倒计时 + private fun setCountdownTime(seconds: Long) { + val minutes = seconds / 60 + val hours = minutes / 60 + val day = hours / 24 + binding.tvDay.text = String.format("%02d", day) + binding.tvHour.text = if (day > 0) String.format("%02d", hours % 24) else String.format("%02d", hours) + binding.tvMinute.text = String.format("%02d", minutes % 60) + binding.tvSecond.text = String.format("%02d", seconds % 60) + } + + private fun startScroll() { + if (userTipsList.isEmpty() || scrollTask != null) return + scrollTask = Observable.interval(300, 9, TimeUnit.MILLISECONDS) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe { + if (activity != null) { + binding.rvUser.scrollBy(3, 0) + } + } + } + + private fun stopScroll() { + scrollTask?.dispose() + scrollTask = null + } + + override fun onStart() { + startScroll() + super.onStart() + } + + override fun onStop() { + stopScroll() + super.onStop() + } + + override fun onDestroyView() { + countdownDisposable?.dispose() + super.onDestroyView() } @SuppressLint("UnsafeOptInUsageError") diff --git a/app/src/main/java/com/cheng/blzb/ui/fragment/guide/vip/GuideVipIndustryAdapter.kt b/app/src/main/java/com/cheng/blzb/ui/fragment/guide/vip/GuideVipIndustryAdapter.kt new file mode 100644 index 0000000..ec3dd79 --- /dev/null +++ b/app/src/main/java/com/cheng/blzb/ui/fragment/guide/vip/GuideVipIndustryAdapter.kt @@ -0,0 +1,45 @@ +package com.cheng.blzb.ui.fragment.guide.vip + +import android.content.Context +import android.view.View +import android.view.ViewGroup +import android.widget.BaseAdapter +import android.widget.TextView +import com.cheng.blzb.R +import com.cheng.blzb.bean.HotWordEntity +import com.cheng.blzb.common.Constants + + +class GuideVipIndustryAdapter(val context: Context, val data: List): BaseAdapter() { + override fun getCount(): Int { + return data.size + } + + override fun getItem(position: Int): HotWordEntity.Child { + 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_guide_vip_industry, null) + viewHolder = ViewHolder(view) + view.tag = viewHolder + } else { + view = convertView + viewHolder = convertView.tag as ViewHolder + } + viewHolder.tvName.typeface = Constants.ysbth + viewHolder.tvName.text = getItem(position).name + return view + } + + inner class ViewHolder(val view: View) { + val tvName: TextView = view.findViewById(R.id.tv_name) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/cheng/blzb/ui/fragment/guide/vip/GuideVipUserAdapter.kt b/app/src/main/java/com/cheng/blzb/ui/fragment/guide/vip/GuideVipUserAdapter.kt new file mode 100644 index 0000000..ef96469 --- /dev/null +++ b/app/src/main/java/com/cheng/blzb/ui/fragment/guide/vip/GuideVipUserAdapter.kt @@ -0,0 +1,38 @@ +package com.cheng.blzb.ui.fragment.guide.vip + +import android.annotation.SuppressLint +import android.content.Context +import android.view.View +import android.view.ViewGroup +import android.view.ViewGroup.LayoutParams +import android.widget.ImageView +import androidx.constraintlayout.widget.ConstraintLayout +import androidx.recyclerview.widget.RecyclerView +import coil.load +import coil.transform.CircleCropTransformation +import com.chad.library.adapter.base.viewholder.BaseViewHolder +import com.cheng.blzb.R +import com.example.base.utils.DensityUtils + +class GuideVipUserAdapter(val context: Context, val data: MutableList): RecyclerView.Adapter() { + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder { + val view = View.inflate(context, R.layout.listitem_guide_vip_user, null) + val lp = ConstraintLayout.LayoutParams(LayoutParams.WRAP_CONTENT, DensityUtils.dp2px(24f)) + lp.leftMargin = DensityUtils.dp2px(10f) + view.layoutParams = lp + return BaseViewHolder(view) + } + + @SuppressLint("DiscouragedApi") + override fun onBindViewHolder(holder: BaseViewHolder, position: Int) { + holder.getView(R.id.iv_avatar).load(context.resources.getIdentifier("yq_${position % 51}", "mipmap", context.packageName)) { + transformations(CircleCropTransformation()) + } + holder.setText(R.id.tv_content, data[position % data.size]) + } + + override fun getItemCount(): Int { + return if (data.isNotEmpty()) Int.MAX_VALUE else 0 + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/cheng/blzb/ui/fragment/guide/vip/GuideVipViewModel.kt b/app/src/main/java/com/cheng/blzb/ui/fragment/guide/vip/GuideVipViewModel.kt index abf61e0..9108c67 100644 --- a/app/src/main/java/com/cheng/blzb/ui/fragment/guide/vip/GuideVipViewModel.kt +++ b/app/src/main/java/com/cheng/blzb/ui/fragment/guide/vip/GuideVipViewModel.kt @@ -1,27 +1,27 @@ package com.cheng.blzb.ui.fragment.guide.vip import androidx.lifecycle.MutableLiveData -import com.cheng.blzb.bean.AreaEntity -import com.cheng.blzb.bean.GuideTotalBidEntity import com.cheng.blzb.bean.GuideUpdateEntity -import com.cheng.blzb.bean.HotWordEntity +import com.cheng.blzb.bean.OrderPayEntity +import com.cheng.blzb.bean.VipGoodsEntity import com.cheng.blzb.net.ApiFactory import com.example.base.extensions.toast import com.example.base.utils.L import com.example.base.viewmodel.BaseViewModel +import com.google.gson.JsonObject +import okhttp3.RequestBody.Companion.toRequestBody class GuideVipViewModel: BaseViewModel() { - val hotWordLiveData = MutableLiveData>() - val cityLiveData = MutableLiveData>() - val userCityLiveData = MutableLiveData() - val totalLiveData = MutableLiveData() + val goodsListLiveData = MutableLiveData>() + val createOrderLiveData = MutableLiveData() + val payTipsLiveData = MutableLiveData>() val updateLiveData = MutableLiveData>() - fun getHotWordList() { + fun getGoodsList() { launchOnUiTryCatch({ - val response = ApiFactory.apiService.getHotWordList() + val response = ApiFactory.apiService.getGoodsList() if (response.status) { - hotWordLiveData.postValue(response.data) + goodsListLiveData.postValue(response.data) } else toast(response.message, true) }, { setError(it) @@ -29,36 +29,35 @@ class GuideVipViewModel: BaseViewModel() { }) } - fun getCityList() { + fun payCreateOrder(goodsId: String, payType: String) { + showDialog() launchOnUiTryCatch({ - val response = ApiFactory.apiService.getAreaList() + val json = JsonObject() + json.addProperty("goods_id", goodsId) + json.addProperty("pay_type", payType) + json.addProperty("source", "bootpage") + json.addProperty("pay_source", "app") + + val response = ApiFactory.apiService.payCreateOrder(json.toString().toRequestBody()) if (response.status) { - cityLiveData.postValue(response.data) - } else toast(response.message, true) + createOrderLiveData.postValue(response.data) + } else { + toast(response.message, true) + } + dismissDialog() }, { + dismissDialog() setError(it) L.d(it) }) } - fun getUserCity() { + fun getPayUserTips() { launchOnUiTryCatch({ - val response = ApiFactory.apiService.getUserCity() + val response = ApiFactory.apiService.getPayUserTips() if (response.status) { - userCityLiveData.postValue(response.data) - } else toast(response.message, true) - }, { - setError(it) - L.d(it) - }) - } - - fun getTotalBidInfo(keywords: String, cityIds: String, kindNum: String) { - launchOnUiTryCatch({ - val response = ApiFactory.apiService.getTotalBidInfo(keywords, cityIds, kindNum) - if (response.status) { - totalLiveData.postValue(response.data) - } else toast(response.message, true) + payTipsLiveData.postValue(response.data) + } }, { setError(it) L.d(it) @@ -67,7 +66,7 @@ class GuideVipViewModel: BaseViewModel() { fun getUpdateNum() { launchOnUiTryCatch({ - val response = ApiFactory.apiService.getUpdateNum("8") + val response = ApiFactory.apiService.getUpdateNum("7") if (response.status) { updateLiveData.postValue(response.data) } else toast(response.message, true) diff --git a/app/src/main/java/com/cheng/blzb/widget/BarChartView.kt b/app/src/main/java/com/cheng/blzb/widget/BarChartView.kt new file mode 100644 index 0000000..3165fb7 --- /dev/null +++ b/app/src/main/java/com/cheng/blzb/widget/BarChartView.kt @@ -0,0 +1,115 @@ +package com.cheng.blzb.widget + +import android.animation.ValueAnimator +import android.content.Context +import android.util.AttributeSet +import android.view.View +import android.widget.FrameLayout +import android.widget.ImageView +import androidx.constraintlayout.widget.ConstraintLayout +import androidx.core.animation.addListener +import androidx.recyclerview.widget.RecyclerView +import com.chad.library.adapter.base.BaseQuickAdapter +import com.chad.library.adapter.base.viewholder.BaseViewHolder +import com.cheng.blzb.R +import com.example.base.extensions.visible +import com.example.base.utils.DensityUtils +import java.text.DecimalFormat +import kotlin.math.roundToInt + +class BarChartView @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : FrameLayout(context, attrs, defStyleAttr) { + private val xAxisAdapter by lazy { XAxisAdapter() } + + private val yAxisAdapter by lazy { YAxisAdapter() } + + private val yAxisRowCount = 6 + + private var maxValue = 0f + + init { + val view = inflate(context, R.layout.layout_bar_chart, null) + addView(view, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT) + } + + override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec) + + val rvX = findViewById(R.id.rv_x) + rvX.adapter = xAxisAdapter + + val rvY = findViewById(R.id.rv_y) + rvY.adapter = yAxisAdapter + } + + fun setData(xValueList: List) { + val yValueList = mutableListOf() + val rowValue = xValueList.maxBy { it.value }.value / yAxisRowCount + val value = if (rowValue > 10) { + var bigNum = rowValue.toInt().toFloat() + val numLength = rowValue.toInt().toString().length + for (i in 0 until numLength - 1) { + bigNum /= 10 + } + bigNum = (bigNum + 0.5f).roundToInt().toFloat() + for (i in 0 until numLength - 1) { + bigNum *= 10 + } + bigNum + } else rowValue + + for (i in 0 .. yAxisRowCount) { + yValueList.add(0, YAxisValue(i * value)) + } + maxValue = value * yAxisRowCount + + xAxisAdapter.setList(xValueList) + yAxisAdapter.setList(yValueList) + } + + data class XAxisValue(val value: Float, val date: String) + + data class YAxisValue(val value: Float) + + inner class XAxisAdapter : BaseQuickAdapter(R.layout.listitem_bar_chart_x) { + override fun convert(holder: BaseViewHolder, item: XAxisValue) { + holder.setText(R.id.tv_value, "${DecimalFormat("0.#").format(item.value)}") + holder.setText(R.id.tv_date, item.date) + + val lp = holder.getView(R.id.iv_bar).layoutParams as ConstraintLayout.LayoutParams + lp.height = (item.value / maxValue * recyclerView.measuredHeight * yAxisRowCount / (yAxisRowCount + 1)).toInt() - DensityUtils.dp2px(6f) + (holder.getView(R.id.iv_bar)).layoutParams = lp +// startAnim(holder.getView(R.id.iv_bar), item) + } + + private fun startAnim(barView: View, item: XAxisValue) { + val valueAnim = ValueAnimator.ofFloat(0f, 1f) + valueAnim.addUpdateListener { animator -> + val value = animator.animatedValue as Float + val itemHeight = (item.value / maxValue * recyclerView.measuredHeight * yAxisRowCount / (yAxisRowCount + 1)).toInt() - DensityUtils.dp2px(6f) + val lp = barView.layoutParams as ConstraintLayout.LayoutParams + lp.height = (value * itemHeight).toInt() + barView.layoutParams = lp + } + valueAnim.addListener(onStart = { + barView.visible() + }) + valueAnim.duration = 1000 + valueAnim.start() + } + } + + inner class YAxisAdapter() : BaseQuickAdapter(R.layout.listitem_bar_chart_y) { + + override fun convert(holder: BaseViewHolder, item: YAxisValue) { + val lp = holder.itemView.layoutParams as RecyclerView.LayoutParams + lp.height = recyclerView.measuredHeight / (yAxisRowCount + 1) + holder.itemView.layoutParams = lp + + holder.setText(R.id.tv_value, "${DecimalFormat("0.#").format(item.value)}") + } + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_ff8929_cor4.xml b/app/src/main/res/drawable/shape_ff8929_cor4.xml new file mode 100644 index 0000000..d29da61 --- /dev/null +++ b/app/src/main/res/drawable/shape_ff8929_cor4.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_guide_vip_time_bg.xml b/app/src/main/res/drawable/shape_guide_vip_time_bg.xml new file mode 100644 index 0000000..acfa2cb --- /dev/null +++ b/app/src/main/res/drawable/shape_guide_vip_time_bg.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_guide_vip_user_bg.xml b/app/src/main/res/drawable/shape_guide_vip_user_bg.xml new file mode 100644 index 0000000..666f901 --- /dev/null +++ b/app/src/main/res/drawable/shape_guide_vip_user_bg.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_vip_tag_bg.xml b/app/src/main/res/drawable/shape_vip_tag_bg.xml index 32dfb4a..d0a90b5 100644 --- a/app/src/main/res/drawable/shape_vip_tag_bg.xml +++ b/app/src/main/res/drawable/shape_vip_tag_bg.xml @@ -1,7 +1,5 @@ - + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_guide_sale.xml b/app/src/main/res/layout/dialog_guide_sale.xml new file mode 100644 index 0000000..ae9cff0 --- /dev/null +++ b/app/src/main/res/layout/dialog_guide_sale.xml @@ -0,0 +1,264 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_guide_vip.xml b/app/src/main/res/layout/fragment_guide_vip.xml index 91592c4..effbee0 100644 --- a/app/src/main/res/layout/fragment_guide_vip.xml +++ b/app/src/main/res/layout/fragment_guide_vip.xml @@ -1,31 +1,718 @@ + android:background="@mipmap/ic_guide_vip_bg"> + android:layout_height="0dp" + android:layout_marginBottom="@dimen/dp_20" + android:fillViewport="true" + app:layout_constraintBottom_toTopOf="@id/layout_pay_btn" + app:layout_constraintTop_toTopOf="parent"> + android:layout_height="wrap_content"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + android:src="@mipmap/ic_guide_vip_close" + android:visibility="invisible" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toTopOf="parent" + tools:visibility="visible" /> \ No newline at end of file diff --git a/app/src/main/res/layout/layout_bar_chart.xml b/app/src/main/res/layout/layout_bar_chart.xml new file mode 100644 index 0000000..c798eea --- /dev/null +++ b/app/src/main/res/layout/layout_bar_chart.xml @@ -0,0 +1,28 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/listitem_bar_chart_x.xml b/app/src/main/res/layout/listitem_bar_chart_x.xml new file mode 100644 index 0000000..75d3a12 --- /dev/null +++ b/app/src/main/res/layout/listitem_bar_chart_x.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/listitem_bar_chart_y.xml b/app/src/main/res/layout/listitem_bar_chart_y.xml new file mode 100644 index 0000000..56f3566 --- /dev/null +++ b/app/src/main/res/layout/listitem_bar_chart_y.xml @@ -0,0 +1,25 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/listitem_guide_vip_goods.xml b/app/src/main/res/layout/listitem_guide_vip_goods.xml new file mode 100644 index 0000000..db3166a --- /dev/null +++ b/app/src/main/res/layout/listitem_guide_vip_goods.xml @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/listitem_guide_vip_industry.xml b/app/src/main/res/layout/listitem_guide_vip_industry.xml new file mode 100644 index 0000000..f4eb7f9 --- /dev/null +++ b/app/src/main/res/layout/listitem_guide_vip_industry.xml @@ -0,0 +1,16 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/listitem_guide_vip_user.xml b/app/src/main/res/layout/listitem_guide_vip_user.xml new file mode 100644 index 0000000..e2b9f5f --- /dev/null +++ b/app/src/main/res/layout/listitem_guide_vip_user.xml @@ -0,0 +1,32 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-xxhdpi/ic_bar_chart.9.png b/app/src/main/res/mipmap-xxhdpi/ic_bar_chart.9.png new file mode 100644 index 0000000..7339334 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_bar_chart.9.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_bar_chart_top.webp b/app/src/main/res/mipmap-xxhdpi/ic_bar_chart_top.webp new file mode 100644 index 0000000..2559dce Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_bar_chart_top.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_guide_pay_checked.webp b/app/src/main/res/mipmap-xxhdpi/ic_guide_pay_checked.webp new file mode 100644 index 0000000..5022362 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_guide_pay_checked.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_guide_pay_default.webp b/app/src/main/res/mipmap-xxhdpi/ic_guide_pay_default.webp new file mode 100644 index 0000000..a7f8a55 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_guide_pay_default.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_guide_sale_dialog_bg1.webp b/app/src/main/res/mipmap-xxhdpi/ic_guide_sale_dialog_bg1.webp new file mode 100644 index 0000000..9840c18 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_guide_sale_dialog_bg1.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_guide_sale_dialog_bg2.webp b/app/src/main/res/mipmap-xxhdpi/ic_guide_sale_dialog_bg2.webp new file mode 100644 index 0000000..eaca02f Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_guide_sale_dialog_bg2.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_guide_sale_dialog_bg3.webp b/app/src/main/res/mipmap-xxhdpi/ic_guide_sale_dialog_bg3.webp new file mode 100644 index 0000000..ce69acf Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_guide_sale_dialog_bg3.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_guide_sale_dialog_bg4.webp b/app/src/main/res/mipmap-xxhdpi/ic_guide_sale_dialog_bg4.webp new file mode 100644 index 0000000..27d576f Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_guide_sale_dialog_bg4.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_guide_sale_dialog_bg5.webp b/app/src/main/res/mipmap-xxhdpi/ic_guide_sale_dialog_bg5.webp new file mode 100644 index 0000000..836048f Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_guide_sale_dialog_bg5.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_guide_sale_dialog_btn.webp b/app/src/main/res/mipmap-xxhdpi/ic_guide_sale_dialog_btn.webp new file mode 100644 index 0000000..83c7b64 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_guide_sale_dialog_btn.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_guide_sale_dialog_icon1.webp b/app/src/main/res/mipmap-xxhdpi/ic_guide_sale_dialog_icon1.webp new file mode 100644 index 0000000..b908215 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_guide_sale_dialog_icon1.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_guide_sale_dialog_icon2.webp b/app/src/main/res/mipmap-xxhdpi/ic_guide_sale_dialog_icon2.webp new file mode 100644 index 0000000..224faa4 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_guide_sale_dialog_icon2.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_guide_sale_dialog_icon3.webp b/app/src/main/res/mipmap-xxhdpi/ic_guide_sale_dialog_icon3.webp new file mode 100644 index 0000000..6f69493 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_guide_sale_dialog_icon3.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_guide_sale_dialog_icon4.webp b/app/src/main/res/mipmap-xxhdpi/ic_guide_sale_dialog_icon4.webp new file mode 100644 index 0000000..cbab860 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_guide_sale_dialog_icon4.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_guide_vip_btn_bg.webp b/app/src/main/res/mipmap-xxhdpi/ic_guide_vip_btn_bg.webp new file mode 100644 index 0000000..2d33718 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_guide_vip_btn_bg.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_guide_vip_fire.webp b/app/src/main/res/mipmap-xxhdpi/ic_guide_vip_fire.webp new file mode 100644 index 0000000..ccbd84c Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_guide_vip_fire.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_guide_vip_goods_checked.webp b/app/src/main/res/mipmap-xxhdpi/ic_guide_vip_goods_checked.webp new file mode 100644 index 0000000..3c5fd31 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_guide_vip_goods_checked.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_guide_vip_goods_default.webp b/app/src/main/res/mipmap-xxhdpi/ic_guide_vip_goods_default.webp new file mode 100644 index 0000000..fa848c1 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_guide_vip_goods_default.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_guide_vip_industry_bg.webp b/app/src/main/res/mipmap-xxhdpi/ic_guide_vip_industry_bg.webp new file mode 100644 index 0000000..f6f60ab Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_guide_vip_industry_bg.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_guide_vip_info_bg.9.png b/app/src/main/res/mipmap-xxhdpi/ic_guide_vip_info_bg.9.png new file mode 100644 index 0000000..3db9451 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_guide_vip_info_bg.9.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_guide_vip_info_line.webp b/app/src/main/res/mipmap-xxhdpi/ic_guide_vip_info_line.webp new file mode 100644 index 0000000..95bfb69 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_guide_vip_info_line.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_guide_vip_tab_checked.webp b/app/src/main/res/mipmap-xxhdpi/ic_guide_vip_tab_checked.webp new file mode 100644 index 0000000..60bbd4e Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_guide_vip_tab_checked.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_guide_vip_tab_default.webp b/app/src/main/res/mipmap-xxhdpi/ic_guide_vip_tab_default.webp new file mode 100644 index 0000000..e0c16d1 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_guide_vip_tab_default.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_guide_vip_total_info_icon1.webp b/app/src/main/res/mipmap-xxhdpi/ic_guide_vip_total_info_icon1.webp new file mode 100644 index 0000000..cebc9e4 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_guide_vip_total_info_icon1.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_guide_vip_total_info_icon2.webp b/app/src/main/res/mipmap-xxhdpi/ic_guide_vip_total_info_icon2.webp new file mode 100644 index 0000000..d723297 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_guide_vip_total_info_icon2.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_guide_vip_total_info_icon3.webp b/app/src/main/res/mipmap-xxhdpi/ic_guide_vip_total_info_icon3.webp new file mode 100644 index 0000000..46e5452 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_guide_vip_total_info_icon3.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_guide_vip_total_info_icon4.webp b/app/src/main/res/mipmap-xxhdpi/ic_guide_vip_total_info_icon4.webp new file mode 100644 index 0000000..260731d Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_guide_vip_total_info_icon4.webp differ diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 7e5419e..17317b0 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -127,4 +127,12 @@ #FF9234 #E3FAE7 #FFEDE7 + #9BBBDF + #04214F + #A6ACB5 + #A6E8F7 + #202020 + #20F3E6 + #05ACE8 + #6DD9F2 \ No newline at end of file diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index fecff7c..1031aa0 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -92,5 +92,6 @@ 66dp 190dp 180dp + 280dp \ No newline at end of file diff --git a/base/src/main/java/com/example/base/extensions/LongExtensions.kt b/base/src/main/java/com/example/base/extensions/LongExtensions.kt index cea2114..74f65b2 100644 --- a/base/src/main/java/com/example/base/extensions/LongExtensions.kt +++ b/base/src/main/java/com/example/base/extensions/LongExtensions.kt @@ -118,6 +118,11 @@ fun Long.getHHMM(): String { return dateFormat.format(this) } +fun Long.getDD(): String { + val dateFormat = SimpleDateFormat("dd日", Locale.CHINA) + return dateFormat.format(this) +} + fun Long.getYYYYMMDDHHMM(format: String): String { val dateFormat = SimpleDateFormat(format, Locale.CHINA) return dateFormat.format(this)