From b1732987ceb805b5ea8f613b4140ab6d8e035fbf Mon Sep 17 00:00:00 2001 From: TaiwanStar Developer Date: Tue, 9 Jun 2026 15:59:17 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=84=AA=E5=8C=96=E5=95=86=E5=93=81?= =?UTF-8?q?=E6=90=9C=E5=B0=8B=E4=BB=8B=E9=9D=A2=E4=B8=A6=E4=BF=AE=E5=BE=A9?= =?UTF-8?q?=E5=BE=8C=E5=8F=B0=E8=B2=A8=E9=81=93=E7=B7=A8=E8=BC=AF=20Bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 商品搜尋介面大改版: 1. 搜尋列表從單欄改為 3 欄網格排列,並導入 MaterialCardView 重新設計商品卡片。 2. 搜尋框體驗優化:隱藏原生圖示,新增清空按鈕;支援點擊列表或候選字時自動收起鍵盤。 3. 點擊候選字邏輯修改為直接套用完整字詞。 4. 擴大點擊範圍,改為點擊整張商品卡片即可選取。 - 貨道編輯清單修復: 1. 將 textCount 隱藏狀態改為 INVISIBLE 解決 GONE 導致輸入框寬度壓縮為 0 的問題。 2. 輸入數量時改用 numberPassword 並移除密碼遮罩,以喚起乾淨的純數字鍵盤。 - 資源與樣式: 1. 新增 button_outline_black.xml 黑框按鈕樣式。 2. 修正圖片檔名大小寫 (eTicket -> eticket)。 --- .../com/unibuy/smartdevice/tools/Tools.java | 8 +- .../smartdevice/ui/ProductSearchActivity.java | 85 ++++++++--- .../devs/vmc/RecyclerVmcSlotListAdpter.java | 6 +- .../recycler/RecyclerProductSearchAdpter.java | 2 +- .../ui/recycler/RecyclerSearchTextAdpter.java | 6 +- .../res/drawable/button_outline_black.xml | 6 + ...png => payment_accepted_types_eticket.png} | Bin .../res/layout/activity_product_search.xml | 144 +++++++++++++----- .../res/layout/activity_vmc_slot_list.xml | 8 +- .../res/layout/recycler_product_search.xml | 111 +++++++------- .../main/res/layout/recycler_search_text.xml | 8 +- .../res/layout/recycler_vmc_slot_list.xml | 3 +- 12 files changed, 265 insertions(+), 122 deletions(-) create mode 100644 app/src/main/res/drawable/button_outline_black.xml rename app/src/main/res/drawable/{payment_accepted_types_eTicket.png => payment_accepted_types_eticket.png} (100%) diff --git a/app/src/main/java/com/unibuy/smartdevice/tools/Tools.java b/app/src/main/java/com/unibuy/smartdevice/tools/Tools.java index 6701340..cc1e3c4 100644 --- a/app/src/main/java/com/unibuy/smartdevice/tools/Tools.java +++ b/app/src/main/java/com/unibuy/smartdevice/tools/Tools.java @@ -346,8 +346,12 @@ public class Tools { public void setImmOpenByFocusChange(EditText editText) { editText.requestFocus(); editText.setSelection(editText.getText().length()); - InputMethodManager imm = (InputMethodManager) context.getSystemService(context.INPUT_METHOD_SERVICE); - imm.showSoftInput(editText, InputMethodManager.SHOW_IMPLICIT); + // 使用 post() 延遲執行,確保 hideSystemBars() 觸發的 Window 重繪完成後才彈出鍵盤 + // 若直接呼叫 showSoftInput,Window flag 變更會清除 focus,導致鍵盤無法彈出 + editText.post(() -> { + InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); + imm.showSoftInput(editText, InputMethodManager.SHOW_IMPLICIT); + }); } public void setImmHideByFocusChange(EditText editText) { diff --git a/app/src/main/java/com/unibuy/smartdevice/ui/ProductSearchActivity.java b/app/src/main/java/com/unibuy/smartdevice/ui/ProductSearchActivity.java index 66a187c..9e438b6 100644 --- a/app/src/main/java/com/unibuy/smartdevice/ui/ProductSearchActivity.java +++ b/app/src/main/java/com/unibuy/smartdevice/ui/ProductSearchActivity.java @@ -12,6 +12,7 @@ import android.widget.ImageView; import android.widget.SearchView; import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.GridLayoutManager; import com.unibuy.smartdevice.AppCompatActivityAbstract; import com.unibuy.smartdevice.MyApp; @@ -94,34 +95,44 @@ public class ProductSearchActivity extends AppCompatActivityAbstract { if (size > 0) recyclerSearchTextAdpter.notifyItemRangeRemoved(0, size); if (message.isEmpty()) { + binding.recyclerSearchText.setVisibility(View.GONE); + binding.textSearchStatus.setVisibility(View.VISIBLE); + binding.textSearchStatus.setText("請輸入您要搜尋的文字"); + for (ProductStructure product: MyApp.getInstance().getProductList()) { searchProductList.add(product); } - recyclerProductSearchAdpter.notifyItemInserted(searchProductList.size() -1); + if (searchProductList.size() > 0) { + recyclerProductSearchAdpter.notifyDataSetChanged(); + } } else { for (ProductStructure product: MyApp.getInstance().getProductList()) { if (product.getProductName().contains(message)) { searchProductList.add(product); String name = product.getProductName(); -// Log.i("product name", name); - int index = name.indexOf(message); - if (index != -1 && index < name.length() - 1) { - String result = name.substring(index + message.length()); - if (!result.isEmpty()) { - String oneText = String.valueOf(result.charAt(0)); - if (!searchTextList.contains(oneText)) { - searchTextList.add(oneText); - } - } + if (!searchTextList.contains(name)) { + searchTextList.add(name); } } } if (searchTextList.size() > 2) Collections.sort(searchTextList); - recyclerProductSearchAdpter.notifyItemInserted(searchProductList.size() -1); - recyclerSearchTextAdpter.notifyItemInserted(searchTextList.size() -1); + + if (searchTextList.isEmpty()) { + binding.recyclerSearchText.setVisibility(View.GONE); + binding.textSearchStatus.setVisibility(View.VISIBLE); + binding.textSearchStatus.setText("查無相關的候選字"); + } else { + binding.recyclerSearchText.setVisibility(View.VISIBLE); + binding.textSearchStatus.setVisibility(View.GONE); + recyclerSearchTextAdpter.notifyDataSetChanged(); + } + + if (searchProductList.size() > 0) { + recyclerProductSearchAdpter.notifyDataSetChanged(); + } } break; } @@ -140,7 +151,7 @@ public class ProductSearchActivity extends AppCompatActivityAbstract { recyclerProductSearchAdpter = new RecyclerProductSearchAdpter(getCtx(), position, searchProductList); binding.recyclerProductSearch.setAdapter(recyclerProductSearchAdpter); - binding.recyclerProductSearch.setLayoutManager(new LinearLayoutManager(getCtx())); + binding.recyclerProductSearch.setLayoutManager(new GridLayoutManager(getCtx(), 3)); recyclerSearchTextAdpter = new RecyclerSearchTextAdpter(binding, searchTextList); binding.recyclerSearchText.setAdapter(recyclerSearchTextAdpter); @@ -149,8 +160,30 @@ public class ProductSearchActivity extends AppCompatActivityAbstract { // SearchView searchView = binding.searchProductList; // enlargeSearchView(searchView, 32, 20, R.drawable.search); // icon 32dp,文字 20sp,自訂 drawable replaceSearchViewIcon(binding.searchProductList); - binding.searchProductList.setOnQueryTextListener(new SearchProductListOnQueryText(getHandlerMain())); + binding.searchProductList.setOnQueryTextListener(new SearchProductListOnQueryText(getHandlerMain()) { + @Override + public boolean onQueryTextSubmit(String query) { + binding.searchProductList.clearFocus(); + return super.onQueryTextSubmit(query); + } + }); + + // 點擊列表時自動關閉鍵盤 + binding.recyclerProductSearch.setOnTouchListener((v, event) -> { + binding.searchProductList.clearFocus(); + return false; + }); + binding.recyclerSearchText.setOnTouchListener((v, event) -> { + binding.searchProductList.clearFocus(); + return false; + }); + binding.buttonBack.setOnClickListener(v -> finish()); + + binding.buttonClear.setOnClickListener(v -> { + binding.searchProductList.setQuery("", false); + binding.searchProductList.clearFocus(); + }); if (MyApp.getInstance().getProductList().isEmpty()) { ProductsDao productsDao = new ProductsDao(getCtx()); @@ -172,9 +205,6 @@ public class ProductSearchActivity extends AppCompatActivityAbstract { private void replaceSearchViewIcon(SearchView searchView) { if (searchView == null) return; - // 設定 hint - searchView.setQueryHint("輸入搜尋關鍵字"); - // 找到內部的 EditText,修改字體大小 & 顏色 int searchEditTextId = searchView.getContext() .getResources() @@ -194,7 +224,24 @@ public class ProductSearchActivity extends AppCompatActivityAbstract { ImageView searchIcon = searchView.findViewById(searchIconId); if (searchIcon != null) { - searchIcon.setImageResource(R.drawable.searchopen); + searchIcon.setImageDrawable(null); + searchIcon.setVisibility(View.GONE); + } + + // 隱藏內部的清除 icon + int closeIconId = searchView.getContext() + .getResources() + .getIdentifier("android:id/search_close_btn", null, null); + ImageView closeIcon = searchView.findViewById(closeIconId); + if (closeIcon != null) { + closeIcon.setImageDrawable(null); + closeIcon.setEnabled(false); + ViewGroup.LayoutParams params = closeIcon.getLayoutParams(); + if (params != null) { + params.width = 0; + params.height = 0; + closeIcon.setLayoutParams(params); + } } } diff --git a/app/src/main/java/com/unibuy/smartdevice/ui/devs/vmc/RecyclerVmcSlotListAdpter.java b/app/src/main/java/com/unibuy/smartdevice/ui/devs/vmc/RecyclerVmcSlotListAdpter.java index 45f2bd5..9d54478 100644 --- a/app/src/main/java/com/unibuy/smartdevice/ui/devs/vmc/RecyclerVmcSlotListAdpter.java +++ b/app/src/main/java/com/unibuy/smartdevice/ui/devs/vmc/RecyclerVmcSlotListAdpter.java @@ -73,6 +73,8 @@ public class RecyclerVmcSlotListAdpter extends RecyclerView.Adapter + + + + + diff --git a/app/src/main/res/drawable/payment_accepted_types_eTicket.png b/app/src/main/res/drawable/payment_accepted_types_eticket.png similarity index 100% rename from app/src/main/res/drawable/payment_accepted_types_eTicket.png rename to app/src/main/res/drawable/payment_accepted_types_eticket.png diff --git a/app/src/main/res/layout/activity_product_search.xml b/app/src/main/res/layout/activity_product_search.xml index 15124d6..9c0e2e8 100644 --- a/app/src/main/res/layout/activity_product_search.xml +++ b/app/src/main/res/layout/activity_product_search.xml @@ -6,26 +6,83 @@ android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".ui.ProductSearchActivity" - android:background="@color/light_gray"> + android:background="@color/background"> - + android:layout_height="wrap_content" + android:background="@color/cardSurface" + android:elevation="8dp" + android:orientation="vertical" + android:paddingBottom="16dp" + app:layout_constraintTop_toTopOf="parent"> - + + + + + + +