在執行期根據資料動態產生多個按鈕,每個按鈕需有獨立的點擊事件處理,並能識別是哪個按鈕被點擊。
// 在 Activity 或 Fragment 中
private void createDynamicButtons(List<String> buttonLabels) {
LinearLayout container = findViewById(R.id.button_container);
container.setOrientation(LinearLayout.VERTICAL);
for (int i = 0; i < buttonLabels.size(); i++) {
final int index = i; // Java 8+ 可直接用 i (effective final)
String label = buttonLabels.get(i);
Button btn = new Button(this);
btn.setText(label);
btn.setId(View.generateViewId()); // API 17+ 產生唯一 ID
btn.setLayoutParams(new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT
));
// 設定點擊監聽器
btn.setOnClickListener(v -> {
// 這裡可存取 index、label 等最終變數
Toast.makeText(this, "點擊了第 " + (index + 1) + " 個按鈕: " + label, Toast.LENGTH_SHORT).show();
handleButtonClick(index, label);
});
container.addView(btn);
}
}
private void handleButtonClick(int index, String label) {
// 具體業務邏輯
Log.d("DynamicBtn", "處理按鈕: " + label);
}
Button btn = new Button(this);
btn.setText("刪除項目 " + itemId);
// 將完整物件或 ID 存入 Tag
btn.setTag(item); // 可存任何 Object
btn.setOnClickListener(v -> {
Item clickedItem = (Item) v.getTag(); // 取回原始資料
deleteItem(clickedItem.getId());
});
| 問題 | 原因 | 解決 |
|---|---|---|
| 所有按鈕點擊都執行最後一個項目的邏輯 | 迴圈變數被捕獲為參考,非值 | 使用 final int index = i; 或 Java 8+ lambda 自動捕獲 final 變數 |
| 動態按鈕方向旋轉後消失 | Activity 重建,動態 View 未保存 | 在 onSaveInstanceState 保存資料,onCreate 重建 |
| 大量按鈕效能差 | 頻繁建立 View、Layout 重繪 | 改用 RecyclerView + Adapter |
// XML
// Adapter
public class ButtonAdapter extends RecyclerView.Adapter<ButtonAdapter.ViewHolder> {
private List<String> labels;
private OnItemClickListener listener;
public ButtonAdapter(List<String> labels, OnItemClickListener listener) {
this.labels = labels; this.listener = listener;
}
@NonNull @Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
Button btn = new Button(parent.getContext());
btn.setLayoutParams(new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT
));
return new ViewHolder(btn);
}
@Override public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
holder.button.setText(labels.get(position));
holder.button.setOnClickListener(v -> listener.onItemClick(position, labels.get(position)));
}
@Override public int getItemCount() { return labels.size(); }
static class ViewHolder extends RecyclerView.ViewHolder {
Button button;
ViewHolder(Button btn) { super(btn); button = btn; }
}
interface OnItemClickListener { void onItemClick(int position, String label); }
}
// 使用
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(new ButtonAdapter(labels, (pos, label) -> handleClick(pos, label)));
優勢:視圖回收、效能優異、支援動畫、易於維護。