下面是一个完整的Android Java实现,包含单选、多选、全选功能的列表UI:
1. 数据模型类
public class SelectableItem {
private String id;
private String title;
private boolean isSelected;
public SelectableItem(String id, String title) {
this.id = id;
this.title = title;
this.isSelected = false;
}
// Getters and Setters
public String getId() {
return id;
}
public String getTitle() {
return title;
}
public boolean isSelected() {
return isSelected;
}
public void setSelected(boolean selected) {
isSelected = selected;
}
}
2. 适配器实现
public class SelectionAdapter extends RecyclerView.Adapter<SelectionAdapter.ViewHolder> {
private List<SelectableItem> items;
private boolean isMultiSelectMode;
private OnItemClickListener itemClickListener;
public interface OnItemClickListener {
void onItemClick(int position);
}
public SelectionAdapter(List<SelectableItem> items, boolean isMultiSelectMode) {
this.items = items;
this.isMultiSelectMode = isMultiSelectMode;
}
public void setMultiSelectMode(boolean isMultiSelectMode) {
this.isMultiSelectMode = isMultiSelectMode;
notifyDataSetChanged();
}
public void setItemClickListener(OnItemClickListener listener) {
this.itemClickListener = listener;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_selectable, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
SelectableItem item = items.get(position);
holder.title.setText(item.getTitle());
holder.checkBox.setChecked(item.isSelected());
// 根据模式设置不同的选择器样式
if (isMultiSelectMode) {
holder.checkBox.setButtonDrawable(R.drawable.selector_checkbox);
} else {
holder.checkBox.setButtonDrawable(R.drawable.selector_radio);
}
holder.itemView.setOnClickListener(v -> {
if (itemClickListener != null) {
itemClickListener.onItemClick(position);
}
});
}
@Override
public int getItemCount() {
return items.size();
}
public List<SelectableItem> getSelectedItems() {
List<SelectableItem> selectedItems = new ArrayList<>();
for (SelectableItem item : items) {
if (item.isSelected()) {
selectedItems.add(item);
}
}
return selectedItems;
}
public void selectAll(boolean select) {
for (SelectableItem item : items) {
item.setSelected(select);
}
notifyDataSetChanged();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
CheckBox checkBox;
TextView title;
public ViewHolder(@NonNull View itemView) {
super(itemView);
checkBox = itemView.findViewById(R.id.checkbox);
title = itemView.findViewById(R.id.title);
}
}
}
3. 布局文件
// item_selectable.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="16dp"
android:background="?attr/selectableItemBackground">
<CheckBox
android:id="@+id/checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="false"
android:focusable="false"/>
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:textSize="16sp"/>
</LinearLayout>
// activity_selection.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="8dp">
<Button
android:id="@+id/btn_select_all"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="全选"/>
<Button
android:id="@+id/btn_switch_mode"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="切换模式"/>
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
// res/drawable/selector_checkbox.xml:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/ic_checkbox_checked" android:state_checked="true"/>
<item android:drawable="@drawable/ic_checkbox_unchecked" android:state_checked="false"/>
</selector>
// res/drawable/selector_radio.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/ic_radio_checked" android:state_checked="true"/>
<item android:drawable="@drawable/ic_radio_unchecked" android:state_checked="false"/>
</selector>
// res/menu/menu_selection.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_show_selected"
android:title="显示选中项"
app:showAsAction="never"/>
</menu>
4. Activity实现
public class SelectionActivity extends AppCompatActivity {
private SelectionAdapter adapter;
private Button selectAllButton;
private Button switchModeButton;
private boolean isMultiSelectMode = true;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_selection);
// 初始化视图
RecyclerView recyclerView = findViewById(R.id.recyclerView);
selectAllButton = findViewById(R.id.btn_select_all);
switchModeButton = findViewById(R.id.btn_switch_mode);
// 设置布局管理器
recyclerView.setLayoutManager(new LinearLayoutManager(this));
// 创建测试数据
List<SelectableItem> items = new ArrayList<>();
for (int i = 1; i <= 20; i++) {
items.add(new SelectableItem("item_" + i, "选项 " + i));
}
// 初始化适配器
adapter = new SelectionAdapter(items, isMultiSelectMode);
adapter.setItemClickListener(position -> {
SelectableItem item = items.get(position);
if (isMultiSelectMode) {
// 多选模式:切换当前项选中状态
item.setSelected(!item.isSelected());
} else {
// 单选模式:先取消所有选中,再设置当前项
for (SelectableItem i : items) {
i.setSelected(false);
}
item.setSelected(true);
}
adapter.notifyDataSetChanged();
// 更新全选按钮状态
updateSelectAllButton();
});
recyclerView.setAdapter(adapter);
// 全选按钮
selectAllButton.setOnClickListener(v -> {
boolean allSelected = areAllItemsSelected();
adapter.selectAll(!allSelected);
updateSelectAllButton();
});
// 切换模式按钮
switchModeButton.setOnClickListener(v -> {
isMultiSelectMode = !isMultiSelectMode;
adapter.setMultiSelectMode(isMultiSelectMode);
switchModeButton.setText(isMultiSelectMode ? "切换单选模式" : "切换多选模式");
selectAllButton.setVisibility(isMultiSelectMode ? View.VISIBLE : View.GONE);
// 如果是切换到单选模式且有多项被选中,只保留第一项
if (!isMultiSelectMode && getSelectedCount() > 1) {
clearAllSelections();
items.get(0).setSelected(true);
adapter.notifyDataSetChanged();
}
});
// 初始状态
updateSelectAllButton();
}
private boolean areAllItemsSelected() {
return adapter.getSelectedItems().size() == adapter.getItemCount();
}
private int getSelectedCount() {
return adapter.getSelectedItems().size();
}
private void clearAllSelections() {
adapter.selectAll(false);
}
private void updateSelectAllButton() {
if (areAllItemsSelected()) {
selectAllButton.setText("取消全选");
} else {
selectAllButton.setText("全选");
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_selection, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.action_show_selected) {
showSelectedItems();
return true;
}
return super.onOptionsItemSelected(item);
}
private void showSelectedItems() {
List<SelectableItem> selectedItems = adapter.getSelectedItems();
StringBuilder sb = new StringBuilder("已选项目:\n");
for (SelectableItem item : selectedItems) {
sb.append(item.getTitle()).append("\n");
}
new AlertDialog.Builder(this)
.setTitle("选择结果")
.setMessage(sb.toString())
.setPositiveButton("确定", null)
.show();
}
}