123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333 |
- package com.develop.common.widget
- import android.annotation.SuppressLint
- import android.content.Context
- import android.graphics.Color
- import android.util.AttributeSet
- import android.util.Log
- import android.view.View
- import android.view.animation.AlphaAnimation
- import android.view.animation.Animation
- import android.widget.TextView
- import androidx.constraintlayout.widget.ConstraintLayout
- import androidx.recyclerview.widget.LinearSnapHelper
- import com.develop.base.ext.isBrand062
- import com.develop.base.ext.updateText
- import com.develop.common.R
- import com.develop.common.databinding.TimePickerViewBinding
- import com.drake.brv.utils.models
- import com.drake.brv.utils.setup
- class TimePickerView : ConstraintLayout {
- private var binding: TimePickerViewBinding
- private var timeColor = Color.WHITE
- private val firstData = mutableListOf<String>()
- private val secondData = mutableListOf<String>()
- private var firstTimePos = 0
- private var secondTimePos = 0
- private var currentTotalSecond = 0
- private var maxTime = 8 * 60 * 60
- private var minTime = 0
- private var firstUnit: String? = null
- private var secondUnit: String? = null
- private var is062 = false
- var onTimePickerCallback: OnTimePickerCallback? = null
- private var firstManager: ScrollLinearManager
- private var secondManager: ScrollLinearManager
- private val animation: Animation = AlphaAnimation(1f, 0.2f)
- private var isCanChange = true
- constructor(context: Context) : super(context) {}
- constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
- initAttrs(context, attrs)
- }
- constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
- context,
- attrs,
- defStyleAttr
- ) {
- initAttrs(context, attrs)
- }
- init {
- val root = View.inflate(context, R.layout.time_picker_view, this)
- binding = TimePickerViewBinding.bind(root)
- is062 = isBrand062()
- repeat(60) { idx ->
- if (idx < 10) {
- firstData.add("0$idx")
- secondData.add("0$idx")
- } else {
- firstData.add(idx.toString())
- secondData.add(idx.toString())
- }
- }
- repeat(99) { idx ->
- if (idx == 0) {
- return@repeat
- }
- if (idx < 10) {
- firstData.add("0$idx")
- } else {
- firstData.add(idx.toString())
- }
- }
- firstManager = ScrollLinearManager(context)
- secondManager = ScrollLinearManager(context)
- }
- @SuppressLint("ClickableViewAccessibility")
- private fun initAttrs(context: Context, attrs: AttributeSet?) {
- context.obtainStyledAttributes(attrs, R.styleable.TimePickerView).apply {
- timeColor = getColor(R.styleable.TimePickerView_time_color, Color.WHITE)
- }.recycle()
- if (is062) timeColor = Color.WHITE
- binding.tvDotTime.setTextColor(timeColor)
- binding.tvFirstBottom.setTextColor(timeColor)
- binding.tvSecondBottom.setTextColor(timeColor)
- binding.tvSetTimeFirst.apply {
- layoutManager = firstManager
- setup {
- addType<String>(R.layout.item_cook_time)
- onBind {
- val tvTime = findView<TextView>(R.id.tv_time)
- tvTime.updateText(getModel())
- tvTime.setTextColor(timeColor)
- }
- }
- }.models = firstData
- binding.tvSetTimeSecond.apply {
- layoutManager = secondManager
- setup {
- addType<String>(R.layout.item_cook_time)
- onBind {
- val tvTime = findView<TextView>(R.id.tv_time)
- tvTime.updateText(getModel())
- tvTime.setTextColor(timeColor)
- }
- }
- }.models = secondData
- binding.tvSetTimeFirst.addOnScrollListener(LinearPositionObserver { pos ->
- firstTimePos = pos
- checkChangeTimeScale(pos)
- updateDisplayTime()
- })
- binding.tvSetTimeFirst.setOnTouchListener { view, motionEvent ->
- if (isCanChange){
- stopAlphaAnim()
- alphaAnim(binding.tvSetTimeFirst)
- onTimePickerCallback?.onTimePickerTouchFirst(1)
- }
- false
- }
- binding.tvSetTimeSecond.addOnScrollListener(LinearPositionObserver { pos ->
- secondTimePos = pos
- updateDisplayTime()
- })
- binding.tvSetTimeSecond.setOnTouchListener { view, motionEvent ->
- if (isCanChange){
- stopAlphaAnim()
- alphaAnim(binding.tvSetTimeSecond)
- onTimePickerCallback?.onTimePickerTouchFirst(2)
- }
- false
- }
- LinearSnapHelper().attachToRecyclerView(binding.tvSetTimeFirst)
- LinearSnapHelper().attachToRecyclerView(binding.tvSetTimeSecond)
- }
- private fun alphaAnim(view: View) {
- animation.duration = 600
- animation.repeatCount = -1
- view.startAnimation(animation)
- }
- fun stopAlphaAnim() {
- binding.tvSetTimeFirst.clearAnimation()
- binding.tvSetTimeSecond.clearAnimation()
- }
- private fun checkChangeTimeScale(firstPos: Int) {
- val firstUnit: String
- val secondUnit: String
- if (firstPos >= 60) {
- firstUnit = resources.getString(R.string.mode_hour)
- secondUnit = resources.getString(R.string.mode_min)
- } else {
- firstUnit = resources.getString(R.string.mode_min)
- secondUnit = resources.getString(R.string.mode_sec)
- }
- if (firstUnit != binding.tvFirstBottom.text) {
- binding.tvFirstBottom.text = firstUnit
- }
- if (secondUnit != binding.tvSecondBottom.text) {
- binding.tvSecondBottom.text = secondUnit
- }
- this.firstUnit = firstUnit;
- this.secondUnit = secondUnit;
- }
- private fun updateDisplayTime() {
- checkLimitTime(true)
- if (firstTimePos >= 60) {
- //处理时间 的 小时超出自动换最大值
- var maxhoursTime = maxTime / 3600
- var hoursTime = 0
- var secondTime = (maxTime - (maxhoursTime * 3600)) / 60
- if ((firstTimePos - 60 + 1) > maxhoursTime) {
- hoursTime = maxhoursTime
- } else {
- hoursTime = firstTimePos - 60 + 1
- if (secondTimePos < secondTime) {
- secondTime = secondTimePos
- }
- }
- setTimeInternal(
- hoursTime,
- secondTime,
- 0,
- true,
- setByUser = true
- )
- } else {
- setTimeInternal(
- 0,
- firstTimePos,
- secondTimePos,
- true,
- setByUser = true
- )
- }
- }
- @SuppressLint("SetTextI18n")
- fun setTimeInternal(
- hours: Int,
- minute: Int,
- second: Int,
- changeSetting: Boolean,
- setByUser: Boolean = false
- ) {
- val firstTime: Int
- val secondTime: Int
- if (hours > 0 || minute >= 60) {
- checkChangeTimeScale(80)
- firstTime = (hours + minute / 60)
- secondTime = (minute % 60)
- } else {
- checkChangeTimeScale(30)
- firstTime = minute
- secondTime = second
- }
- binding.let {
- if (changeSetting) {
- firstTimePos = if (hours > 0) {
- 59 + firstTime
- } else {
- firstTime
- }
- secondTimePos = secondTime
- it.tvSetTimeFirst.scrollToPosition(firstTimePos)
- it.tvSetTimeSecond.scrollToPosition(secondTimePos)
- }
- val firstStr = if (firstTime < 10) {
- "0$firstTime"
- } else {
- firstTime.toString()
- }
- val secondStr = if (secondTime < 10) {
- "0$secondTime"
- } else {
- secondTime.toString()
- }
- onTimePickerCallback?.onTimePicker(
- hours,
- minute,
- second,
- "${firstStr}:${secondStr}",
- setByUser
- )
- }
- }
- /**
- * 设置最大最小时间
- * 单位秒
- */
- fun setTimeRange(minTime: Int, maxTime: Int) {
- this.minTime = minTime
- this.maxTime = maxTime
- checkLimitTime()
- }
- private fun checkLimitTime(setByUser: Boolean = false) {
- val minMinutes = (minTime / 60 % 60)
- val minHours = (minTime / 3600)
- val minSeconds = minTime % 60
- val maxMinutes = (maxTime / 60 % 60)
- val maxHours = (maxTime / 3600)
- val maxSeconds = maxTime % 60
- val currentSeconds: Int = if (firstUnit === "hour") {
- val indexRe = firstData[firstTimePos]
- val hours = if (indexRe.startsWith("0")) {
- indexRe.substring(1, 2).toInt()
- } else {
- indexRe.toInt()
- }
- hours * 60 * 60 + secondTimePos * 60
- } else {
- firstTimePos * 60 + secondTimePos
- }
- if (currentSeconds < minTime) {
- setTimeInternal(
- minHours,
- minMinutes,
- minSeconds,
- changeSetting = true,
- setByUser = setByUser
- )
- } else if (currentSeconds > maxTime) {
- setTimeInternal(
- maxHours,
- maxMinutes,
- maxSeconds,
- changeSetting = true,
- setByUser = setByUser
- )
- }
- }
- fun setTargetTime(time: String) {
- binding.tvTargetTime.visibility = View.VISIBLE
- binding.tvTargetTime.text = time
- }
- fun hideTargetTime() {
- binding.tvTargetTime.visibility = View.INVISIBLE
- }
- fun isTimeCanChange(isCanChange: Boolean) {
- this.isCanChange = isCanChange
- binding.tvSetTimeFirst.isEnabled = !isCanChange
- binding.tvSetTimeSecond.isEnabled = !isCanChange
- firstManager.setCanScrollVertically(isCanChange)
- secondManager.setCanScrollVertically(isCanChange)
- }
- interface OnTimePickerCallback {
- fun onTimePicker(hours: Int, minute: Int, second: Int, time: String, setByUser: Boolean)
- fun onTimePickerTouchFirst(where: Int)
- }
- }
|