feat: 新增商品出貨成功與機器巡檢中 UI 彈跳視窗

This commit is contained in:
TaiwanStar Developer 2026-06-11 10:24:04 +08:00
parent b56c539549
commit 3b1764b75c
6 changed files with 382 additions and 0 deletions

View File

@ -0,0 +1,148 @@
package com.unibuy.smartdevice.ui.dialog;
import android.content.Context;
import com.unibuy.smartdevice.DialogAbstract;
import com.unibuy.smartdevice.databinding.DialogPickupSuccessBinding;
import com.unibuy.smartdevice.tools.HandlerMain;
import com.unibuy.smartdevice.tools.HandlerMainCountdown;
import com.unibuy.smartdevice.tools.ToastHandlerMain;
import java.util.HashMap;
import java.util.Map;
public class PickupSuccessDialog extends DialogAbstract {
public enum Option {
TOAST(0),
COUNTDOWN_CANCEL(1),
SET_COUNTDOWN_TEXT(2),
RESET_COUNTDOWN(3),
;
private int option;
public int getOption() {
return option;
}
Option(int option) {
this.option = option;
}
}
public PickupSuccessDialog(Context context, HandlerMain srcHandlerMain) {
super(context, srcHandlerMain);
getLogs().info("PickupSuccessDialog:" + getClass().getSimpleName());
}
public static final Map<Integer, Option> optionMap = new HashMap<>();
static {
for (Option option : Option.values()) {
optionMap.put(option.getOption(), option);
}
}
@Override
protected Context setCtx() {
return this.getContext();
}
@Override
protected Class<? extends DialogAbstract> setCls() {
return getClass();
}
@Override
protected HandlerMain setHandlerMain() {
return new ToastHandlerMain(getContext(), getLogs()) {
@Override
protected void execute(Context context, int commandCode, String message) {
Option option = optionMap.get(commandCode);
if (option != null) {
switch (option) {
case TOAST:
super.execute(context, commandCode, message);
break;
case COUNTDOWN_CANCEL:
cancelOnThreadCountdown();
break;
case SET_COUNTDOWN_TEXT:
setButtonConfirmText(Integer.valueOf(message));
break;
case RESET_COUNTDOWN:
closeDialogCountdown.setCountdown(15);
break;
}
}
}
};
}
private DialogPickupSuccessBinding binding;
private CloseDialogOnThreadHandler closeDialogCountdown;
private String laneNumber = "99"; // 預設貨道號碼
public void setLaneNumber(String laneNumber) {
this.laneNumber = laneNumber;
if (binding != null) {
binding.tvLaneNumber.setText(laneNumber);
binding.tvSubtitle.setText("請至" + laneNumber + "號櫃門拿取您的商品");
}
}
@Override
protected void onCreate(Context context) {
binding = DialogPickupSuccessBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
// 初始化貨道數字與副標文字
setLaneNumber(laneNumber);
binding.btnConfirm.setOnClickListener(v -> dialogCancel());
closeDialogCountdown = new CloseDialogOnThreadHandler(getHandlerMain());
closeDialogCountdown.start(15);
}
public void dialogCancel() {
if (closeDialogCountdown != null) {
closeDialogCountdown.shutdown();
}
cancel();
}
public void cancelOnThreadCountdown() {
getTools().dialogClose();
cancel();
}
public void setButtonConfirmText(long countdown) {
binding.btnConfirm.setText("確認已取貨(" + countdown + "秒)");
}
public static class CloseDialogOnThreadHandler extends HandlerMainCountdown {
public CloseDialogOnThreadHandler(HandlerMain handlerMain) {
super(handlerMain);
}
@Override
protected HandlerMain setHandlerMain() {
return getSrcHandlerMain();
}
@Override
protected void close(HandlerMain handlerMain) {
handlerMain.start(getClass().getSimpleName(), Option.COUNTDOWN_CANCEL.getOption(), "close dialog");
}
@Override
protected void execute(long countdown, HandlerMain handlerMain) {
handlerMain.start(getClass().getSimpleName(), Option.SET_COUNTDOWN_TEXT.getOption(), String.valueOf(countdown));
}
@Override
protected Class<?> setCls() {
return getClass();
}
}
}

View File

@ -0,0 +1,44 @@
package com.unibuy.smartdevice.ui.dialog;
import android.content.Context;
import com.unibuy.smartdevice.DialogAbstract;
import com.unibuy.smartdevice.databinding.DialogSystemInspectionBinding;
import com.unibuy.smartdevice.tools.HandlerMain;
import com.unibuy.smartdevice.tools.ToastHandlerMain;
public class SystemInspectionDialog extends DialogAbstract {
public SystemInspectionDialog(Context context, HandlerMain srcHandlerMain) {
super(context, srcHandlerMain);
getLogs().info("SystemInspectionDialog:" + getClass().getSimpleName());
}
@Override
protected Context setCtx() {
return this.getContext();
}
@Override
protected Class<? extends DialogAbstract> setCls() {
return getClass();
}
@Override
protected HandlerMain setHandlerMain() {
return new ToastHandlerMain(getContext(), getLogs()) {
@Override
protected void execute(Context context, int commandCode, String message) {
super.execute(context, commandCode, message);
}
};
}
private DialogSystemInspectionBinding binding;
@Override
protected void onCreate(Context context) {
binding = DialogSystemInspectionBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
}
}

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<!-- 使用專案主色 -->
<solid android:color="@color/primary" />
</shape>

View File

@ -0,0 +1,97 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="24dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="800dp"
android:layout_gravity="center_horizontal"
android:background="@drawable/bg_dialog_rounded"
android:padding="36dp">
<!-- ==========================================
上半部: 標題與副標
========================================== -->
<LinearLayout
android:id="@+id/layoutHeader"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center_horizontal"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="24dp">
<TextView
android:id="@+id/tvTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/product_delivery_success"
android:textSize="44sp"
android:textStyle="bold"
android:textColor="@color/black"
android:layout_marginBottom="16dp" />
<TextView
android:id="@+id/tvSubtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/please_go_to_cabinet_to_pick_up_goods"
android:textSize="32sp"
android:textColor="@color/primary"
android:textStyle="bold" />
</LinearLayout>
<!-- ==========================================
中間部: 圓形貨道數字
========================================== -->
<TextView
android:id="@+id/tvLaneNumber"
android:layout_width="260dp"
android:layout_height="260dp"
android:background="@drawable/bg_circle_primary"
android:gravity="center"
android:text="99"
android:textColor="@color/white"
android:textSize="110sp"
android:textStyle="bold"
app:layout_constraintTop_toBottomOf="@id/layoutHeader"
app:layout_constraintBottom_toTopOf="@id/btnConfirm"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<!-- ==========================================
下半部: 按鈕與商標區域
========================================== -->
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/btnConfirm"
android:layout_width="match_parent"
android:layout_height="72dp"
android:background="@drawable/bg_button_primary"
android:text="@string/confirm_goods_taken_hardcoded"
android:textSize="26sp"
android:textColor="@color/onPrimary"
android:textAllCaps="false"
app:layout_constraintBottom_toTopOf="@id/tvBrand"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginBottom="16dp" />
<TextView
android:id="@+id/tvBrand"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Powered by Star Helper | 由 Star Helper 提供技術支援"
android:textSize="14sp"
android:textColor="@color/outline"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginBottom="8dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>

View File

@ -0,0 +1,83 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="24dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="800dp"
android:layout_gravity="center_horizontal"
android:background="@drawable/bg_dialog_rounded"
android:padding="36dp">
<!-- ==========================================
上半部: 標題
========================================== -->
<LinearLayout
android:id="@+id/layoutHeader"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center_horizontal"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="36dp">
<TextView
android:id="@+id/tvTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/system_inspection_in_progress"
android:textSize="44sp"
android:textStyle="bold"
android:textColor="@color/black"
android:gravity="center"
android:textAlignment="center" />
</LinearLayout>
<!-- ==========================================
中間部: 中間圖示
========================================== -->
<ImageView
android:id="@+id/imgIcon"
android:layout_width="300dp"
android:layout_height="300dp"
android:src="@drawable/system_settings"
android:scaleType="fitCenter"
app:layout_constraintTop_toBottomOf="@id/layoutHeader"
app:layout_constraintBottom_toTopOf="@id/btnConfirm"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<!-- ==========================================
下半部: 按鈕與商標區域(按鈕設為 invisible 保留空間結構)
========================================== -->
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/btnConfirm"
android:layout_width="match_parent"
android:layout_height="72dp"
android:background="@drawable/bg_button_primary"
android:visibility="invisible"
android:textAllCaps="false"
app:layout_constraintBottom_toTopOf="@id/tvBrand"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginBottom="16dp" />
<TextView
android:id="@+id/tvBrand"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Powered by Star Helper | 由 Star Helper 提供技術支援"
android:textSize="14sp"
android:textColor="@color/outline"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginBottom="8dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>

View File

@ -334,4 +334,8 @@
<string name="cart_max_items">購物車最多可購買 8 件商品</string>
<string name="cart_added">已加入購物車</string>
<string name="data_error">數據異常</string>
<string name="product_delivery_success">商品出貨成功</string>
<string name="please_go_to_cabinet_to_pick_up_goods">請至99號櫃門拿取您的商品</string>
<string name="confirm_goods_taken_hardcoded">確認已取貨15秒</string>
<string name="system_inspection_in_progress">機器巡檢中請稍後</string>
</resources>