Android Java 如何实现带增删拖拽排序功能的分步EditText输入组件
Android Java 分步操作指引输入模块实现方案
以下是满足需求的完整实现方案,基于RecyclerView+ItemTouchHelper实现拖拽排序、动态增删条目、自动编号功能:
前置依赖
首先在模块级build.gradle中引入RecyclerView依赖:
dependencies { implementation 'androidx.recyclerview:recyclerview:1.3.2' }
1. 定义步骤实体类
用于存储每个步骤的输入内容,避免排序时内容错乱:
public class StepItem { private String content; private long itemId; public StepItem(String content, long itemId) { this.content = content; this.itemId = itemId; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public long getItemId() { return itemId; } }
2. 步骤条目布局(res/layout/item_step_input.xml)
每个输入条目的布局包含编号、拖拽手柄、输入框、删除按钮:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:gravity="center_vertical" android:padding="8dp"> <TextView android:id="@+id/tv_step_num" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="16sp" android:textStyle="bold" android:layout_marginEnd="12dp"/> <ImageView android:id="@+id/iv_drag_handle" android:layout_width="24dp" android:layout_height="24dp" android:src="@android:drawable/ic_menu_sort_by_size" android:layout_marginEnd="8dp"/> <EditText android:id="@+id/et_step_content" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:hint="请输入步骤内容"/> <Button android:id="@+id/btn_delete" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="删除" android:layout_marginStart="8dp"/> </LinearLayout>
3. 列表适配器实现
处理条目绑定、内容同步、删除事件:
public class StepAdapter extends RecyclerView.Adapter<StepAdapter.StepViewHolder> { private List<StepItem> stepList; private OnDeleteClickListener deleteListener; public interface OnDeleteClickListener { void onDelete(int position); } public StepAdapter(List<StepItem> stepList, OnDeleteClickListener deleteListener) { this.stepList = stepList; this.deleteListener = deleteListener; setHasStableIds(true); } @NonNull @Override public StepViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_step_input, parent, false); return new StepViewHolder(view); } @Override public void onBindViewHolder(@NonNull StepViewHolder holder, int position) { holder.tvStepNum.setText(String.valueOf(position + 1)); StepItem item = stepList.get(position); holder.etStepContent.setText(item.getContent()); // 同步输入内容到实体类 holder.etStepContent.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {} @Override public void onTextChanged(CharSequence s, int start, int before, int count) { int pos = holder.getAdapterPosition(); if(pos != RecyclerView.NO_POSITION) { stepList.get(pos).setContent(s.toString()); } } @Override public void afterTextChanged(Editable s) {} }); // 绑定删除事件 holder.btnDelete.setOnClickListener(v -> { int pos = holder.getAdapterPosition(); if (pos != RecyclerView.NO_POSITION) { deleteListener.onDelete(pos); } }); } @Override public int getItemCount() { return stepList.size(); } @Override public long getItemId(int position) { return stepList.get(position).getItemId(); } public static class StepViewHolder extends RecyclerView.ViewHolder { TextView tvStepNum; ImageView ivDragHandle; EditText etStepContent; Button btnDelete; public StepViewHolder(@NonNull View itemView) { super(itemView); tvStepNum = itemView.findViewById(R.id.tv_step_num); ivDragHandle = itemView.findViewById(R.id.iv_drag_handle); etStepContent = itemView.findViewById(R.id.et_step_content); btnDelete = itemView.findViewById(R.id.btn_delete); } } }
4. 拖拽排序回调实现
处理拖拽逻辑,调整条目顺序后自动更新编号:
public class StepItemTouchCallback extends ItemTouchHelper.Callback { private final StepAdapter adapter; private final List<StepItem> stepList; public StepItemTouchCallback(StepAdapter adapter, List<StepItem> stepList) { this.adapter = adapter; this.stepList = stepList; } @Override public int getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) { int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN; return makeMovementFlags(dragFlags, 0); } @Override public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) { int fromPosition = viewHolder.getAdapterPosition(); int toPosition = target.getAdapterPosition(); Collections.swap(stepList, fromPosition, toPosition); adapter.notifyItemMoved(fromPosition, toPosition); // 刷新受影响条目的编号 for (int i = Math.min(fromPosition, toPosition); i <= Math.max(fromPosition, toPosition); i++) { adapter.notifyItemChanged(i); } return true; } @Override public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {} @Override public boolean isLongPressDragEnabled() { return false; } }
5. 主页面实现
主页面布局(res/layout/activity_step_input.xml)
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="16dp"> <Button android:id="@+id/btn_add_step" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="新增步骤" android:layout_marginBottom="16dp"/> <androidx.recyclerview.widget.RecyclerView android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="match_parent"/> </LinearLayout>
主页面逻辑代码
public class StepInputActivity extends AppCompatActivity { private List<StepItem> stepList = new ArrayList<>(); private StepAdapter adapter; private ItemTouchHelper itemTouchHelper; private long nextItemId = 1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_step_input); RecyclerView recyclerView = findViewById(R.id.recycler_view); recyclerView.setLayoutManager(new LinearLayoutManager(this)); Button btnAddStep = findViewById(R.id.btn_add_step); // 初始化适配器 adapter = new StepAdapter(stepList, position -> { stepList.remove(position); adapter.notifyItemRemoved(position); adapter.notifyItemRangeChanged(position, stepList.size()); }); recyclerView.setAdapter(adapter); // 绑定拖拽逻辑 StepItemTouchCallback callback = new StepItemTouchCallback(adapter, stepList); itemTouchHelper = new ItemTouchHelper(callback); itemTouchHelper.attachToRecyclerView(recyclerView); // 拖拽手柄触发拖拽 adapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() { @Override public void onItemRangeInserted(int positionStart, int itemCount) { for (int i = 0; i < recyclerView.getChildCount(); i++) { StepAdapter.StepViewHolder holder = (StepAdapter.StepViewHolder) recyclerView.getChildViewHolder(recyclerView.getChildAt(i)); holder.ivDragHandle.setOnTouchListener((v, event) -> { if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { itemTouchHelper.startDrag(holder); } return false; }); } } }); // 新增步骤逻辑 btnAddStep.setOnClickListener(v -> { stepList.add(new StepItem("", nextItemId++)); adapter.notifyItemInserted(stepList.size() - 1); }); // 默认初始化1个空步骤 btnAddStep.performClick(); } }
功能说明
以上实现可直接满足所有需求:
- 每个步骤自动生成序号,增删、排序操作后自动更新编号
- 点击新增按钮可新增空白输入条目
- 每个条目右侧删除按钮可删除对应条目
- 按住左侧拖拽手柄上下拖动即可调整条目顺序
- 输入内容自动同步到实体类,列表滚动、排序时不会丢失输入内容
内容的提问来源于stack exchange,提问作者Aiden K
相关产品推荐
相关产品推荐

