You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 19:15:04