Browse Source

提交人:jtm
提交内容:菜谱烹饪步骤

江天明 2 years ago
parent
commit
5065b66c03
30 changed files with 3138 additions and 40 deletions
  1. 37 0
      BusinessCommon/src/main/java/com/develop/common/dialog/CookStepCompleteDialog.kt
  2. 1 1
      BusinessCommon/src/main/java/com/develop/common/widget/DownloadFailedDialog.kt
  3. 35 0
      BusinessCommon/src/main/java/com/develop/common/dialog/NoteEditDialog.kt
  4. 28 0
      BusinessCommon/src/main/java/com/develop/common/dialog/PotCoverUnlockedDialog.kt
  5. 1 0
      BusinessCommon/src/main/java/com/develop/common/dialog/RecipeDeleteConfirmDialog.kt
  6. 10 10
      BusinessCommon/src/main/java/com/develop/common/widget/ShareQRCodeDialog.kt
  7. 49 0
      BusinessCommon/src/main/java/com/develop/common/widget/CookProgressDrawable.kt
  8. 25 14
      BusinessCommon/src/main/java/com/develop/common/widget/FoodContentView.kt
  9. BIN
      BusinessCommon/src/main/res/drawable-xxxhdpi/ic_wifi_0.png
  10. BIN
      BusinessCommon/src/main/res/drawable-xxxhdpi/ic_wifi_1.png
  11. BIN
      BusinessCommon/src/main/res/drawable-xxxhdpi/ic_wifi_2.png
  12. BIN
      BusinessCommon/src/main/res/drawable-xxxhdpi/ic_wifi_3.png
  13. BIN
      BusinessCommon/src/main/res/drawable-xxxhdpi/ic_wifi_4.png
  14. 52 0
      BusinessCommon/src/main/res/layout/dialog_cook_step_complete.xml
  15. 68 0
      BusinessCommon/src/main/res/layout/dialog_pot_cover_unlocked.xml
  16. 36 0
      BusinessCommon/src/main/res/layout/item_cook_details.xml
  17. 71 0
      BusinessCommon/src/main/res/layout/item_note_dialog.xml
  18. 2 0
      BusinessStep/src/main/AndroidManifest.xml
  19. 1 1
      BusinessStep/src/main/java/com/develop/step/ui/ModesDetailActivity.kt
  20. 881 0
      BusinessStep/src/main/java/com/develop/step/ui/cook_step/CookStepActivity.kt
  21. 443 0
      BusinessStep/src/main/java/com/develop/step/ui/cook_step/CookStepBaseActivity.kt
  22. 29 0
      BusinessStep/src/main/java/com/develop/step/ui/cook_step/model/CookStepStatus.kt
  23. 135 0
      BusinessStep/src/main/java/com/develop/step/ui/cook_step/model/CookStepUiData.kt
  24. 15 14
      BusinessStep/src/main/java/com/develop/step/ui/recipes_detail/CookDetailActivity.kt
  25. 96 0
      BusinessStep/src/main/java/com/develop/step/ui/recipes_detail/CookEvaluateActivity.kt
  26. 157 0
      BusinessStep/src/main/java/com/develop/step/viewmodel/CookStepViewModel.kt
  27. 120 0
      BusinessStep/src/main/res/layout/activity_cook_evaluate.xml
  28. 192 0
      BusinessStep/src/main/res/layout/activity_cook_step_base.xml
  29. 432 0
      BusinessStep/src/main/res/layout/item_cook_controller.xml
  30. 222 0
      libBase/src/main/java/com/develop/base/util/MusicBackPlayerUtil.java

+ 37 - 0
BusinessCommon/src/main/java/com/develop/common/dialog/CookStepCompleteDialog.kt

@@ -0,0 +1,37 @@
+package com.develop.common.dialog
+
+import android.content.DialogInterface
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import com.develop.base.mvvm.FullScreenTransparentDialog
+import com.develop.common.databinding.DialogCookStepCompleteBinding
+
+class CookStepCompleteDialog(
+    var clickOk: (() -> Unit)?
+): FullScreenTransparentDialog() {
+
+    private lateinit var binding: DialogCookStepCompleteBinding
+
+    override fun onCreateView(
+        inflater: LayoutInflater,
+        container: ViewGroup?,
+        savedInstanceState: Bundle?
+    ): View {
+        binding = DialogCookStepCompleteBinding.inflate(
+            inflater, container, false
+        )
+        binding.tvOk.setOnClickListener {
+            clickOk?.invoke()
+              removeSelf()
+        }
+        return binding.root
+    }
+
+    override fun onDismiss(dialog: DialogInterface) {
+        super.onDismiss(dialog)
+        clickOk = null
+    }
+
+}

+ 1 - 1
BusinessCommon/src/main/java/com/develop/common/widget/DownloadFailedDialog.kt

@@ -1,4 +1,4 @@
-package com.develop.common.widget
+package com.develop.common.dialog
 
 import android.os.Bundle
 import android.view.LayoutInflater

+ 35 - 0
BusinessCommon/src/main/java/com/develop/common/dialog/NoteEditDialog.kt

@@ -0,0 +1,35 @@
+package com.develop.common.dialog
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import com.develop.base.mvvm.FullScreenTransparentDialog
+import com.develop.common.databinding.ItemNoteDialogBinding
+
+
+class NoteEditDialog: FullScreenTransparentDialog() {
+
+    private lateinit var binding: ItemNoteDialogBinding
+
+    override fun onCreateView(
+        inflater: LayoutInflater,
+        container: ViewGroup?,
+        savedInstanceState: Bundle?
+    ): View {
+        binding = ItemNoteDialogBinding.inflate(
+            inflater, container, false
+        )
+        binding.root.setOnClickListener {
+              removeSelf()
+        }
+        binding.viewComplete.setOnClickListener {
+              removeSelf()
+        }
+        binding.viewEdit.setOnClickListener {
+              removeSelf()
+        }
+        return binding.root
+    }
+
+}

+ 28 - 0
BusinessCommon/src/main/java/com/develop/common/dialog/PotCoverUnlockedDialog.kt

@@ -0,0 +1,28 @@
+package com.develop.common.dialog
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import com.develop.base.mvvm.FullScreenTransparentDialog
+import com.develop.common.databinding.DialogPotCoverUnlockedBinding
+
+class PotCoverUnlockedDialog: FullScreenTransparentDialog() {
+
+    private lateinit var binding: DialogPotCoverUnlockedBinding
+
+    override fun onCreateView(
+        inflater: LayoutInflater,
+        container: ViewGroup?,
+        savedInstanceState: Bundle?
+    ): View {
+        binding = DialogPotCoverUnlockedBinding.inflate(
+            inflater, container, false
+        )
+        binding.ivCancel.setOnClickListener {
+              removeSelf()
+        }
+        return binding.root
+    }
+
+}

+ 1 - 0
BusinessCommon/src/main/java/com/develop/common/dialog/RecipeDeleteConfirmDialog.kt

@@ -24,6 +24,7 @@ class RecipeDeleteConfirmDialog(
         )
         binding.tvYes.setOnClickListener {
             onConfirm()
+            removeSelf()
         }
         binding.tvCancel.setOnClickListener {
               removeSelf()

+ 10 - 10
BusinessCommon/src/main/java/com/develop/common/widget/ShareQRCodeDialog.kt

@@ -1,4 +1,4 @@
-package com.develop.common.widget
+package com.develop.common.dialog
 
 import android.os.Bundle
 import android.view.LayoutInflater
@@ -11,10 +11,10 @@ import com.develop.base.util.ThreadUtils
 import com.develop.common.databinding.DialogShareQrCodeBinding
 import com.develop.common.utils.QRCodeUtils
 
-class ShareQRCodeDialog(private val recipeNum: String): FullScreenTransparentDialog() {
+class ShareQRCodeDialog : FullScreenTransparentDialog() {
 
     private lateinit var binding: DialogShareQrCodeBinding
-
+    var recipeNum: String = ""
     override fun onCreateView(
         inflater: LayoutInflater,
         container: ViewGroup?,
@@ -23,14 +23,14 @@ class ShareQRCodeDialog(private val recipeNum: String): FullScreenTransparentDia
         binding = DialogShareQrCodeBinding.inflate(inflater, container, false)
         binding.ivQrCode.viewTreeObserver.addOnPreDrawListener(
             object : ViewTreeObserver.OnPreDrawListener {
-            override fun onPreDraw(): Boolean {
-                binding.ivQrCode.viewTreeObserver.removeOnPreDrawListener(this)
-                loadQRCode(binding.ivQrCode.width, binding.ivQrCode.height)
-                return false
-            }
-        })
+                override fun onPreDraw(): Boolean {
+                    binding.ivQrCode.viewTreeObserver.removeOnPreDrawListener(this)
+                    loadQRCode(binding.ivQrCode.width, binding.ivQrCode.height)
+                    return false
+                }
+            })
         binding.ivCancel.setOnClickListener {
-              removeSelf()
+            removeSelf()
         }
         return binding.root
     }

+ 49 - 0
BusinessCommon/src/main/java/com/develop/common/widget/CookProgressDrawable.kt

@@ -0,0 +1,49 @@
+package com.develop.common.widget
+
+import android.graphics.Canvas
+import android.graphics.ColorFilter
+import android.graphics.Paint
+import android.graphics.PixelFormat
+import android.graphics.drawable.Drawable
+
+class CookProgressDrawable: Drawable() {
+
+    private var stepCount = 0
+    private var stepIndex = 0
+    private val bgColor = 0xffE5E5E5.toInt()
+    private val pgColor = 0xffE60012.toInt()
+    private val paint = Paint(Paint.ANTI_ALIAS_FLAG)
+    init {
+        paint.color = pgColor
+        paint.style = Paint.Style.FILL
+    }
+
+    override fun draw(canvas: Canvas) {
+        canvas.drawColor(bgColor)
+        if (stepCount == 0) {
+            return
+        }
+        val width = bounds.width()
+        val height = bounds.height()
+        val length = (stepIndex + 1) / stepCount.toFloat() * width
+        canvas.drawRect(0f, 0f, length, height.toFloat(), paint)
+    }
+
+    override fun setAlpha(alpha: Int) {
+        
+    }
+
+    override fun setColorFilter(colorFilter: ColorFilter?) {
+        
+    }
+
+    override fun getOpacity(): Int {
+        return PixelFormat.TRANSLUCENT
+    }
+
+    fun setStepState(stepIndex: Int, stepCount: Int) {
+        this.stepIndex = stepIndex
+        this.stepCount = stepCount
+        invalidateSelf()
+    }
+}

+ 25 - 14
BusinessCommon/src/main/java/com/develop/common/widget/FoodContentView.kt

@@ -73,10 +73,18 @@ class FoodContentView : RelativeLayout {
         val isNetRecipes = content.isNetRecipes
         val hasDownload = content.hasDownloaded
         val isLike = content.isLike
-        val cover = if (isNetRecipes && !content.hasDownloaded) {
-            content.cover
+        val cover = if (isFoodList) {
+            if (isNetRecipes && !content.hasDownloaded) {
+                content.cover
+            } else {
+                FoodDataProvider.getResourcePath(content.cover.toString())
+            }
         } else {
-            FoodDataProvider.getResourcePath(content.cover.toString())
+            if (isNetRecipes) {
+                content.cover
+            } else {
+                FoodDataProvider.getResourcePath(content.cover.toString())
+            }
         }
         val dp30 = (com.develop.base.R.dimen.convert_30px).resId2Dimension()
         binding.apply {
@@ -89,19 +97,22 @@ class FoodContentView : RelativeLayout {
                 setCommentNumber(content.useNum.toString())
             }
             tvTimeAndLevel.updateText("${content.time}・${content.level}")
-            if (hasDownload) {
-                ivLike.setBackgroundResource(R.drawable.ic_delete)
-            } else {
-                if (isNetRecipes) {
-                    ivNet.visibility = View.VISIBLE
+            if (isFoodList) {
+                if (hasDownload) {
+                    ivLike.setBackgroundResource(R.drawable.ic_delete)
                 } else {
-                    ivNet.visibility = View.GONE
+                    if (isNetRecipes) {
+                        ivNet.visibility = View.VISIBLE
+                    } else {
+                        ivNet.visibility = View.GONE
+                    }
                 }
-            }
-            if (isLike) {
-                ivLike.load(R.drawable.ic_like)
             } else {
-                ivLike.load(R.drawable.ic_unlike)
+                if (isLike) {
+                    ivLike.load(R.drawable.ic_like)
+                } else {
+                    ivLike.load(R.drawable.ic_unlike)
+                }
             }
             //喜欢点击
             likeLayout.setOnClickListener {
@@ -141,7 +152,7 @@ class FoodContentView : RelativeLayout {
 
                                     }
                                 }
-                            show(supportFragmentManager, "cancelConfirmDialog")
+                            showDialog(supportFragmentManager, "cancelConfirmDialog")
                         }
                     }
                 } else {

BIN
BusinessCommon/src/main/res/drawable-xxxhdpi/ic_wifi_0.png


BIN
BusinessCommon/src/main/res/drawable-xxxhdpi/ic_wifi_1.png


BIN
BusinessCommon/src/main/res/drawable-xxxhdpi/ic_wifi_2.png


BIN
BusinessCommon/src/main/res/drawable-xxxhdpi/ic_wifi_3.png


BIN
BusinessCommon/src/main/res/drawable-xxxhdpi/ic_wifi_4.png


+ 52 - 0
BusinessCommon/src/main/res/layout/dialog_cook_step_complete.xml

@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    tools:background="#444">
+
+    <RelativeLayout
+        android:layout_width="@dimen/convert_780px"
+        android:layout_height="@dimen/convert_720px"
+        android:layout_gravity="center"
+        android:background="@drawable/bg_icon_page">
+
+        <TextView
+            android:id="@+id/tv_finish"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/finish"
+            android:textSize="@dimen/convert_90px"
+            android:textColor="#E60012"
+            android:includeFontPadding="false"
+            android:layout_marginTop="@dimen/convert_78px"
+            android:layout_centerHorizontal="true"/>
+
+        <ImageView
+            android:id="@+id/iv_cancel"
+            android:layout_width="@dimen/convert_150px"
+            android:layout_height="@dimen/convert_150px"
+            android:layout_centerHorizontal="true"
+            android:src="@drawable/ic_cook_step_complete"
+            android:scaleType="fitCenter"
+            android:layout_below="@+id/tv_finish"
+            android:layout_marginTop="@dimen/convert_98px"/>
+
+        <TextView
+            android:id="@+id/tv_ok"
+            android:layout_width="@dimen/convert_300px"
+            android:layout_height="@dimen/convert_120px"
+            android:background="@drawable/bg_cook_step_ok"
+            android:text="@string/ok"
+            android:textColor="#ffffff"
+            android:gravity="center"
+            android:textSize="@dimen/convert_54px"
+            android:layout_centerHorizontal="true"
+            android:layout_below="@+id/iv_cancel"
+            android:layout_marginTop="@dimen/convert_98px"/>
+
+    </RelativeLayout>
+
+
+</FrameLayout>

+ 68 - 0
BusinessCommon/src/main/res/layout/dialog_pot_cover_unlocked.xml

@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    tools:background="#444">
+
+    <RelativeLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center">
+
+        <LinearLayout
+            android:id="@+id/cl_layer"
+            android:layout_width="@dimen/convert_780px"
+            android:layout_height="wrap_content"
+            android:background="@drawable/bg_icon_page"
+            android:paddingBottom="@dimen/convert_137px"
+            android:orientation="vertical"
+            android:gravity="center_horizontal">
+
+            <TextView
+                android:id="@+id/tv_finish"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/warning"
+                android:textSize="@dimen/convert_90px"
+                android:textColor="#E60012"
+                android:includeFontPadding="false"
+                android:layout_marginTop="@dimen/convert_95px"
+                android:layout_centerHorizontal="true"/>
+
+            <ImageView
+                android:layout_width="@dimen/convert_240px"
+                android:layout_height="@dimen/convert_206px"
+                android:layout_centerHorizontal="true"
+                android:src="@drawable/ic_pot_cover"
+                android:scaleType="fitCenter"
+                android:layout_below="@+id/tv_finish"
+                android:layout_marginTop="@dimen/convert_119px"/>
+
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/lid_unlock"
+                android:textSize="@dimen/convert_54px"
+                android:textColor="#6B6B6B"
+                android:includeFontPadding="false"
+                android:layout_marginTop="@dimen/convert_99px"
+                android:layout_centerHorizontal="true"/>
+
+        </LinearLayout>
+
+        <ImageView
+            android:id="@+id/iv_cancel"
+            android:layout_width="40dp"
+            android:layout_height="40dp"
+            android:layout_below="@+id/cl_layer"
+            android:layout_centerHorizontal="true"
+            android:src="@drawable/ic_cancel"
+            android:padding="12dp"
+            android:background="@drawable/bg_icon_cancel"
+            android:layout_marginTop="-20dp"/>
+
+    </RelativeLayout>
+
+</FrameLayout>

+ 36 - 0
BusinessCommon/src/main/res/layout/item_cook_details.xml

@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:background="#80000000">
+
+    <ScrollView
+        android:id="@+id/sv_text"
+        android:layout_width="match_parent"
+        android:layout_height="506dp"
+        android:background="@drawable/bg_cook_detail_dialog"
+        app:layout_constraintTop_toTopOf="parent">
+
+        <TextView
+            android:id="@+id/tv_details"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:textSize="@dimen/convert_39px"
+            android:textColor="#6B6B6B"
+            android:lineSpacingExtra="@dimen/convert_10px"
+            android:paddingHorizontal="@dimen/convert_60px"
+            android:paddingVertical="@dimen/convert_63px"/>
+
+    </ScrollView>
+
+    <ImageView
+        android:id="@+id/iv_close"
+        style="@style/CloseButton"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/sv_text"
+        app:layout_constraintBottom_toBottomOf="@+id/sv_text"/>
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 71 - 0
BusinessCommon/src/main/res/layout/item_note_dialog.xml

@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    xmlns:app="http://schemas.android.com/apk/res-auto">
+
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:layout_width="@dimen/convert_810px"
+        android:layout_height="@dimen/convert_509px"
+        android:layout_gravity="center_horizontal"
+        android:layout_marginTop="@dimen/convert_300px"
+        android:background="@drawable/bg_cook_note">
+
+        <TextView
+            android:id="@+id/tv_note_title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textColor="#E60012"
+            android:textSize="@dimen/convert_54px"
+            android:text="@string/note_title"
+            android:layout_margin="@dimen/convert_50px"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent"/>
+
+        <View
+            android:id="@+id/view_line"
+            android:layout_width="@dimen/convert_755px"
+            android:layout_height="@dimen/convert_2px"
+            android:layout_marginTop="@dimen/convert_39px"
+            android:background="#B1B2B2"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintTop_toBottomOf="@+id/tv_note_title"/>
+
+        <View
+            android:id="@+id/view_edit"
+            android:layout_width="@dimen/convert_120px"
+            android:layout_height="@dimen/convert_120px"
+            android:background="@drawable/ic_note_edit"
+            android:layout_marginEnd="@dimen/convert_48px"
+            android:layout_marginBottom="@dimen/convert_50px"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintBottom_toBottomOf="parent"/>
+
+        <View
+            android:id="@+id/view_complete"
+            android:layout_width="@dimen/convert_120px"
+            android:layout_height="@dimen/convert_120px"
+            android:background="@drawable/ic_note_commit"
+            android:layout_marginEnd="@dimen/convert_48px"
+            app:layout_constraintTop_toTopOf="@+id/view_edit"
+            app:layout_constraintEnd_toStartOf="@+id/view_edit"/>
+
+        <EditText
+            android:id="@+id/et_note"
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:layout_marginTop="@dimen/convert_44px"
+            android:layout_marginHorizontal="@dimen/convert_50px"
+            app:layout_constraintTop_toBottomOf="@+id/view_line"
+            app:layout_constraintBottom_toTopOf="@+id/view_complete"
+            android:background="@null"
+            android:hint="@string/type_your_notes_here"
+            android:textSize="@dimen/convert_45px"
+            android:textColor="#6B6B6B"
+            android:gravity="start"/>
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+
+</FrameLayout>

+ 2 - 0
BusinessStep/src/main/AndroidManifest.xml

@@ -6,5 +6,7 @@
         <activity android:name=".ui.FoodListActivity" />
         <activity android:name=".ui.ModesDetailActivity" />
         <activity android:name=".ui.recipes_detail.CookDetailActivity" />
+        <activity android:name=".ui.recipes_detail.CookEvaluateActivity" />
+        <activity android:name=".ui.cook_step.CookStepActivity" />
     </application>
 </manifest>

+ 1 - 1
BusinessStep/src/main/java/com/develop/step/ui/ModesDetailActivity.kt

@@ -1012,7 +1012,7 @@ class ModesDetailActivity : CommonBVMActivity<ActivityModeDetailBinding, ModesVi
      */
     private fun startClick() {
         if (mRunningInstId != mSettingInstId) {
-            overrideModeDialog.show(supportFragmentManager, "overrideModeDialog")
+            overrideModeDialog.showDialog(supportFragmentManager, "overrideModeDialog")
         } else {
             userChanging = false
             CofarSDK.cancel()

+ 881 - 0
BusinessStep/src/main/java/com/develop/step/ui/cook_step/CookStepActivity.kt

@@ -0,0 +1,881 @@
+package com.develop.step.ui.cook_step
+
+import android.annotation.SuppressLint
+import android.os.Bundle
+import android.util.Log
+import android.view.KeyEvent
+import coil.load
+import com.alibaba.android.arouter.facade.annotation.Route
+import com.develop.base.ext.setGone
+import com.develop.base.ext.setVisible
+import com.develop.base.ext.toJson
+import com.develop.base.ext.updateText
+import com.develop.base.util.MusicBackPlayerUtil
+import com.develop.base.util.ThreadUtils
+import com.develop.common.router.Screens
+import com.develop.common.widget.TimePickerView
+import com.develop.step.BuildConfig
+import com.develop.step.CookSettingType
+import com.develop.common.R
+import com.develop.common.data_repo.FoodDataProvider
+import com.develop.common.data_repo.db.entity.UserHistoryRecipes
+import com.develop.common.dialog.CancelConfirmDialog
+import com.develop.common.dialog.CookStepCompleteDialog
+import com.develop.common.dialog.PotCoverUnlockedDialog
+import com.develop.common.event.CookStepEvent
+import com.develop.common.food_sdk.FloatWindowManager
+import com.develop.common.food_sdk.FoodSdkUtils
+import com.develop.common.tag.CURRENT_USER_ID
+import com.develop.common.tag.PRESS_DOWN_KEY_CODE
+import com.develop.common.tag.TURN_DOWN_KEY_CODE
+import com.develop.common.tag.TURN_UP_KEY_CODE
+import com.develop.common.utils.TimeUtil
+import com.develop.step.ui.cook_step.model.CookStepStatus
+import com.develop.step.ui.cook_step.model.CookStepUiData
+import com.kuyuntech.cofarcooking.device.sdk.constant.core.CommonEventTypes
+import com.kuyuntech.cofarcooking.device.sdk.constant.core.DevStatus
+import com.kuyuntech.cofarcooking.device.sdk.constant.core.HeatModes
+import com.kuyuntech.cofarcooking.device.sdk.constant.core.MotorDirections
+import com.kuyuntech.cofarcooking.device.sdk.eventbus.core.DevInfo
+import com.kuyuntech.cofarcooking.device.sdk.eventbus.event.DevCommonEvent
+import com.kuyuntech.cofarcooking.device.sdk.util.core.CofarSDK
+import org.greenrobot.eventbus.Subscribe
+import java.io.File
+
+@Route(path = Screens.Cook.COOK_STEP2)
+class CookStepActivity : CookStepBaseActivity() {
+    private var timeArray = IntArray(3)
+    private val audioUtil = MusicBackPlayerUtil()
+    private var audioMute = false
+    private var pendingCookStep = false
+    private var isHistory = false
+    private var mSettingInstId = ""
+    private var mRunningInstId = ""
+    private var potCloverStatus = 1 //锅盖是否盖上 0 是 1 否
+    private var coverPath: Any? = null
+    private var isFromOverWrite = false
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        binding.controller.clSetTime.onTimePickerCallback =
+            object : TimePickerView.OnTimePickerCallback {
+                override fun onTimePicker(
+                    hours: Int,
+                    minute: Int,
+                    second: Int,
+                    time: String,
+                    setByUser: Boolean
+                ) {
+                    if (setByUser) {
+                        viewModel.stepUiData.doingModify = true
+                        val totalTime = second + (minute + hours * 60) * 60
+                        viewModel.displayStep()?.uiData?.targetTime = totalTime
+                        binding.controller.tvCookingTimeTarget.updateText("--${time}--")
+                        CofarSDK.cfgTime(totalTime)
+                    }
+                }
+
+                override fun onTimePickerTouchFirst() {
+                    viewModel.stepUiData.doingModify = true
+                }
+            }
+        binding.viewAlarm.setOnClickListener {
+            audioMute = !audioMute
+            if (audioMute) {
+                audioUtil.stopBgSound()
+                binding.viewAlarm.setBackgroundResource(R.drawable.ic_audio_mute)
+            } else {
+                binding.viewAlarm.setBackgroundResource(R.drawable.ic_alarm)
+            }
+        }
+        initData()
+    }
+
+    private fun initData() {
+        viewModel.queryRecipeCookStep(recipeNumber ?: "", currentStepIndex)
+        viewModel.stepDisplay.observe(this) { it ->
+            coverPath = FoodDataProvider.getImagePath(it.source.photoVideoFilePath)
+            if (CofarSDK.devInfo().status == DevStatus.STOP.toInt()) {
+                CofarSDK.changeMode(
+                    "$recipeNumber:${viewModel.stepIndex}",
+                    CofarSDK.devMode(it.workMode)
+                )
+            }
+            if (it.isWeightMode()) {
+                changeWeightPanel()
+                CofarSDK.stoptWeight()
+                CofarSDK.startWeight()
+            } else if (it.isTurboMode()) {
+                CofarSDK.stoptWeight()
+                changeTurboPanel()
+            } else if (it.isDescription()) {
+                CofarSDK.stoptWeight()
+                changeDescription()
+            } else {
+                CofarSDK.stoptWeight()
+                changeTempSettingPanel()
+            }
+            val stepCount = viewModel.getStepCount()
+            val stepIndex = viewModel.allSteps.indexOf(it)
+//            //通知当前步骤信息给浮窗
+//            EventBus.getDefault()
+//                .post(
+//                    CookStepEvent(
+//                        recipeNumber ?: "",
+//                        coverPath as String,
+//                        stepIndex
+//                    )
+//                )
+            cookProgressDrawable.setStepState(stepIndex, stepCount)
+            binding.tvStepName.text = it.source.description
+            binding.tvTitleStep.text = it.source.description
+            if (stepCount == 1) {
+                binding.ivPrevStep.setGone()
+                binding.ivNextStep.setGone()
+            } else if (viewModel.isFirstStep(it)) {
+                binding.ivPrevStep.setGone()
+                binding.ivNextStep.setVisible()
+            } else if (viewModel.isFinalStep(it)) {
+                binding.ivPrevStep.setVisible()
+                binding.ivNextStep.setGone()
+            } else {
+                binding.ivPrevStep.setVisible()
+                binding.ivNextStep.setVisible()
+            }
+            binding.ivCookBg.load(FoodDataProvider.getResourcePath(it.source.photoVideoFilePath)) {
+                error(R.drawable.bg_cook_session)
+                transformations()
+            }
+            updateUiSetting(it)
+            playStepAudio(it.source.audioFilePath)
+            tryConsumePendingCookStep(it)
+
+            initStepData()
+
+        }
+
+        backRequestDialog.apply {
+            title = "Keep cooking in the background?"
+            onDialogClickListener = object : CancelConfirmDialog.OnDialogClickListener {
+                override fun onConfirm() {
+                    val cookStepEvent = CookStepEvent(
+                        recipeNumber ?: "",
+                        coverPath as String,
+                        viewModel.stepIndex,
+                        isMode = false
+                    )
+                    FloatWindowManager.showStepFlowWindow(cookStepEvent)
+                    finish()
+                }
+
+                override fun onCancel() {
+                    FloatWindowManager.hideStepFlowWindow()
+                    CofarSDK.stop(false)
+                    finish()
+                }
+            }
+        }
+
+        overrideModeDialog.apply {
+            title =
+                "Overwrite current cooking process?\n By overwriting,your current progress will got lost."
+            onDialogClickListener = object : CancelConfirmDialog.OnDialogClickListener {
+                override fun onConfirm() {
+                    isFromOverWrite = true
+                    viewModel.displayStep()?.let {
+                        viewModel.setTargetCookingStep(it)
+                        configDataAndStart(it.uiData)
+                    }
+                    val cookStepEvent = CookStepEvent(
+                        recipeNumber ?: "",
+                        coverPath as String,
+                        viewModel.stepIndex,
+                        isMode = false
+                    )
+                    FloatWindowManager.showStepFlowWindow(cookStepEvent)
+                    recordRecipes()
+                }
+
+                override fun onCancel() {
+
+                }
+            }
+        }
+
+    }
+
+    private fun playStepAudio(audioPath: String?) {
+        audioUtil.stopBgSound()
+        if (audioMute) {
+            return
+        }
+        if (!audioPath.isNullOrEmpty()) {
+            val filePath = FoodDataProvider.getResourcePath(audioPath)
+            if (File(filePath).exists()) {
+                audioUtil.playBgSound(filePath)
+            }
+        }
+    }
+
+
+    var configing: Boolean = false
+
+    private fun initStepData() {
+        configing = true;
+        if (runningState == DevStatus.STOP.toInt()) {
+
+            viewModel.allSteps.get(viewModel.stepIndex)?.let {
+
+                it.uiData.applyRecipeSetting(it.source)
+
+                if (!it.isWeightMode() && !it.isDescription()) {
+                    //设置初始参数
+                    CofarSDK.cfgHeat(it.uiData.targetTemp.toShort(), 0)
+                    CofarSDK.cfgTime(it.uiData.targetTime)
+                    CofarSDK.cfgMotorGear(it.uiData.currentSpeed.toByte())
+                    CofarSDK.cfgMotorDirection(it.uiData.direction.toByte())
+                }
+
+            }
+
+        }
+        ThreadUtils.runOnMainThread({
+            configing = false
+        }, 500)
+
+    }
+
+    override fun clickNextStep() {
+        if (viewModel.isCurrentOnCookingStep()
+            && viewModel.cookingStep?.isManualStep() == true
+        ) {
+            // 当前为手动步骤, 下一个步骤切换会设置为当前烹饪步骤
+            pendingCookStep = true
+        }
+        viewModel.nextStep()
+
+        initStepData() //初始化步骤参数
+
+
+    }
+
+    override fun clickPrevStep() {
+        if (viewModel.isCurrentOnCookingStep() && viewModel.cookingStep?.isManualStep() == true
+            || runningState == DevStatus.STOP.toInt()
+        ) {
+            // 当前为手动步骤, 上一个步骤切换会设置为当前烹饪步骤
+            pendingCookStep = true
+        }
+        viewModel.prevStep()
+        initStepData()
+    }
+
+    /**
+     * 前一个步骤为称重步骤, 切换到左/右步骤后自动设定为当前步骤, 有自动开始字段则自动开始烹饪
+     */
+    private fun tryConsumePendingCookStep(status: CookStepStatus) {
+        if (!pendingCookStep) {
+            return
+        }
+        pendingCookStep = false
+        viewModel.setTargetCookingStep(status)
+//        if (status.source.autoStart == "1") {
+//            configDataAndStart(status.uiData)
+//        }
+    }
+
+    /**
+     * BUTTON_TAG_START
+     * BUTTON_TAG_PAUSE
+     * BUTTON_TAG_RESUME
+     * BUTTON_TAG_CONFIRM
+     */
+    override fun clickFirstButton(tag: String) {
+        handleButtonState(tag)
+    }
+
+    /**
+     * BUTTON_TAG_CANCEL
+     * BUTTON_TAG_STOP
+     * BUTTON_TAG_RESET
+     */
+    override fun clickSecondButton(tag: String) {
+        handleButtonState(tag)
+    }
+
+    private fun handleButtonState(tag: String) {
+        if (tag == BUTTON_TAG_START) {
+
+
+            if (CofarSDK.devInfo().potCloverStatus.toInt() == 1) {
+                showPotCloverDialog()
+            } else if (CofarSDK.devInfo().runningInstId != "${recipeNumber}:${viewModel.stepIndex}") {
+                overrideModeDialog.showDialog(supportFragmentManager, "overrideModeDialog")
+            } else {
+                viewModel.displayStep()?.let {
+                    viewModel.setTargetCookingStep(it)
+                    configDataAndStart(it.uiData)
+                }
+                recordRecipes()
+            }
+        } else if (tag == BUTTON_TAG_PAUSE) {
+            CofarSDK.pause()
+        } else if (tag == BUTTON_TAG_RESUME) {
+            CofarSDK.resume()
+        } else if (tag == BUTTON_TAG_CONFIRM) {
+            CofarSDK.confirm()
+            binding.controller.btnStart.setGone()
+            binding.controller.btnReset.setGone()
+        } else if (tag == BUTTON_TAG_STOP) {
+            CofarSDK.stop(false)
+        } else if (tag == BUTTON_TAG_RESET) {
+            val current = viewModel.displayStep() ?: return
+            val stepIndex = viewModel.allSteps.indexOf(current)
+            val uiCopy = viewModel.dataCopy.getOrNull(stepIndex)
+            uiCopy?.let {
+                current.uiData.copyFrom(it)
+                updateUiSetting(current)
+            }
+        } else if (tag == BUTTON_TAG_CANCEL) {
+            CofarSDK.cancel()
+            binding.controller.btnStart.setGone()
+            binding.controller.btnReset.setGone()
+        }
+    }
+
+    override fun clickWeightTare() {
+        CofarSDK.clearWeight()
+    }
+
+    fun checkShowConfirm() {
+//        if(runningState.toByte() != DevStatus.STOP){
+//             viewModel.stepUiData.doingModify=true
+//        }
+    }
+
+    override fun onUserChangeTemp(value: Int) {
+        val v = FoodSdkUtils.parseTemp(value.toShort())
+        viewModel.displayStep()?.uiData?.targetTemp = v.toInt()
+        binding.controller.tvCookingTempTarget.updateText("--${v}°C--")
+        binding.controller.tvRingTempText.updateText("${v}°C")
+        CofarSDK.cfgHeat(value.toShort(), HeatModes.PU_TONG)
+        checkShowConfirm()
+    }
+
+    override fun onUserChangeSpeed(value: Int) {
+        viewModel.displayStep()?.uiData?.currentSpeed = value
+        binding.controller.tvSetSpeed.updateText(value.toString())
+        binding.controller.tvSpeedText.updateText(value.toString())
+        CofarSDK.cfgMotorGear(value.toByte())
+        checkShowConfirm()
+    }
+
+    override fun onSettingDirection(value: Int) {
+        viewModel.displayStep()?.uiData?.direction = value
+        if (value == 0) {
+            CofarSDK.cfgMotorDirection(MotorDirections.FORWARD)
+        } else {
+            CofarSDK.cfgMotorDirection(MotorDirections.REVERSE)
+        }
+        checkShowConfirm()
+    }
+
+    override fun onDevStateChange(devInfo: DevInfo) {
+        if (configing) {
+            return
+        }
+        viewModel.cookingStep?.let {
+            potCloverStatus = devInfo.potCloverStatus.toInt()
+
+            if (recipeNumber?.let { it1 -> CofarSDK.devInfo().runningInstId.equals("$it1:${viewModel.stepIndex}") } == true) {
+                mRunningInstId = devInfo.runningInstId
+                mSettingInstId = devInfo.settingInstId
+                it.uiData.runningStatus = devInfo.status
+                it.uiData.targetTemp = FoodSdkUtils.parseTemp(devInfo.targetTemp).toInt()
+                it.uiData.targetTime = devInfo.targetTime
+                it.uiData.currentSpeed = devInfo.motorGear.toInt()
+                it.uiData.weightNum = devInfo.weight.toInt()
+                it.uiData.direction = devInfo.motorDirection.toInt()
+                it.uiData.currentTemp = FoodSdkUtils.parseTemp(devInfo.temp).toInt()
+                it.uiData.remainTime = devInfo.remainTime
+                it.uiData.targetTimeBuffer = devInfo.targetTimeBuffer
+                it.uiData.isTimeChange = devInfo.mode.isTimeChange
+                it.uiData.isTempChange = devInfo.mode.isTempChange
+                it.uiData.isMotorDirectionChange = devInfo.mode.isMotorDirectionChange
+                it.uiData.isMotorGearChange = devInfo.mode.isMotorGearChange
+                it.uiData.limitMaxSpeed = devInfo.mode.maxMotorGear
+                it.uiData.limitMinSpeed = devInfo.mode.minMotorGear
+                it.uiData.limitMaxTemp = devInfo.mode.maxTemp
+                it.uiData.limitMinTemp = devInfo.mode.minTemp
+                it.uiData.limitMaxTime = devInfo.mode.maxTime
+                it.uiData.limitMinTime = devInfo.mode.minTime
+
+            }
+
+            if (!it.hasStarted && devInfo.status == DevStatus.RUNNING.toInt()) {
+                // 标记这个步骤曾经开始过了
+                it.hasStarted = true
+            }
+            if (it.hasStarted && !it.hasComplete && devInfo.status == DevStatus.STOP.toInt()) {
+                // 这个步骤目前已经结束了
+                it.hasComplete = true
+                notifyStepComplete(it)
+            }
+        }
+        if (viewModel.isCurrentOnCookingStep()) {
+            viewModel.cookingStep?.let {
+                updateUiSetting(it)
+            }
+        }
+        // 重量设置
+        viewModel.cookingStep?.apply {
+            binding.tvWeightNum.updateText("${uiData.weightNum}g")
+            binding.weightView.setWeightNumber(uiData.weightNum.toFloat())
+        }
+    }
+
+
+    private fun showPotCloverDialog() {
+        val warnDialog = supportFragmentManager.findFragmentByTag("WarningDialog")
+        if (warnDialog == null) {
+            supportFragmentManager
+                .beginTransaction()
+                .add(PotCoverUnlockedDialog(), "WarningDialog")
+                .commitNowAllowingStateLoss()
+        }
+    }
+
+    private fun notifyStepComplete(cookStep: CookStepStatus) {
+        val dialog = CookStepCompleteDialog {
+            val nextStep = viewModel.getNextStep(
+                cookStep
+            ) ?: return@CookStepCompleteDialog
+            if (nextStep.source.autoStart != "1") {
+                return@CookStepCompleteDialog
+            }
+            // 自动切换到下一步骤
+            viewModel.setTargetCookingStep(nextStep)
+        }
+        dialog.showDialog(supportFragmentManager, "complete")
+
+    }
+
+    private fun configDataAndStart(uiData: CookStepUiData) {
+
+        CofarSDK.changeMode(
+            "$recipeNumber:${viewModel.stepIndex}",
+            CofarSDK.devMode(viewModel.cookingStep?.workMode)
+        )
+
+        CofarSDK.cfgTime(uiData.targetTime.toInt())
+        CofarSDK.cfgMotorDirection(
+            if (uiData.direction == 0) {
+                MotorDirections.FORWARD
+            } else {
+                MotorDirections.FORWARD
+            }
+        )
+        CofarSDK.cfgMotorGear(uiData.currentSpeed.toByte())
+        CofarSDK.cfgHeat(uiData.targetTemp.toShort(), HeatModes.PU_TONG)
+        CofarSDK.cancel()
+
+        if (isFromOverWrite) {
+            //覆盖调用
+            CofarSDK.startRunning("${recipeNumber}:${viewModel.stepIndex}")
+            isFromOverWrite = false
+        } else {
+            CofarSDK.start("${recipeNumber}:${viewModel.stepIndex}")
+        }
+        //通知当前运行的菜谱的ID和当前步骤索引
+        CofarSDK.startRecipe(recipeNumber, viewModel.stepIndex.toString())
+    }
+
+    override fun dispatchKeyEvent(event: KeyEvent): Boolean {
+        if (event.action != KeyEvent.ACTION_UP) {
+            when (event.keyCode) {
+                TURN_UP_KEY_CODE -> {
+                    operateByPhysical(true)
+                }
+                TURN_DOWN_KEY_CODE -> {
+                    operateByPhysical(false)
+                }
+            }
+        }
+        return super.dispatchKeyEvent(event)
+    }
+
+
+    private fun rotateStep(): Int {
+
+        viewModel.cookingStep?.let {
+            if (it.uiData.targetTime >= 60) {
+                return 10;
+            }
+
+            if (it.uiData.targetTime >= 10 * 60) {
+                return 30;
+            }
+        }
+
+
+
+        return 1
+    }
+
+    private fun operateByPhysical(increase: Boolean) {
+        val cookStep = viewModel.displayStep()
+        val tabType = getSelectedTabType()
+        if (tabType == CookSettingType.TEMP_SETTING) {
+            cookStep?.uiData?.let {
+                if (!it.isTempChange) {
+                    return
+                }
+                if (increase) {
+                    it.targetTemp += CofarSDK.getTempInterval()
+                    if (it.targetTemp > it.limitMaxTemp) {
+                        it.targetTemp = it.limitMaxTemp
+                    }
+                } else {
+                    it.targetTemp -= CofarSDK.getTempInterval()
+                    if (it.targetTemp < it.limitMinTemp) {
+                        it.targetTemp = it.limitMinTemp
+                    }
+
+                    if (it.targetTemp < 37) {
+                        it.targetTemp = 0
+                    }
+
+                }
+                viewModel.stepUiData.doingModify = true
+                binding.controller.tempRingView.updateProgress(it.targetTemp)
+                onUserChangeTemp(it.targetTemp)
+            }
+        } else if (tabType == CookSettingType.SPEED_SETTING) {
+            cookStep?.uiData?.let {
+                if (!it.isMotorGearChange) {
+                    return
+                }
+                if (increase) {
+                    it.currentSpeed++
+                    if (it.currentSpeed > it.limitMaxSpeed) {
+                        it.currentSpeed = it.limitMaxSpeed
+                    }
+                } else {
+                    it.currentSpeed--
+                    if (it.currentSpeed < it.limitMinSpeed) {
+                        it.currentSpeed = it.limitMinSpeed
+                    }
+                }
+                viewModel.stepUiData.doingModify = true
+                binding.controller.speedRingView.updateProgress(it.currentSpeed)
+                onUserChangeSpeed(it.currentSpeed)
+            }
+        } else if (tabType == CookSettingType.TIME_SETTING) {
+            cookStep?.uiData?.let {
+                if (!it.isTimeChange) {
+                    return
+                }
+                dealWithTimeByOperation(it, increase)
+            }
+        }
+    }
+
+    private fun dealWithTimeByOperation(uiData: CookStepUiData, increase: Boolean) {
+        //当前调节时间
+        var targetTime = uiData.targetTime
+        if (increase) {
+            targetTime += rotateStep()
+        } else {
+            targetTime -= rotateStep()
+        }
+        if (targetTime > uiData.limitMaxTime) {
+            targetTime = uiData.limitMaxTime
+        }
+        if (targetTime < uiData.limitMinTime) {
+            targetTime = uiData.limitMinTime
+        }
+        val sec = targetTime % 60
+        val min = ((targetTime / 60) % 60)
+        val hour = (targetTime / 3600)
+        var time = ""
+        if (hour > 0) {
+            time += if (hour < 10) {
+                "0${hour}"
+            } else {
+                "${hour}"
+            }
+
+            time += if (min < 10) {
+                ":0${min}"
+            } else {
+                ":${min}"
+            }
+        } else {
+            time += if (min < 10) {
+                "0${min}"
+            } else {
+                "${min}"
+            }
+
+            time += if (sec < 10) {
+                ":0${sec}"
+            } else {
+                ":${sec}"
+            }
+        }
+        uiData.isTimeChange = true
+        uiData.targetTime = targetTime
+        binding.controller.clSetTime.isTimeCanChange(true)
+        // 回调到上面那个地方来设置时间
+        TimeUtil.getTimes(targetTime, timeArray)
+        binding.controller.clSetTime.setTimeInternal(
+            timeArray[0],
+            timeArray[1],
+            timeArray[2],
+            changeSetting = true,
+            setByUser = true
+        )
+    }
+
+    override fun onKeyLongPress(keyCode: Int, event: KeyEvent?): Boolean {
+
+        if (CofarSDK.devInfo().status == DevStatus.RUNNING.toInt() || CofarSDK.devInfo().status == DevStatus.PAUSE.toInt()) {
+            viewModel.stepUiData.doingModify = false
+            clickFirstButton(BUTTON_TAG_STOP)
+            Log.d("QQQQ", "click stop")
+        }
+        pressStartTime = -1L
+
+        return super.onKeyLongPress(keyCode, event)
+    }
+
+    private var canStart = true
+
+    override fun onKeyUp(keyCode: Int, event: KeyEvent?): Boolean {
+        pressStartTime = -1L
+        if (keyCode == PRESS_DOWN_KEY_CODE) {
+            Log.d("QQQQ", "catch key down")
+            //当前是turbo模式下
+            if (viewModel.cookingStep?.isTurboMode() != true) {
+
+                if (canStart) {
+                    //非turbo模式
+                    if (viewModel.stepUiData.doingModify && CofarSDK.devInfo().status.toByte() != DevStatus.STOP) {
+                        //用户调节中
+                        viewModel.stepUiData.doingModify = false
+                        clickFirstButton(BUTTON_TAG_CONFIRM)
+                        Log.d("QQQQ", "click confirm")
+                    } else {
+                        when (CofarSDK.devInfo().status) {
+                            DevStatus.RUNNING.toInt() -> {
+                                viewModel.stepUiData.doingModify = false
+                                clickFirstButton(BUTTON_TAG_PAUSE)
+                                Log.d("QQQQ", "click stop")
+                            }
+                            DevStatus.PAUSE.toInt() -> {
+                                viewModel.stepUiData.doingModify = false
+                                clickFirstButton(BUTTON_TAG_RESUME)
+                                Log.d("QQQQ", "click stop")
+                            }
+                            DevStatus.STOP.toInt() -> {
+                                viewModel.stepUiData.doingModify = false
+                                clickFirstButton(BUTTON_TAG_START)
+                                Log.d("QQQQ", "click start")
+                            }
+                            else -> {
+                                Log.d("QQQQ", "nothing to do")
+                            }
+                        }
+                    }
+                }
+
+
+            } else {
+                turboUpEvent();
+            }
+        }
+        canStart = true
+        return super.onKeyUp(keyCode, event)
+    }
+
+    private var pressStartTime = -1L;
+
+
+    override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
+        if (keyCode == PRESS_DOWN_KEY_CODE) {
+            Log.d("QQQQ", "catch key down")
+            //当前是turbo模式下
+            if (viewModel.cookingStep?.isTurboMode() == true) {
+                turboDownEvent()
+            } else {
+                if (pressStartTime == -1L) {
+                    pressStartTime = System.currentTimeMillis()
+                }
+
+
+                if (pressStartTime != -1L && (System.currentTimeMillis() - pressStartTime) > 1000 && event?.keyCode == PRESS_DOWN_KEY_CODE) {
+                    this.onKeyLongPress(keyCode, event);
+                    event.startTracking()
+                    pressStartTime = -1L
+                    canStart = false
+                    return false
+                }
+            }
+        }
+        return super.onKeyDown(keyCode, event)
+    }
+
+    /**
+     * 根据UI状态刷新View
+     */
+    @SuppressLint("SetTextI18n")
+    private fun updateUiSetting(status: CookStepStatus, focusUpdate: Boolean = false) {
+        val uiData = status.uiData
+        if (viewModel.stepUiData.doingModify && (uiData.runningStatus == DevStatus.RUNNING.toInt() || uiData.runningStatus == DevStatus.PAUSE.toInt())) {
+            binding.controller.btnStart.setVisible()
+            binding.controller.btnReset.setVisible()
+            binding.controller.btnStart.updateText(getString(R.string.confirm))
+            binding.controller.btnReset.updateText(getString(R.string.cancel))
+            binding.controller.btnStart.tag = BUTTON_TAG_CONFIRM
+            binding.controller.btnReset.tag = BUTTON_TAG_CANCEL
+        } else {
+            if (uiData.runningStatus == DevStatus.STOP.toInt()) {
+                binding.controller.btnStart.setVisible()
+                binding.controller.btnReset.setVisible()
+                binding.controller.btnStart.updateText(getString(R.string.start))
+                binding.controller.btnReset.updateText(getString(R.string.reset_button))
+                binding.controller.btnStart.tag = BUTTON_TAG_START
+                binding.controller.btnReset.tag = BUTTON_TAG_RESET
+            } else if (uiData.runningStatus == DevStatus.RUNNING.toInt()) {
+                binding.controller.btnStart.setVisible()
+                binding.controller.btnReset.setGone()
+                binding.controller.btnStart.updateText(getString(R.string.pause))
+                binding.controller.btnStart.tag = BUTTON_TAG_PAUSE
+            } else {
+                binding.controller.btnStart.setVisible()
+                binding.controller.btnReset.setVisible()
+                binding.controller.btnStart.updateText(getString(R.string.resume))
+                binding.controller.btnReset.updateText(getString(R.string.stop))
+                binding.controller.btnStart.tag = BUTTON_TAG_RESUME
+                binding.controller.btnReset.tag = BUTTON_TAG_STOP
+            }
+        }
+        // 已经开始运行, 并且不是当前步骤, 隐藏操作按钮, 禁止操作
+        val modifyDisable = viewModel.isCookingStepStarted() && !viewModel.isCurrentOnCookingStep()
+        binding.controller.speedRingView.setCanTouch(!modifyDisable && uiData.isMotorGearChange)
+        binding.controller.tempRingView.setCanTouch(!modifyDisable && uiData.isTempChange)
+        binding.controller.tvTurnLeft.isEnabled = !modifyDisable && uiData.isMotorDirectionChange
+        binding.controller.tvTurnRight.isEnabled = !modifyDisable && uiData.isMotorDirectionChange
+        binding.controller.clSetTime.isTimeCanChange(!modifyDisable && uiData.isTimeChange)
+        if (modifyDisable || status.isManualStep()) {
+            binding.controller.btnStart.setGone()
+            binding.controller.btnReset.setGone()
+        }
+
+        binding.controller.speedRingView.setRange(
+            uiData.limitMinSpeed.toFloat(), uiData.limitMaxSpeed.toFloat()
+        )
+        binding.controller.tempRingView.setRange(
+            uiData.limitMinTemp.toFloat(), uiData.limitMaxTemp.toFloat()
+        )
+        binding.controller.clSetTime.setTimeRange(
+            uiData.limitMinTime, uiData.limitMaxTime
+        )
+
+        // 播放电机转动动画
+        if (viewModel.isCurrentOnCookingStep()
+            && uiData.runningStatus == DevStatus.RUNNING.toInt()
+            && uiData.currentSpeed > 0
+        ) {
+            playRotateAnimator(uiData.direction)
+        } else {
+            pauseRotateAnimator()
+        }
+
+        // 时间设置
+        if (runningState == DevStatus.STOP.toInt()) {
+            TimeUtil.getTimes(uiData.targetTime, timeArray)
+        } else {
+            TimeUtil.getTimes(uiData.remainTime, timeArray)
+        }
+        if (!viewModel.stepUiData.doingModify || focusUpdate) {
+            binding.controller.clSetTime.setTimeInternal(
+                timeArray[0],
+                timeArray[1],
+                timeArray[2],
+                true
+            ) // 表盘时间设置-当前剩余时间
+            TimeUtil.getTimes(uiData.targetTime, timeArray)
+            binding.controller.tvCookingTimeTarget.updateText("--${TimeUtil.formatTime(timeArray)}--") // 下面的TAB-目标运行时间
+        }
+        TimeUtil.getTimes(uiData.remainTime, timeArray)
+        binding.controller.tvSetTime.updateText(TimeUtil.formatTime(timeArray))                            // 下面的TAB-当前剩余时间
+
+        // 温度
+        val showTemp =
+            if (runningState == DevStatus.STOP.toInt()) uiData.targetTemp else uiData.currentTemp;
+        if (!viewModel.stepUiData.doingModify || focusUpdate) {
+            binding.controller.tvCookingTempTarget.updateText("--${uiData.targetTemp}°C--")            // 下面的TAB-目标运行温度
+            binding.controller.tempRingView.updateProgress(showTemp)                                 // 圆环设置-当前运行温度
+            binding.controller.tvRingTempText.updateText("${showTemp}°C")                     // 圆环内的数字-当前运行温度
+        }
+        binding.controller.tvTempValue.updateText("${uiData.currentTemp}°C")                       // 下面的TAB-当前运行温度
+
+        // 速度设置
+        if (!viewModel.stepUiData.doingModify || focusUpdate) {
+
+            binding.controller.speedRingView.updateProgress(uiData.currentSpeed)                               // 圆环设置-当前运行速度
+            binding.controller.tvSpeedText.updateText(uiData.currentSpeed.toString())                          // 圆环内的数字-当前运行速度
+            binding.controller.tvSetSpeed.updateText(uiData.currentSpeed.toString())                           // 下面的TAB-当前运行速度
+        }
+
+        // 方向设置
+        if (!viewModel.stepUiData.doingModify || focusUpdate) {
+            updateDirection(uiData.direction)
+        }
+    }
+
+
+    @Subscribe
+    fun onDevCommonEvent(event: DevCommonEvent) {
+
+
+        ThreadUtils.runOnMainThread({
+
+            val mode = CofarSDK.devMode(viewModel.cookingStep?.workMode)
+
+            if (CommonEventTypes.MOTOR_GEAR_RATHER_THEN_7 == event.type) {
+                CofarSDK.cfgTime((10 * 60))
+                viewModel.cookingStep?.let { updateUiSetting(it, true) }
+            }
+
+            if (CommonEventTypes.MOTOR_GEAR_RATHER_THEN_3_WITH_TEMP == event.type) {
+                CofarSDK.cfgMotorGear(3)
+                viewModel.cookingStep?.let { updateUiSetting(it, true) }
+            }
+        }, 500)
+
+
+    }
+
+    override fun onDestroy() {
+        super.onDestroy()
+        audioUtil.releaseMedia()
+    }
+
+    private fun recordRecipes() {
+        if (!isHistory) {
+            isHistory = true
+            FoodDataProvider.getUserDatabase().runInTransaction {
+                recipeNumber?.let {
+                    FoodDataProvider.getUserDatabase().userInfoDao().removeHistoryRecipe(
+                        CURRENT_USER_ID, it
+                    )
+                }
+                FoodDataProvider.getUserDatabase().userInfoDao().insertHistoryRecipe(
+                    UserHistoryRecipes(CURRENT_USER_ID, recipeNumber ?: "")
+                )
+            }
+        }
+    }
+}

+ 443 - 0
BusinessStep/src/main/java/com/develop/step/ui/cook_step/CookStepBaseActivity.kt

@@ -0,0 +1,443 @@
+package com.develop.step.ui.cook_step
+
+import android.animation.ObjectAnimator
+import android.annotation.SuppressLint
+import android.os.Bundle
+import android.util.Log
+import android.view.LayoutInflater
+import android.view.MotionEvent
+import android.view.View
+import android.view.animation.LinearInterpolator
+import android.widget.TextView
+import com.alibaba.android.arouter.facade.annotation.Autowired
+import com.alibaba.android.arouter.launcher.ARouter
+import com.develop.base.ext.updateText
+import com.develop.base.util.ThreadUtils
+import com.develop.common.dialog.CancelConfirmDialog
+import com.develop.common.ui.CommonBVMActivity
+import com.develop.common.widget.CookProgressDrawable
+import com.develop.common.widget.RingControlView
+import com.develop.step.CookSettingType
+import com.develop.common.R
+import com.develop.common.dialog.NoteEditDialog
+import com.develop.step.databinding.ActivityCookStepBaseBinding
+import com.develop.step.viewmodel.CookStepViewModel
+import com.kuyuntech.cofarcooking.device.sdk.eventbus.core.DevInfo
+import com.kuyuntech.cofarcooking.device.sdk.eventbus.event.DevStatusEvent
+import com.kuyuntech.cofarcooking.device.sdk.util.core.CofarSDK
+import org.greenrobot.eventbus.EventBus
+import org.greenrobot.eventbus.Subscribe
+import java.util.*
+
+abstract class CookStepBaseActivity :
+    CommonBVMActivity<ActivityCookStepBaseBinding, CookStepViewModel>() {
+    @JvmField
+    @Autowired(name = "number")
+    var recipeNumber: String? = null
+
+    @JvmField
+    @Autowired(name = "stepIndex")
+    var currentStepIndex: Int = 0
+
+    var runningState = 0
+
+    val cookProgressDrawable = CookProgressDrawable()
+    private var turboTimer: Timer? = null
+
+    val backRequestDialog by lazy {
+        CancelConfirmDialog()
+    }
+
+    val overrideModeDialog by lazy {
+        CancelConfirmDialog()
+    }
+
+    private var isCookDetailDialogShow = false
+    private var rotateAnimator: ObjectAnimator? = null
+    private var rotateAnimDir = -1
+
+    abstract fun clickNextStep()
+
+    abstract fun clickPrevStep()
+
+    abstract fun clickFirstButton(tag: String)
+
+    abstract fun clickSecondButton(tag: String)
+
+    abstract fun clickWeightTare()
+
+    abstract fun onUserChangeTemp(value: Int)
+
+    abstract fun onUserChangeSpeed(value: Int)
+
+    abstract fun onDevStateChange(devInfo: DevInfo)
+
+    /**
+     * left => value = 0
+     * right => value = 1
+     */
+    abstract fun onSettingDirection(value: Int)
+
+    override fun createViewModel(): CookStepViewModel {
+        return getViewModel(CookStepViewModel::class.java)
+    }
+
+    override fun createViewBinding(inflater: LayoutInflater): ActivityCookStepBaseBinding {
+        return ActivityCookStepBaseBinding.inflate(inflater)
+    }
+
+    @SuppressLint("ClickableViewAccessibility")
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        hasShowScreenSaver = true
+        ARouter.getInstance().inject(this)
+        EventBus.getDefault().register(this)
+        binding.viewProgress.background = cookProgressDrawable
+        binding.tvTitleStep.setOnClickListener {
+            showCookDetailDialog()
+        }
+        binding.tvStepName.setOnClickListener {
+            showCookDetailDialog()
+        }
+        binding.viewRemark.setOnClickListener {
+            NoteEditDialog().showDialog(supportFragmentManager, "NoteEditDialog")
+        }
+        binding.ivNextStep.setOnClickListener {
+            clickNextStep()
+            viewModel.stepUiData.doingModify = false
+        }
+        binding.ivPrevStep.setOnClickListener {
+            clickPrevStep()
+            viewModel.stepUiData.doingModify = false
+        }
+        binding.controller.clCookTemp.setOnClickListener {
+            changeTempSettingPanel()
+        }
+        binding.controller.clCookTime.setOnClickListener {
+            changeTimeSettingPanel()
+        }
+        binding.controller.clCookSpeed.setOnClickListener {
+            changeSpeedSettingStep()
+        }
+        binding.controller.clCookDirection.setOnClickListener {
+            changeDirectionSettingStep()
+        }
+        binding.viewBack.setOnClickListener {
+            val run = recipeNumber?.let { it1 -> CofarSDK.devInfo().runningInstId.startsWith(it1) }
+            if (runningState != 0 && run == true) {
+                backRequestDialog.showDialog(supportFragmentManager, "backRequestDialog")
+            } else {
+                finish()
+            }
+        }
+        binding.controller.btnStart.setOnClickListener {
+            clickFirstButton((it.tag as? String) ?: BUTTON_TAG_START)
+            viewModel.stepUiData.doingModify = false
+        }
+        binding.controller.btnReset.setOnClickListener {
+            viewModel.stepUiData.doingModify = false
+            clickSecondButton((it.tag as? String) ?: BUTTON_TAG_RESET)
+        }
+        binding.tvWeightTare.setOnClickListener {
+            viewModel.stepUiData.doingModify = false
+            clickWeightTare()
+        }
+        binding.controller.apply {
+            tempRingView.setRange(0f, 100f)
+            tempRingView.updateProgress(80)
+            tempRingView.onRingViewListener = object : RingControlView.OnRingViewListener {
+                override fun onProgressChange(progress: Int) {
+                    viewModel.stepUiData.doingModify = true
+                    onUserChangeTemp(progress)
+                }
+            }
+            speedRingView.setRange(0f, 10f)
+            speedRingView.updateProgress(2)
+            speedRingView.onRingViewListener = object : RingControlView.OnRingViewListener {
+                override fun onProgressChange(progress: Int) {
+                    viewModel.stepUiData.doingModify = true
+                    onUserChangeSpeed(progress)
+                }
+            }
+        }
+        binding.ivTurboView.setOnTouchListener { view, motionEvent ->
+            when (motionEvent.action) {
+                MotionEvent.ACTION_DOWN -> {
+                    turboDownEvent()
+                }
+                MotionEvent.ACTION_CANCEL, MotionEvent.ACTION_UP -> {
+                    turboUpEvent()
+                }
+            }
+            true
+        }
+        configureDirection()
+    }
+
+    private fun startTurbo() {
+        turboTimer?.cancel()
+        turboTimer = Timer()
+        turboTimer?.schedule(object : TimerTask() {
+            override fun run() {
+                CofarSDK.start("")
+                Log.d("ddddddd", "-----")
+            }
+        }, 0, 300)
+    }
+
+    private fun configureDirection() {
+        binding.controller.tvTurnRight.setOnClickListener {
+            viewModel.stepUiData.doingModify = true
+            updateDirection(1)
+            onSettingDirection(1)
+        }
+        binding.controller.tvTurnLeft.setOnClickListener {
+            viewModel.stepUiData.doingModify = true
+            updateDirection(0)
+            onSettingDirection(0)
+        }
+    }
+
+
+    fun updateDirection(directionValue: Int) {
+        if (directionValue == 0) {
+            binding.controller.ivDirection.rotation = 180f
+            binding.controller.tvTurnRight.setTextColor(0xffE5E5E5.toInt())
+            binding.controller.tvTurnLeft.setTextColor(0xffE60012.toInt())
+            binding.controller.tvSetDirection.updateText(getString(R.string.turn_right))
+        } else {
+            binding.controller.ivDirection.rotation = 0f
+            binding.controller.tvTurnRight.setTextColor(0xffE60012.toInt())
+            binding.controller.tvTurnLeft.setTextColor(0xffE5E5E5.toInt())
+            binding.controller.tvSetDirection.updateText(getString(R.string.turn_left ))
+        }
+    }
+
+    fun changeWeightPanel() {
+        binding.controller.root.visibility = View.GONE
+        binding.llWeightView.visibility = View.VISIBLE
+        binding.ivTurboView.visibility = View.GONE
+    }
+
+    fun changeDescription(){
+        binding.controller.root.visibility = View.GONE
+        binding.llWeightView.visibility = View.GONE
+        binding.ivTurboView.visibility = View.GONE
+    }
+
+    fun changeTurboPanel() {
+        changeTempSettingPanel()
+        binding.ivTurboView.visibility = View.VISIBLE
+    }
+
+    fun changeTempSettingPanel() {
+        binding.llWeightView.visibility = View.GONE
+        binding.controller.root.visibility = View.VISIBLE
+        binding.controller.tempRingView.visibility = View.VISIBLE
+        binding.controller.tvRingTempText.visibility = View.VISIBLE
+        binding.controller.speedRingView.visibility = View.GONE
+        binding.controller.tvSpeedText.visibility = View.GONE
+        binding.controller.clSetTime.visibility = View.GONE
+        binding.controller.flDirection.visibility = View.GONE
+        if (viewModel.displayStep()?.isTurboMode() != true) {
+            binding.ivTurboView.visibility = View.GONE
+        }
+        setPanelViewProperty(CookSettingType.TEMP_SETTING)
+    }
+
+    fun changeTimeSettingPanel() {
+        binding.llWeightView.visibility = View.GONE
+        binding.controller.root.visibility = View.VISIBLE
+        binding.controller.tempRingView.visibility = View.INVISIBLE
+        binding.controller.tvRingTempText.visibility = View.GONE
+        binding.controller.speedRingView.visibility = View.GONE
+        binding.controller.tvSpeedText.visibility = View.GONE
+        binding.controller.clSetTime.visibility = View.VISIBLE
+        binding.controller.flDirection.visibility = View.GONE
+        if (viewModel.displayStep()?.isTurboMode() != true) {
+            binding.ivTurboView.visibility = View.GONE
+        }
+        setPanelViewProperty(CookSettingType.TIME_SETTING)
+    }
+
+    fun changeSpeedSettingStep() {
+        binding.llWeightView.visibility = View.GONE
+        binding.controller.root.visibility = View.VISIBLE
+        binding.controller.tempRingView.visibility = View.INVISIBLE
+        binding.controller.tvRingTempText.visibility = View.GONE
+        binding.controller.speedRingView.visibility = View.VISIBLE
+        binding.controller.tvSpeedText.visibility = View.VISIBLE
+        binding.controller.clSetTime.visibility = View.GONE
+        binding.controller.flDirection.visibility = View.GONE
+        if (viewModel.displayStep()?.isTurboMode() != true) {
+            binding.ivTurboView.visibility = View.GONE
+        }
+        setPanelViewProperty(CookSettingType.SPEED_SETTING)
+    }
+
+    fun changeDirectionSettingStep() {
+        binding.llWeightView.visibility = View.GONE
+        binding.controller.root.visibility = View.VISIBLE
+        binding.controller.tempRingView.visibility = View.INVISIBLE
+        binding.controller.tvRingTempText.visibility = View.GONE
+        binding.controller.speedRingView.visibility = View.GONE
+        binding.controller.tvSpeedText.visibility = View.GONE
+        binding.controller.clSetTime.visibility = View.GONE
+        binding.controller.flDirection.visibility = View.VISIBLE
+        if (viewModel.displayStep()?.isTurboMode() != true) {
+            binding.ivTurboView.visibility = View.GONE
+        }
+        setPanelViewProperty(CookSettingType.DIRECTION_SETTING)
+    }
+
+    private fun setPanelViewProperty(selectStep: CookSettingType) {
+        binding.controller.apply {
+            root.tag = selectStep
+            viewSelectTemp.visibility = View.INVISIBLE
+            viewSelectTime.visibility = View.INVISIBLE
+            viewSelectSpeed.visibility = View.INVISIBLE
+            viewSelectDirection.visibility = View.INVISIBLE
+            tvTempValue.isSelected = false
+            tvTitleTemp.isSelected = false
+            tvSetTime.isSelected = false
+            tvTitleTime.isSelected = false
+            tvSetSpeed.isSelected = false
+            tvTitleSpeed.isSelected = false
+            tvSetDirection.isSelected = false
+            tvTitleDirection.isSelected = false
+            viewBackgroundTemp.isSelected = false
+            viewBackgroundTime.isSelected = false
+            viewBackgroundSpeed.isSelected = false
+            viewBackgroundDirection.isSelected = false
+            viewIconTemp.isSelected = false
+            viewIconTime.isSelected = false
+            viewIconSpeed.isSelected = false
+            viewIconDirection.isSelected = false
+            when (selectStep) {
+                CookSettingType.TEMP_SETTING -> {
+                    viewSelectTemp.visibility = View.VISIBLE
+                    tvTempValue.isSelected = true
+                    tvTitleTemp.isSelected = true
+                    viewBackgroundTemp.isSelected = true
+                    viewIconTemp.isSelected = true
+                }
+                CookSettingType.TIME_SETTING -> {
+                    viewSelectTime.visibility = View.VISIBLE
+                    tvSetTime.isSelected = true
+                    tvTitleTime.isSelected = true
+                    viewBackgroundTime.isSelected = true
+                    viewIconTime.isSelected = true
+                }
+                CookSettingType.SPEED_SETTING -> {
+                    viewSelectSpeed.visibility = View.VISIBLE
+                    tvSetSpeed.isSelected = true
+                    tvTitleSpeed.isSelected = true
+                    viewBackgroundSpeed.isSelected = true
+                    viewIconSpeed.isSelected = true
+                }
+                CookSettingType.DIRECTION_SETTING -> {
+                    viewSelectDirection.visibility = View.VISIBLE
+                    tvSetDirection.isSelected = true
+                    tvTitleDirection.isSelected = true
+                    viewBackgroundDirection.isSelected = true
+                    viewIconDirection.isSelected = true
+                }
+                else -> {}
+            }
+        }
+    }
+
+    fun getSelectedTabType(): CookSettingType {
+        return binding.controller.root.tag as? CookSettingType ?: CookSettingType.TEMP_SETTING
+    }
+
+    private fun showCookDetailDialog() {
+        if (!isCookDetailDialogShow) {
+            val dialogView = layoutInflater.inflate(
+                R.layout.item_cook_details, binding.flCookDetails, true
+            )
+            val textView = dialogView.findViewById<TextView>(R.id.tv_details)
+            textView.text = viewModel.getStepCombineText()
+            val closeView = dialogView.findViewById<View>(R.id.iv_close)
+            isCookDetailDialogShow = true
+            closeView.setOnClickListener {
+                isCookDetailDialogShow = false
+                binding.flCookDetails.removeAllViews()
+            }
+        }
+    }
+
+    @Subscribe
+    fun onDevStateEvent(event: DevStatusEvent) {
+        ThreadUtils.runOnMainThread {
+            runningState = event.devInfo.status.toInt()
+            onDevStateChange(event.devInfo)
+        }
+    }
+
+    fun playRotateAnimator(direction: Int) {
+        if (rotateAnimator == null) {
+            rotateAnimator = ObjectAnimator.ofFloat(
+                binding.controller.viewIconDirection, View.ROTATION, 0f, 360f
+            ).apply {
+                duration = 2000
+                repeatCount = ObjectAnimator.INFINITE
+                interpolator = LinearInterpolator()
+            }
+        }
+        if (rotateAnimator!!.isRunning) {
+            if (direction == rotateAnimDir) {
+                return
+            }else {
+                rotateAnimator?.cancel()
+            }
+        }
+        if (direction != 0) {
+            rotateAnimator?.reverse()
+        }else {
+            rotateAnimator?.start()
+        }
+        rotateAnimDir = direction
+    }
+
+    fun pauseRotateAnimator() {
+        rotateAnimator?.cancel()
+        binding.controller.viewIconDirection.rotation = 0f
+    }
+
+    /**
+     * turbo按下事件
+     */
+    protected fun turboDownEvent() {
+        binding.ivTurboView.setBackgroundResource(R.drawable.ic_turbo)
+        startTurbo()
+    }
+
+    /**
+     * turbo离开事件
+     */
+    protected fun turboUpEvent() {
+        binding.ivTurboView.setBackgroundResource(R.drawable.ic_turbo_unselected)
+        turboTimer?.cancel()
+        turboTimer = null
+    }
+
+    override fun onDestroy() {
+        super.onDestroy()
+        EventBus.getDefault().unregister(this)
+        turboTimer?.cancel()
+        CofarSDK.stoptWeight()
+        rotateAnimator?.cancel()
+        hasShowScreenSaver = false
+    }
+
+    companion object {
+        const val BUTTON_TAG_START = "start"
+        const val BUTTON_TAG_PAUSE = "pause"
+        const val BUTTON_TAG_RESUME = "resume"
+        const val BUTTON_TAG_STOP = "stop"
+        const val BUTTON_TAG_RESET = "reset"
+        const val BUTTON_TAG_CONFIRM = "confirm"
+        const val BUTTON_TAG_CANCEL = "cancel"
+    }
+}

+ 29 - 0
BusinessStep/src/main/java/com/develop/step/ui/cook_step/model/CookStepStatus.kt

@@ -0,0 +1,29 @@
+package com.develop.step.ui.cook_step.model
+
+import com.develop.common.data_repo.db.entity.DevRecipeCookingStep
+
+
+class CookStepStatus(
+    val workMode: String,
+    val source: DevRecipeCookingStep,
+) {
+    var hasStarted = false
+    var hasComplete = false
+    val uiData = CookStepUiData()
+
+    fun isWeightMode(): Boolean {
+        return workMode == "WIGHT" || workMode == "WEIGH" || workMode == "WEIGHT"
+    }
+
+    fun isTurboMode(): Boolean {
+        return workMode == "TURBO"
+    }
+
+    fun isDescription():Boolean {
+        return  workMode == "DESCRIPTION";
+    }
+
+    fun isManualStep(): Boolean {
+        return isWeightMode() || isTurboMode()
+    }
+}

+ 135 - 0
BusinessStep/src/main/java/com/develop/step/ui/cook_step/model/CookStepUiData.kt

@@ -0,0 +1,135 @@
+package com.develop.step.ui.cook_step.model
+
+import com.develop.common.data_repo.db.entity.DevRecipeCookingStep
+import com.kuyuntech.cofarcooking.device.sdk.constant.core.DevStatus
+import com.kuyuntech.cofarcooking.device.sdk.util.core.CofarSDK
+
+class CookStepUiData {
+    var doingModify = false
+    var runningStatus = DevStatus.STOP.toInt()
+
+    // 设置目标温度
+    var targetTemp = 0
+    // 设置目标时间
+    var targetTime = 0
+
+    // 当前温度
+    var currentTemp = 0
+    // 当前时间
+    var currentTime = 0
+    // 当前剩余时间
+    var remainTime = 0
+    // targetTimeBuffer
+    var targetTimeBuffer = 0
+    // 称重数
+    var weightNum = 0
+    // 当前方向
+    var direction = 0
+    // 当前转速
+    var currentSpeed = 0
+
+    // 限制时间调整范围
+    var limitMinTime = 0
+    var limitMaxTime = 0
+
+    // 限制温度调整范围
+    var limitMinTemp = 0
+    var limitMaxTemp = 0
+
+    // 限制转速调整范围
+    var limitMinSpeed = 0
+    var limitMaxSpeed = 0
+
+    //是否可以修改参数
+    var isTempChange = false
+    var isTimeChange = false
+    var isMotorGearChange = false
+    var isMotorDirectionChange = false
+
+    fun applyRecipeSetting(data: DevRecipeCookingStep) {
+        targetTime = (data.minute ?: 0) * 60 + (data.second ?: 0)
+        targetTemp = data.temperature ?: 0
+        direction = if (data.rotateDirection == "0") 0 else 1
+
+
+        currentSpeed = data.rotateSpeed ?: 0
+//        remainTime = targetTime
+        CofarSDK.devMode(data.workMode).let {
+            limitMinTime = it.minTime
+            limitMaxTime = it.maxTime
+            limitMinTemp = it.minTemp
+            limitMaxTemp = it.maxTemp
+            limitMinSpeed = it.minMotorGear
+            limitMaxSpeed = it.maxMotorGear
+            isTempChange = it.isTempChange
+            isTimeChange = it.isTimeChange
+            isMotorGearChange = it.isMotorGearChange
+            isMotorDirectionChange = it.isMotorDirectionChange
+        }
+        targetTime = getFixedValue(targetTime, limitMinTime, limitMaxTime)
+        targetTemp = getFixedValue(targetTemp, limitMinTemp, limitMaxTemp)
+        currentSpeed = getFixedValue(currentSpeed, limitMinSpeed, limitMaxSpeed)
+
+
+
+    }
+
+    private fun getFixedValue(source: Int, min: Int, max: Int): Int {
+        if (source < min) {
+            return min
+        }
+        if (source > max) {
+            return source
+        }
+        return source
+    }
+
+    fun newCopy(): CookStepUiData {
+        val uiData = CookStepUiData()
+        uiData.let {
+            it.targetTemp = targetTemp
+            it.targetTime = targetTime
+            it.currentTemp = currentTemp
+            it.currentTime = currentTime
+            it.remainTime = remainTime
+            it.weightNum = weightNum
+            it.direction = direction
+            it.currentSpeed = currentSpeed
+            it.limitMinTime = limitMinTime
+            it.limitMaxTime = limitMaxTime
+            it.limitMinTemp = limitMinTemp
+            it.limitMaxTemp = limitMaxTemp
+            it.limitMinSpeed = limitMinSpeed
+            it.limitMaxSpeed = limitMaxSpeed
+            it.isTempChange = isTempChange
+            it.isTimeChange = isTimeChange
+            it.isMotorGearChange = isMotorGearChange
+            it.isMotorDirectionChange = isMotorDirectionChange
+        }
+        return uiData
+    }
+    
+    fun copyFrom(uiData: CookStepUiData): CookStepUiData {
+        uiData.let {
+            targetTemp = it.targetTemp
+            targetTime = it.targetTime
+            currentTemp = it.currentTemp
+            currentTime = it.currentTime
+            remainTime = it.remainTime
+            weightNum = it.weightNum
+            direction = it.direction
+            currentSpeed = it.currentSpeed
+            limitMinTime = it.limitMinTime
+            limitMaxTime = it.limitMaxTime
+            limitMinTemp = it.limitMinTemp
+            limitMaxTemp = it.limitMaxTemp
+            limitMinSpeed = it.limitMinSpeed
+            limitMaxSpeed = it.limitMaxSpeed
+            isTempChange = it.isTempChange
+            isTimeChange = it.isTimeChange
+            isMotorGearChange = it.isMotorGearChange
+            isMotorDirectionChange = it.isMotorDirectionChange
+        }
+        return uiData
+    }
+}

+ 15 - 14
BusinessStep/src/main/java/com/develop/step/ui/recipes_detail/CookDetailActivity.kt

@@ -20,8 +20,8 @@ import com.develop.common.router.Screens
 import com.develop.common.tag.CURRENT_USER_ID
 import com.develop.common.ui.CommonBVMActivity
 import com.develop.common.utils.Resource
-import com.develop.common.widget.DownloadFailedDialog
-import com.develop.common.widget.ShareQRCodeDialog
+import com.develop.common.dialog.DownloadFailedDialog
+import com.develop.common.dialog.ShareQRCodeDialog
 import com.develop.step.databinding.ActivityCookDetailBinding
 import com.develop.step.viewmodel.CookDetailViewModel
 import java.util.*
@@ -54,6 +54,13 @@ class CookDetailActivity : CommonBVMActivity<ActivityCookDetailBinding, CookDeta
     private val hideViews = mutableListOf<View>()
     private val allTabViews = mutableListOf<View>()
 
+    private val shareQRCodeDialog by lazy {
+        ShareQRCodeDialog()
+    }
+
+    private val downloadFileDialog by lazy {
+        DownloadFailedDialog()
+    }
 
     override fun createViewModel(): CookDetailViewModel {
         return getViewModel(CookDetailViewModel::class.java)
@@ -198,10 +205,10 @@ class CookDetailActivity : CommonBVMActivity<ActivityCookDetailBinding, CookDeta
                 return@setOnClickListener
             }
             binding.clFuncMore.setGone()
-            supportFragmentManager
-                .beginTransaction()
-                .add(ShareQRCodeDialog(number), "ShareQRCodeDialog")
-                .commitAllowingStateLoss()
+            shareQRCodeDialog.apply {
+                recipeNum = number
+                showDialog(supportFragmentManager,"ShareQRCodeDialog")
+            }
         }
         binding.viewServing.setOnClickListener {
             showAmountSelectDialog()
@@ -313,10 +320,7 @@ class CookDetailActivity : CommonBVMActivity<ActivityCookDetailBinding, CookDeta
                 binding.viewProgress.setProgress(1f)
                 binding.viewProgress.setButtonColor(Color.parseColor("#1296db"))
                 binding.viewIcon.setImageResource(com.develop.common.R.drawable.ic_detail_cook_download)
-                supportFragmentManager
-                    .beginTransaction()
-                    .add(DownloadFailedDialog(), "DownloadFailedDialog")
-                    .commitAllowingStateLoss()
+                downloadFileDialog.showDialog(supportFragmentManager,"DownloadFailedDialog")
             }
             Resource.Status.LOADING -> {
                 val updateProgress = "${resource.data}%"
@@ -372,10 +376,7 @@ class CookDetailActivity : CommonBVMActivity<ActivityCookDetailBinding, CookDeta
                 }
             })
         }
-        supportFragmentManager
-            .beginTransaction()
-            .add(dialog, "RecipeDeleteConfirmDialog")
-            .commitAllowingStateLoss()
+        dialog.showDialog(supportFragmentManager,"RecipeDeleteConfirmDialog")
     }
 
     companion object {

+ 96 - 0
BusinessStep/src/main/java/com/develop/step/ui/recipes_detail/CookEvaluateActivity.kt

@@ -0,0 +1,96 @@
+package com.develop.step.ui.recipes_detail
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import com.alibaba.android.arouter.facade.annotation.Autowired
+import com.alibaba.android.arouter.facade.annotation.Route
+import com.alibaba.android.arouter.launcher.ARouter
+import com.blankj.utilcode.util.KeyboardUtils
+import com.develop.base.util.GlobalToast
+import com.develop.common.data_repo.FoodDataProvider
+import com.develop.common.data_repo.db.entity.UserTag
+import com.develop.common.router.Screens
+import com.develop.common.tag.CURRENT_USER_ID
+import com.develop.common.ui.CommonBindingActivity
+import com.develop.common.R
+
+import com.develop.step.databinding.ActivityCookEvaluateBinding
+
+@Route(path = Screens.Cook.COOK_EVALUATE)
+class CookEvaluateActivity : CommonBindingActivity<ActivityCookEvaluateBinding>() {
+    override fun createViewBinding(inflater: LayoutInflater): ActivityCookEvaluateBinding {
+        return ActivityCookEvaluateBinding.inflate(inflater)
+    }
+
+    private val starViews = mutableListOf<View>()
+
+    @JvmField
+    @Autowired(name = "recipeId")
+    var recipeId = ""
+
+    private var starCount = 0
+    private var evaluateContent = ""
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        ARouter.getInstance().inject(this)
+
+        binding.let {
+            starViews.add(it.ivStar1)
+            starViews.add(it.ivStar2)
+            starViews.add(it.ivStar3)
+            starViews.add(it.ivStar4)
+            starViews.add(it.ivStar5)
+        }
+
+        binding.root.setOnClickListener {
+            KeyboardUtils.hideSoftInput(this)
+        }
+
+        binding.ivStar1.setOnClickListener {
+            selectStar(1)
+            starCount = 1
+            binding.tvGood.text = getString(R.string.bad)
+        }
+        binding.ivStar2.setOnClickListener {
+            selectStar(2)
+            starCount = 2
+            binding.tvGood.text = getString(R.string.imperfect)
+        }
+        binding.ivStar3.setOnClickListener {
+            selectStar(3)
+            starCount = 3
+            binding.tvGood.text = getString(R.string.ordinary)
+        }
+        binding.ivStar4.setOnClickListener {
+            selectStar(4)
+            starCount = 4
+            binding.tvGood.text = getString(R.string.good)
+        }
+        binding.ivStar5.setOnClickListener {
+            selectStar(5)
+            starCount = 5
+            binding.tvGood.text = getString(R.string.perfect)
+        }
+        binding.viewClose.setOnClickListener {
+            finish()
+        }
+
+        binding.tvOk.setOnClickListener {
+            KeyboardUtils.hideSoftInput(this)
+            evaluateContent = binding.etContent.text.toString()
+            FoodDataProvider.getUserDatabase().runInTransaction {
+                val userTag = UserTag(CURRENT_USER_ID, recipeId, starCount, evaluateContent)
+                FoodDataProvider.getUserDatabase().userInfoDao().updateUserTag(userTag)
+            }
+            GlobalToast.showToast("Evaluate successfully")
+
+        }
+    }
+
+    private fun selectStar(count: Int) {
+        for (index in starViews.indices) {
+            starViews[index].isSelected = index + 1 <= count
+        }
+    }
+}

+ 157 - 0
BusinessStep/src/main/java/com/develop/step/viewmodel/CookStepViewModel.kt

@@ -0,0 +1,157 @@
+package com.develop.step.viewmodel
+
+import android.graphics.Color
+import android.text.SpannableStringBuilder
+import android.text.Spanned
+import android.text.style.ForegroundColorSpan
+import android.util.Log
+import androidx.lifecycle.MutableLiveData
+import com.develop.base.mvvm.BaseViewModel
+import com.develop.common.data_repo.FoodDataProvider
+import com.develop.step.CookSettingType
+import com.develop.step.ui.cook_step.model.CookStepStatus
+import com.develop.step.ui.cook_step.model.CookStepUiData
+import com.develop.step.ui.recipes_detail.model.CookStatus
+import com.kuyuntech.cofarcooking.device.sdk.constant.core.DevStatus
+import java.util.concurrent.CopyOnWriteArrayList
+
+class CookStepViewModel:BaseViewModel() {
+
+    @Deprecated("后面会移除下面这些CookStatus")
+    val tempStatus = CookStatus.Temp(80)
+    val timeStatus = CookStatus.Time(5, 0, 0)
+    val speedStatus = CookStatus.Speed(2, 0)
+    val directionStatus = CookStatus.Direction(1, 1)
+    val currentSetting = MutableLiveData(CookSettingType.WEIGHT)
+    val stepUiData = CookStepUiData()
+
+    var stepIndex = 0
+
+    // 默认属性, 只读
+    val dataCopy = mutableListOf<CookStepUiData>()
+    val allSteps = CopyOnWriteArrayList<CookStepStatus>()
+    val stepDisplay = MutableLiveData<CookStepStatus>()
+    var cookingStep: CookStepStatus? = null
+
+    fun queryRecipeCookStep(number: String, currentStepIndex: Int = 0) {
+        FoodDataProvider.getDatabase().runInTransaction {
+            allSteps.clear()
+            val cookSteps = FoodDataProvider
+                .getDatabase()
+                .recipeDao()
+                .queryCookingStep(number)
+            if (cookSteps.isEmpty()) {
+                return@runInTransaction
+            }
+            Log.d("Step", "total count:${cookSteps.size}")
+            for (cookStep in cookSteps) {
+                val stepStatus = CookStepStatus(
+                    cookStep.workMode ?: "", cookStep
+                )
+                stepStatus.uiData.applyRecipeSetting(cookStep)
+                allSteps.add(stepStatus)
+                dataCopy.add(stepStatus.uiData.newCopy())
+            }
+            stepIndex = currentStepIndex
+            if (allSteps.isNotEmpty() && allSteps.size > currentStepIndex) {
+                allSteps[currentStepIndex].let {
+                    stepDisplay.value = it
+                    cookingStep = it
+                }
+            }
+        }
+    }
+
+    fun nextStep() {
+        if (stepIndex >= allSteps.size - 1) {
+            return
+        }
+        stepIndex++
+        allSteps.getOrNull(stepIndex)?.let {
+            stepDisplay.value = it
+        }
+    }
+
+    fun prevStep() {
+        if (stepIndex <= 0) {
+            return
+        }
+        stepIndex--
+        allSteps.getOrNull(stepIndex)?.let {
+            stepDisplay.value = it
+        }
+    }
+
+    fun setDisplayStep(index: Int) {
+        stepIndex = index
+        allSteps.getOrNull(stepIndex)?.let {
+            if (stepDisplay.value != it) {
+                stepDisplay.value = it
+            }
+        }
+    }
+
+    fun getStepCount(): Int {
+        return allSteps.size
+    }
+
+    fun isFirstStep(step: CookStepStatus): Boolean {
+        return allSteps.indexOf(step) == 0
+    }
+
+    fun isFinalStep(step: CookStepStatus): Boolean {
+        return allSteps.indexOf(step) == allSteps.size - 1
+    }
+
+    fun changeStep(step: CookSettingType) {
+        currentSetting.value = step
+    }
+
+    fun getNextStep(step: CookStepStatus): CookStepStatus? {
+        val index = allSteps.indexOf(step)
+        if (index < 0) {
+            return null
+        }
+        return allSteps.getOrNull(index + 1)
+    }
+
+    fun setTargetCookingStep(cookStep: CookStepStatus) {
+        val stepIndex = allSteps.indexOf(cookStep)
+        if (stepIndex < 0) {
+            return
+        }
+        cookStep.hasComplete = false
+        cookStep.hasStarted = false
+        cookingStep = cookStep
+        setDisplayStep(stepIndex)
+    }
+
+    fun displayStep(): CookStepStatus? {
+        return stepDisplay.value
+    }
+
+    fun isCurrentOnCookingStep(): Boolean {
+        return displayStep() == cookingStep
+    }
+
+    fun isCookingStepStarted(): Boolean {
+        return cookingStep != null && cookingStep?.uiData?.runningStatus != DevStatus.STOP.toInt()
+    }
+
+    fun getStepCombineText(): CharSequence {
+        val spanBuilder = SpannableStringBuilder()
+        for (step in allSteps) {
+            if (step == displayStep()) {
+                spanBuilder.append(
+                    step.source.description,
+                    ForegroundColorSpan(Color.parseColor("#E60012")),
+                    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
+                )
+            } else {
+                spanBuilder.append(step.source.description)
+            }
+            spanBuilder.append("\n\n")
+        }
+        return spanBuilder
+    }
+}

+ 120 - 0
BusinessStep/src/main/res/layout/activity_cook_evaluate.xml

@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools">
+
+    <TextView
+        android:id="@+id/tv_good"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textColor="#FFA627"
+        android:textSize="@dimen/convert_108px"
+        android:text="@string/bad"
+        android:layout_marginTop="@dimen/convert_248px"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintTop_toTopOf="parent"/>
+
+    <LinearLayout
+        android:id="@+id/ll_stars"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal"
+        android:gravity="center_vertical"
+        android:layout_marginTop="@dimen/convert_105px"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/tv_good">
+
+        <ImageView
+            android:id="@+id/iv_star1"
+            android:layout_width="@dimen/convert_81px"
+            android:layout_height="@dimen/convert_75px"
+            android:src="@drawable/ic_star_unselected"
+            app:tint="@color/detail_star_tint2"
+            tools:tint="#f4a12e"/>
+
+        <ImageView
+            android:id="@+id/iv_star2"
+            android:layout_width="@dimen/convert_81px"
+            android:layout_height="@dimen/convert_75px"
+            android:src="@drawable/ic_star_unselected"
+            app:tint="@color/detail_star_tint2"
+            tools:tint="#f4a12e"
+            android:layout_marginStart="@dimen/convert_39px"/>
+
+        <ImageView
+            android:id="@+id/iv_star3"
+            android:layout_width="@dimen/convert_81px"
+            android:layout_height="@dimen/convert_75px"
+            android:src="@drawable/ic_star_unselected"
+            app:tint="@color/detail_star_tint2"
+            tools:tint="#f4a12e"
+            android:layout_marginStart="@dimen/convert_39px"/>
+
+        <ImageView
+            android:id="@+id/iv_star4"
+            android:layout_width="@dimen/convert_81px"
+            android:layout_height="@dimen/convert_75px"
+            android:src="@drawable/ic_star_unselected"
+            app:tint="@color/detail_star_tint2"
+            tools:tint="#f4a12e"
+            android:layout_marginStart="@dimen/convert_39px"/>
+
+        <ImageView
+            android:id="@+id/iv_star5"
+            android:layout_width="@dimen/convert_81px"
+            android:layout_height="@dimen/convert_75px"
+            android:src="@drawable/ic_star_unselected"
+            app:tint="@color/detail_star_tint2"
+            tools:tint="#f4a12e"
+            android:layout_marginStart="@dimen/convert_39px"/>
+
+    </LinearLayout>
+
+    <EditText
+        android:imeOptions="actionDone"
+        android:id="@+id/et_content"
+        android:layout_width="@dimen/convert_930px"
+        android:layout_height="@dimen/convert_389px"
+        android:background="@drawable/bg_evaluate_content"
+        android:layout_marginTop="@dimen/convert_84px"
+        android:padding="@dimen/convert_53px"
+        android:hint="@string/enter_what_you_want_to_say"
+        android:gravity="start"
+        android:textColor="#000000"
+        android:textColorHint="#6B6B6B"
+        android:textSize="@dimen/convert_39px"
+        app:layout_constraintTop_toBottomOf="@+id/ll_stars"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"/>
+
+    <ImageView
+        android:id="@+id/view_close"
+        android:layout_width="@dimen/convert_90px"
+        android:layout_height="@dimen/convert_90px"
+        android:src="@drawable/ic_cancel"
+        app:tint="#FFA627"
+        android:padding="@dimen/convert_16px"
+        android:layout_marginStart="@dimen/convert_45px"
+        android:layout_marginTop="@dimen/convert_45px"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent"/>
+
+    <TextView
+        android:id="@+id/tv_ok"
+        android:layout_width="@dimen/convert_930px"
+        android:layout_height="@dimen/convert_120px"
+        android:layout_marginTop="@dimen/convert_143px"
+        android:background="@drawable/bg_tare_button"
+        android:gravity="center"
+        android:textColor="#fff"
+        android:text="@string/ok"
+        app:layout_constraintTop_toBottomOf="@+id/et_content"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"/>
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 192 - 0
BusinessStep/src/main/res/layout/activity_cook_step_base.xml

@@ -0,0 +1,192 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    xmlns:app="http://schemas.android.com/apk/res-auto">
+
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:id="@+id/cl_status_bar"
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/convert_132px"
+        android:background="#FFA627"
+        app:layout_constraintTop_toTopOf="parent">
+
+        <View
+            android:id="@+id/view_back"
+            android:layout_width="@dimen/convert_120px"
+            android:layout_height="@dimen/convert_132px"
+            android:background="@drawable/ic_cook_back"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent"/>
+
+        <View
+            android:id="@+id/view_progress"
+            android:layout_width="0dp"
+            android:layout_height="@dimen/convert_15px"
+            app:layout_constraintStart_toEndOf="@+id/view_back"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintBottom_toBottomOf="parent"/>
+
+        <TextView
+            android:id="@+id/tv_title_step"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:text="Step1:Peel 3 onions(180g)and2..."
+            android:gravity="center_vertical"
+            android:textColor="#ffffff"
+            android:textSize="@dimen/convert_45px"
+            android:maxLines="1"
+            android:ellipsize="end"
+            android:layout_marginStart="@dimen/convert_51px"
+            android:layout_marginEnd="@dimen/convert_70px"
+            app:layout_constraintStart_toEndOf="@+id/view_back"
+            app:layout_constraintEnd_toStartOf="@+id/view_alarm"/>
+
+        <View
+            android:id="@+id/view_alarm"
+            android:layout_width="@dimen/convert_75px"
+            android:layout_height="@dimen/convert_59px"
+            android:background="@drawable/ic_alarm"
+            android:layout_marginEnd="@dimen/convert_45px"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintTop_toTopOf="parent"
+            app:layout_constraintBottom_toBottomOf="parent"/>
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+
+    <ImageView
+        android:id="@+id/iv_cook_bg"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:scaleType="centerCrop"
+        app:layout_constraintTop_toBottomOf="@+id/cl_status_bar"
+        app:layout_constraintBottom_toBottomOf="parent"/>
+
+    <View
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:background="@drawable/bg_cook_mask"
+        app:layout_constraintTop_toBottomOf="@+id/cl_status_bar"
+        app:layout_constraintBottom_toBottomOf="parent"/>
+
+    <TextView
+        android:id="@+id/tv_step_name"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:text="Step1:Peel 3 onions(180g)and2garlic cloves,halve the onions andput both in the blender jug."
+        android:textColor="#fff"
+        android:layout_marginStart="@dimen/convert_77px"
+        android:layout_marginTop="@dimen/convert_77px"
+        android:layout_marginEnd="@dimen/convert_99px"
+        android:textSize="@dimen/convert_39px"
+        android:lineSpacingExtra="10dp"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toStartOf="@+id/view_remark"
+        app:layout_constraintTop_toBottomOf="@+id/cl_status_bar"/>
+
+    <View
+        android:id="@+id/view_remark"
+        android:layout_width="@dimen/convert_122px"
+        android:layout_height="@dimen/convert_120px"
+        android:layout_marginTop="@dimen/convert_47px"
+        android:layout_marginEnd="@dimen/convert_45px"
+        android:background="@drawable/ic_remark"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/cl_status_bar"/>
+
+    <ImageView
+        android:id="@+id/iv_prev_step"
+        android:layout_width="@dimen/convert_90px"
+        android:layout_height="@dimen/convert_90px"
+        android:src="@drawable/ic_cook_prev_step"
+        android:layout_marginStart="@dimen/convert_48px"
+        app:layout_constraintVertical_bias="0.4"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintBottom_toBottomOf="parent"/>
+
+    <ImageView
+        android:id="@+id/iv_next_step"
+        android:layout_width="@dimen/convert_90px"
+        android:layout_height="@dimen/convert_90px"
+        android:src="@drawable/ic_cook_next_step"
+        android:layout_marginEnd="@dimen/convert_48px"
+        app:layout_constraintVertical_bias="0.4"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintBottom_toBottomOf="parent"/>
+
+    <include
+        android:id="@+id/controller"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        layout="@layout/item_cook_controller"
+        android:layout_marginBottom="@dimen/convert_64px"
+        app:layout_constraintBottom_toBottomOf="parent"/>
+
+    <FrameLayout
+        android:id="@+id/fl_cook_details"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        app:layout_constraintTop_toBottomOf="@+id/cl_status_bar"
+        app:layout_constraintBottom_toBottomOf="parent"/>
+
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:id="@+id/ll_weight_view"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+        app:layout_constraintBottom_toBottomOf="parent">
+
+        <TextView
+            android:id="@+id/tv_weight_num"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textColor="#ffffff"
+            android:textSize="@dimen/convert_180px"
+            android:text="50g"
+            android:layout_marginBottom="@dimen/convert_80px"
+            android:includeFontPadding="false"
+            android:layout_gravity="center_horizontal"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintBottom_toTopOf="@+id/weight_view"/>
+
+        <com.develop.common.widget.WeightView
+            android:id="@+id/weight_view"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="@dimen/convert_83px"
+            app:layout_constraintBottom_toBottomOf="parent"/>
+
+        <TextView
+            android:id="@+id/tv_weight_tare"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:paddingHorizontal="@dimen/convert_80px"
+            android:paddingVertical="@dimen/convert_20px"
+            android:textColor="#ffffff"
+            android:textSize="@dimen/convert_56px"
+            android:text="@string/tare"
+            android:includeFontPadding="false"
+            android:layout_marginBottom="@dimen/convert_66px"
+            android:background="@drawable/bg_tare_button"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintBottom_toBottomOf="parent"/>
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+
+    <ImageView
+        android:visibility="visible"
+        android:id="@+id/iv_turbo_view"
+        android:layout_width="@dimen/convert_200px"
+        android:layout_height="@dimen/convert_200px"
+        android:layout_marginBottom="@dimen/convert_64px"
+        android:background="@drawable/ic_turbo_unselected"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintBottom_toBottomOf="parent"/>
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 432 - 0
BusinessStep/src/main/res/layout/item_cook_controller.xml

@@ -0,0 +1,432 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    xmlns:tools="http://schemas.android.com/tools"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:paddingHorizontal="@dimen/convert_75px">
+
+    <com.develop.common.widget.RingControlView
+        android:id="@+id/temp_ring_view"
+        android:layout_width="@dimen/convert_500px"
+        android:layout_height="@dimen/convert_500px"
+        android:visibility="invisible"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintVertical_bias="0.35"/>
+
+    <com.develop.common.widget.RingControlView
+        android:id="@+id/speed_ring_view"
+        android:layout_width="@dimen/convert_500px"
+        android:layout_height="@dimen/convert_500px"
+        android:visibility="invisible"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintVertical_bias="0.35"/>
+
+    <TextView
+        android:id="@+id/tv_speed_text"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="2"
+        android:textColor="#E60012"
+        android:textSize="@dimen/convert_90px"
+        android:visibility="gone"
+        app:layout_constraintBottom_toBottomOf="@+id/speed_ring_view"
+        app:layout_constraintEnd_toEndOf="@+id/speed_ring_view"
+        app:layout_constraintStart_toStartOf="@+id/speed_ring_view"
+        app:layout_constraintTop_toTopOf="@+id/speed_ring_view"
+        app:layout_constraintVertical_bias="0.45" />
+
+    <TextView
+        android:id="@+id/tv_ring_temp_text"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textColor="#E60012"
+        android:textSize="@dimen/convert_90px"
+        android:text="80°C"
+        android:visibility="gone"
+        tools:visibility="visible"
+        app:layout_constraintStart_toStartOf="@+id/temp_ring_view"
+        app:layout_constraintEnd_toEndOf="@+id/temp_ring_view"
+        app:layout_constraintTop_toTopOf="@+id/temp_ring_view"
+        app:layout_constraintBottom_toBottomOf="@+id/temp_ring_view"
+        app:layout_constraintVertical_bias="0.45"/>
+
+    <com.develop.common.widget.TimePickerView
+        android:id="@+id/cl_set_time"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:visibility="gone"
+        tools:background="#aaa"
+        tools:visibility="gone"
+        app:time_color="@color/color_fff"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintVertical_bias="0.36"/>
+
+    <TextView
+        android:id="@+id/tv_countdown_time"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textColor="#ffffff"
+        android:textSize="@dimen/convert_54px"
+        android:text="--05:00--"
+        android:visibility="gone"
+        android:layout_marginBottom="@dimen/convert_6px"
+        app:layout_constraintBottom_toTopOf="@+id/cl_set_time"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"/>
+
+    <FrameLayout
+        android:id="@+id/fl_direction"
+        android:layout_width="@dimen/convert_500px"
+        android:layout_height="@dimen/convert_500px"
+        android:visibility="gone"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintVertical_bias="0.36">
+
+        <ImageView
+            android:id="@+id/iv_direction"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:src="@drawable/ic_direction" />
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:orientation="horizontal">
+
+            <TextView
+                android:id="@+id/tv_turn_right"
+                android:layout_width="0dp"
+                android:layout_height="match_parent"
+                android:gravity="center"
+                android:paddingStart="@dimen/convert_60px"
+                android:layout_weight="1"
+                android:text="@string/turn_left"
+                android:textColor="@color/color_E60012"
+                android:textSize="@dimen/convert_39px" />
+
+            <TextView
+                android:id="@+id/tv_turn_left"
+                android:layout_width="0dp"
+                android:layout_height="match_parent"
+                android:layout_weight="1"
+                android:gravity="center"
+                android:paddingEnd= "@dimen/convert_60px"
+                android:text="@string/turn_right"
+                android:textColor="@color/color_E5E5E5"
+                android:textSize="@dimen/convert_39px" />
+        </LinearLayout>
+
+    </FrameLayout>
+
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:id="@+id/cl_cook_temp"
+        android:layout_width="@dimen/convert_210px"
+        android:layout_height="wrap_content"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/temp_ring_view"
+        app:layout_constraintBottom_toTopOf="@+id/btn_start">
+
+        <com.develop.common.widget.TriangleView
+            android:id="@+id/view_select_temp"
+            android:layout_width="@dimen/convert_72px"
+            android:layout_height="@dimen/convert_42px"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintTop_toTopOf="parent"/>
+
+        <View
+            android:id="@+id/view_background_temp"
+            android:layout_width="match_parent"
+            android:layout_height="@dimen/convert_330px"
+            app:layout_constraintTop_toBottomOf="@+id/view_select_temp"
+            android:background="@drawable/bg_cook_item_selected"/>
+
+        <TextView
+            android:id="@+id/tv_temp_value"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="80°C"
+            android:textColor="@color/cook_panel_text"
+            android:textSize="@dimen/convert_54px"
+            android:layout_marginTop="@dimen/convert_45px"
+            android:includeFontPadding="false"
+            app:layout_constraintTop_toTopOf="@+id/view_background_temp"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"/>
+
+        <ImageView
+            android:id="@+id/view_icon_temp"
+            android:layout_width="@dimen/convert_60px"
+            android:layout_height="@dimen/convert_60px"
+            android:src="@drawable/ic_cook_temp"
+            android:scaleType="fitCenter"
+            android:layout_marginBottom="@dimen/convert_70px"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:tint="@color/cook_panel_text" />
+
+        <TextView
+            android:id="@+id/tv_title_temp"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/temperature"
+            android:textSize="@dimen/convert_27px"
+            android:textColor="@color/cook_panel_text"
+            android:layout_marginTop="@dimen/convert_8px"
+            app:layout_constraintTop_toBottomOf="@+id/view_icon_temp"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"/>
+
+        <TextView
+            android:id="@+id/tv_cooking_temp_target"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textColor="#FFA627"
+            android:text="--80°C--"
+            android:textSize="@dimen/convert_36px"
+            android:visibility="visible"
+            android:layout_marginTop="@dimen/convert_16px"
+            app:layout_constraintTop_toBottomOf="@+id/tv_temp_value"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"/>
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:id="@+id/cl_cook_time"
+        android:layout_width="@dimen/convert_210px"
+        android:layout_height="wrap_content"
+        app:layout_constraintStart_toEndOf="@+id/cl_cook_temp"
+        app:layout_constraintEnd_toStartOf="@+id/cl_cook_speed"
+        app:layout_constraintTop_toTopOf="@+id/cl_cook_temp">
+
+        <com.develop.common.widget.TriangleView
+            android:id="@+id/view_select_time"
+            android:layout_width="@dimen/convert_72px"
+            android:layout_height="@dimen/convert_42px"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintTop_toTopOf="parent"/>
+
+        <View
+            android:id="@+id/view_background_time"
+            android:layout_width="match_parent"
+            android:layout_height="@dimen/convert_330px"
+            app:layout_constraintTop_toBottomOf="@+id/view_select_time"
+            android:background="@drawable/bg_cook_item_selected"/>
+
+        <TextView
+            android:id="@+id/tv_set_time"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="00:60"
+            android:textColor="@color/cook_panel_text"
+            android:textSize="@dimen/convert_54px"
+            android:includeFontPadding="false"
+            android:layout_marginTop="@dimen/convert_45px"
+            app:layout_constraintTop_toTopOf="@+id/view_background_time"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"/>
+
+        <ImageView
+            android:id="@+id/view_icon_time"
+            android:layout_width="@dimen/convert_60px"
+            android:layout_height="@dimen/convert_60px"
+            android:src="@drawable/ic_cook_time"
+            android:scaleType="fitCenter"
+            android:layout_marginBottom="@dimen/convert_68px"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:tint="@color/cook_panel_text" />
+
+        <TextView
+            android:id="@+id/tv_title_time"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/time"
+            android:textSize="@dimen/convert_27px"
+            android:textColor="@color/cook_panel_text"
+            android:layout_marginTop="@dimen/convert_8px"
+            app:layout_constraintTop_toBottomOf="@+id/view_icon_time"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"/>
+
+        <TextView
+            android:id="@+id/tv_cooking_time_target"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textColor="#FFA627"
+            android:text="--05:00--"
+            android:textSize="@dimen/convert_36px"
+            android:layout_marginTop="@dimen/convert_16px"
+            android:visibility="visible"
+            app:layout_constraintTop_toBottomOf="@+id/tv_set_time"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"/>
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:id="@+id/cl_cook_speed"
+        android:layout_width="@dimen/convert_210px"
+        android:layout_height="wrap_content"
+        app:layout_constraintStart_toEndOf="@+id/cl_cook_time"
+        app:layout_constraintEnd_toStartOf="@+id/cl_cook_direction"
+        app:layout_constraintTop_toTopOf="@+id/cl_cook_temp">
+
+        <com.develop.common.widget.TriangleView
+            android:id="@+id/view_select_speed"
+            android:layout_width="@dimen/convert_72px"
+            android:layout_height="@dimen/convert_42px"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintTop_toTopOf="parent"/>
+
+        <View
+            android:id="@+id/view_background_speed"
+            android:layout_width="match_parent"
+            android:layout_height="@dimen/convert_330px"
+            app:layout_constraintTop_toBottomOf="@+id/view_select_speed"
+            android:background="@drawable/bg_cook_item_selected"/>
+
+        <TextView
+            android:id="@+id/tv_set_speed"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="2"
+            android:textColor="@color/cook_panel_text"
+            android:textSize="@dimen/convert_54px"
+            android:layout_marginTop="@dimen/convert_45px"
+            android:includeFontPadding="false"
+            app:layout_constraintTop_toTopOf="@+id/view_background_speed"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"/>
+
+        <ImageView
+            android:id="@+id/view_icon_speed"
+            android:layout_width="@dimen/convert_60px"
+            android:layout_height="@dimen/convert_60px"
+            android:src="@drawable/ic_cook_quick"
+            android:scaleType="fitCenter"
+            android:layout_marginBottom="@dimen/convert_70px"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:tint="@color/cook_panel_text"/>
+
+        <TextView
+            android:id="@+id/tv_title_speed"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/speed"
+            android:textSize="@dimen/convert_27px"
+            android:textColor="@color/cook_panel_text"
+            android:layout_marginTop="@dimen/convert_8px"
+            app:layout_constraintTop_toBottomOf="@+id/view_icon_speed"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"/>
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:id="@+id/cl_cook_direction"
+        android:layout_width="@dimen/convert_210px"
+        android:layout_height="wrap_content"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintTop_toTopOf="@+id/cl_cook_temp">
+
+        <com.develop.common.widget.TriangleView
+            android:id="@+id/view_select_direction"
+            android:layout_width="@dimen/convert_72px"
+            android:layout_height="@dimen/convert_42px"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintTop_toTopOf="parent"/>
+
+        <View
+            android:id="@+id/view_background_direction"
+            android:layout_width="match_parent"
+            android:layout_height="@dimen/convert_330px"
+            app:layout_constraintTop_toBottomOf="@+id/view_select_direction"
+            android:background="@drawable/bg_cook_item_selected"/>
+
+        <TextView
+            android:id="@+id/tv_set_direction"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/turn_right"
+            android:textColor="@color/cook_panel_text"
+            android:textSize="@dimen/convert_36px"
+            android:layout_marginTop="@dimen/convert_45px"
+            android:includeFontPadding="false"
+            app:layout_constraintTop_toTopOf="@+id/view_background_direction"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"/>
+
+        <ImageView
+            android:id="@+id/view_icon_direction"
+            android:layout_width="@dimen/convert_60px"
+            android:layout_height="@dimen/convert_60px"
+            android:src="@drawable/ic_cook_rotate"
+            android:scaleType="fitCenter"
+            android:layout_marginBottom="@dimen/convert_70px"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:tint="@color/cook_panel_text"/>
+
+        <TextView
+            android:id="@+id/tv_title_direction"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/direction"
+            android:textSize="@dimen/convert_27px"
+            android:textColor="@color/cook_panel_text"
+            android:layout_marginTop="@dimen/convert_8px"
+            app:layout_constraintTop_toBottomOf="@+id/view_icon_direction"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"/>
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+
+    <TextView
+        android:id="@+id/btn_start"
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/convert_120px"
+        android:background="@drawable/bg_orange_button"
+        android:text="@string/start"
+        android:textColor="#ffffff"
+        android:textSize="@dimen/convert_54px"
+        android:gravity="center"
+        android:layout_marginBottom="@dimen/convert_42px"
+        app:layout_constraintBottom_toTopOf="@+id/btn_reset"/>
+
+    <TextView
+        android:id="@+id/btn_reset"
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/convert_120px"
+        android:background="@drawable/bg_white_button"
+        android:text="@string/reset_button"
+        android:textColor="#FFA627"
+        android:textSize="@dimen/convert_54px"
+        android:gravity="center"
+        android:layout_marginBottom="@dimen/convert_71px"
+        app:layout_constraintBottom_toBottomOf="parent"/>
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 222 - 0
libBase/src/main/java/com/develop/base/util/MusicBackPlayerUtil.java

@@ -0,0 +1,222 @@
+package com.develop.base.util;
+
+import android.content.Context;
+import android.media.MediaPlayer;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * 播放背景音等较长或者较大的文件
+ */
+public class MusicBackPlayerUtil {
+
+    private MediaPlayer bgPlayer, btPlayer, soundPlayer;
+
+    public MusicBackPlayerUtil() {
+        bgPlayer = new MediaPlayer();
+        btPlayer = new MediaPlayer();
+    }
+
+    /**
+     * 判断背景音乐是否在播放
+     *
+     * @return
+     */
+    public boolean isBGPlaying() {
+        return bgPlayer != null && bgPlayer.isPlaying();
+    }
+
+    /**
+     * 播放背景音
+     */
+    public void playBgSound(Context context, int ResID) {
+        try {
+            if (ResID != 0) {
+                if (bgPlayer != null) {
+                    if (bgPlayer.isPlaying()) {
+                        bgPlayer.stop();
+                    }
+                    bgPlayer.release();
+                    bgPlayer = null;
+                }
+                bgPlayer = MediaPlayer.create(context, ResID);
+            }
+            //mPlayer.setDataSource(resPath);
+        } catch (IllegalArgumentException | IllegalStateException e) {
+            e.printStackTrace();
+        }
+        bgPlayer.setLooping(true);
+        try {
+            bgPlayer.prepare();
+        } catch (IllegalStateException | IOException e) {
+            e.printStackTrace();
+        }
+        bgPlayer.start();
+    }
+
+    /**
+     * 播放背景音
+     */
+    public void playBgSound(String soundPath) {
+        try {
+            if (!soundPath.isEmpty() && new File(soundPath).exists()) {
+                if (bgPlayer != null) {
+                    if (bgPlayer.isPlaying()) {
+                        bgPlayer.stop();
+                    }
+                    bgPlayer.release();
+                    bgPlayer = null;
+                }
+                bgPlayer = new MediaPlayer();
+                bgPlayer.setDataSource(soundPath);
+            }
+        } catch (IllegalArgumentException | IllegalStateException | IOException e) {
+            e.printStackTrace();
+        }
+        try {
+            bgPlayer.prepare();
+        } catch (IllegalStateException | IOException e) {
+            e.printStackTrace();
+        }
+        bgPlayer.start();
+    }
+
+
+    //背景声音大小
+    public void setBgVolume(float leftVolume, float RightVolume) {
+        if (bgPlayer != null) {
+            bgPlayer.setVolume(leftVolume, RightVolume);
+        }
+    }
+
+    /**
+     * 播放按钮音
+     */
+    public void playSound(String path) throws Exception {
+        if (btPlayer == null) {
+            btPlayer = new MediaPlayer();
+        }
+        btPlayer.reset();
+        btPlayer.setDataSource(path);
+        btPlayer.prepare();
+        btPlayer.setLooping(false);
+        btPlayer.start();
+    }
+
+
+    public void playSound(Context context, int ResID, boolean isLoop) {
+        try {
+            if (ResID != 0) {
+                if (soundPlayer != null) {
+                    if (soundPlayer.isPlaying()) {
+                        soundPlayer.stop();
+                    }
+                    soundPlayer.release();
+                    soundPlayer = null;
+                }
+                soundPlayer = MediaPlayer.create(context, ResID);
+            }
+            //mPlayer.setDataSource(resPath);
+        } catch (IllegalArgumentException | IllegalStateException e) {
+            e.printStackTrace();
+        }
+        soundPlayer.setLooping(isLoop);
+        try {
+            soundPlayer.prepareAsync();
+//			soundPlayer.prepare();
+        } catch (IllegalStateException e) {
+            e.printStackTrace();
+        }
+        soundPlayer.start();
+    }
+
+
+    public MediaPlayer getBgPlayer() {
+        return this.bgPlayer;
+    }
+
+    public MediaPlayer getBtPlayer() {
+        return this.btPlayer;
+    }
+
+    public MediaPlayer getPlayer() {
+        return this.soundPlayer;
+    }
+
+    /**
+     * 停止播放背景音乐
+     */
+    public void stopBgSound() {
+        if (bgPlayer == null)
+            return;
+        if (bgPlayer.isPlaying())
+            bgPlayer.stop();
+    }
+
+    /**
+     * 停止按钮声音播放
+     */
+    public void stopBtSound() {
+        if (btPlayer == null)
+            return;
+        try {
+            if (btPlayer.isPlaying()) {
+                btPlayer.stop();
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 停止声音播放
+     */
+    public void stopSound() {
+        if (soundPlayer == null)
+            return;
+        try {
+            if (soundPlayer.isPlaying()) {
+                soundPlayer.stop();
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 释放设备
+     */
+    public void releaseMedia() {
+        if (bgPlayer != null) {
+            try {
+                if (bgPlayer.isPlaying())
+                    bgPlayer.stop();
+                bgPlayer.release();
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+            bgPlayer = null;
+        }
+        if (btPlayer != null) {
+            try {
+                if (btPlayer.isPlaying())
+                    btPlayer.stop();
+                btPlayer.release();
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+            btPlayer = null;
+        }
+        if (soundPlayer != null) {
+            try {
+                if (soundPlayer.isPlaying())
+                    soundPlayer.stop();
+                soundPlayer.release();
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+            soundPlayer = null;
+        }
+    }
+}