为啥列表元素不交换?

Posted

技术标签:

【中文标题】为啥列表元素不交换?【英文标题】:Why do the list elements not swap?为什么列表元素不交换? 【发布时间】:2017-07-16 12:48:11 【问题描述】:

我有一个RecyclerView 并实现了一个名为onItemMoveonMove 命令。我正在使用onItemMove 尝试让列表元素在拖动时交换位置,但列表元素只是悬停在每个元素上,它们不会交换。我该如何纠正这个问题?

注 1:onItemDismiss 工作正常;它会将项目滑开并将其从列表中删除。

注意 2:我尝试过 Override onItemMove,但它实际上并没有覆盖它的超类。

列表适配器类:这包含 onItemMove 命令

public class ListAdapter extends RecyclerView.Adapter<ListAdapter.ListViewHolder> 
    private static final String TAG = "ListAdapter";
    Context context;
    private List<UserData> dataList = new ArrayList<>();
    LayoutInflater inflater;
    Listener listener;
    DbHelper dbHelper;



    public interface Listener 
        void nameToChnge(String name);
    

    public ListAdapter(Context context, List<UserData> dataList1) 
        this.context = context;
        this.dataList = dataList1;
        this.listener= (Listener) context;
        inflater = LayoutInflater.from(context);
    


    @Override
    public ListViewHolder onCreateViewHolder(ViewGroup parent, int viewType) 
        View convertView = inflater.inflate(R.layout.recylerview_one, parent, false);
        ListViewHolder viewHolder = new ListViewHolder(convertView);
        return viewHolder;
    

    @Override
    public void onBindViewHolder(ListViewHolder holder, final int position) 
        holder.tv_name.setText(dataList.get(position).name);
        holder.tv_quantity.setText(dataList.get(position).quantity);
        holder.tv_description.setText(dataList.get(position).description + "");

        holder.relLayout.setOnClickListener(new View.OnClickListener()
            @Override
            public void onClick(View v) 
                String s = dataList.get(position).id;
                Integer stringo = Integer.parseInt(s);
                Intent intent = new Intent(context, ItemEditActivity.class);
                intent.putExtra("ItemNumber", stringo);
                context.startActivity(intent);
            
        );
    

    @Override
    public int getItemCount() 
        return dataList.size();
    

    class ListViewHolder extends RecyclerView.ViewHolder 
        TextView tv_name, tv_quantity, tv_description;
        RelativeLayout relLayout;


        public ListViewHolder(View itemView) 
            super(itemView);
            tv_name = (TextView) itemView.findViewById(R.id.nameDisplay);
            tv_quantity = (TextView) itemView.findViewById(R.id.quantityDisplay);
            tv_description = (TextView) itemView.findViewById(R.id.descriptionDisplay);
            relLayout = (RelativeLayout) itemView.findViewById(R.id.relLayout);
        
    



    public void onItemDismiss(final int position) 
        dataList.remove(position);
        notifyItemRemoved(position);

    

    public void onItemMove(int fromPosition, int toPosition) 
        Collections.swap(dataList, fromPosition, toPosition);
        notifyItemMoved(fromPosition, toPosition);

    

ItemTouchHelper 类:

  public class SimpleItemTouchHelperCallback extends ItemTouchHelper.Callback
        private final ListAdapter  mAdapter;


        public SimpleItemTouchHelperCallback(ListAdapter adapter) 
            mAdapter = adapter;
        

        @Ov

erride
    public boolean isLongPressDragEnabled() 
        return true;
    

    @Override
    public boolean isItemViewSwipeEnabled() 
        return true;
    

    @Override
    public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) 
        int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
        int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;
        return makeMovementFlags(dragFlags, swipeFlags);
    

    @Override
    public boolean onMove(RecyclerView recyclerView,
                          RecyclerView.ViewHolder viewHolder,
                          RecyclerView.ViewHolder target) 
        mAdapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());

        return true;
    

    @Override
    public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) 
        mAdapter.onItemDismiss(viewHolder.getAdapterPosition());
    

我初始化 RecyclerView 和 SimpleItemTouchHelperCallback:

public class MainActivity extends AppCompatActivity implements ListAdapter.Listener 
    private static final String TAG = "MainActivity";

    RecyclerView recyclerView;
    DbHelper dbHelper;
    ListAdapter adapter;
    FloatingActionButton fab;


    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        introItem();
        dbHelper = DbHelper.getInstance(getApplicationContext());

        recyclerView= (RecyclerView) findViewById(R.id.rv_contactlist);
        adapter = new ListAdapter(this, dbHelper.getAllUser());
        recyclerView.setAdapter(adapter);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));

        ItemTouchHelper.Callback callback =
                new SimpleItemTouchHelperCallback(adapter);
        ItemTouchHelper touchHelper = new ItemTouchHelper(callback);
        touchHelper.attachToRecyclerView(recyclerView);

        totalQuantity();

        adapter.notifyDataSetChanged();
        fabHideShow();
        versionCheckMethod();

    

【问题讨论】:

发布您创建和初始化 RecyclerView 和 SimpleItemTouchHelperCallback 的代码 @AnuragSingh 我想我已经提供了所需的信息,如果我没有提供请纠正我 你说的很对。谢谢,我会尽快回复。 问候“注 2”:RecyclerView.Adapter 没有 onItemMove() 方法 - 那么您为什么要尝试覆盖不存在的方法呢? 【参考方案1】:

你只需要研究这个示例的代码并实现它:https://github.com/iPaulPro/android-ItemTouchHelper-Demo/tree/master/app/src/main/java/co/paulburke/android/itemtouchhelperdemo

但基本上你需要的是创建两个接口。第一个:

public interface ItemTouchHelperAdapter 
/**
 * Called when an item has been dragged far enough to trigger a move. This is called every time
 * an item is shifted, and not at the end of a "drop" event.
 *
 * @param fromPosition The start position of the moved item.
 * @param toPosition   Then end position of the moved item.

 */
void onItemMove(int fromPosition, int toPosition);


/**
 * Called when an item has been dismissed by a swipe.
 *
 * @param position The position of the item dismissed.

 */
void onItemDismiss(int position);

第二个:

public interface ItemTouchHelperViewHolder 
    /**
      * Implementations should update the item view to indicate it's active state.
     */
    void onItemSelected();


    /**
     * state should be cleared.
     */
    void onItemClear();

在 SimpleItemTouchHelperCallback 中是这样的:

public class SimpleItemTouchHelperCallback extends ItemTouchHelper.Callback 

    private final ItemTouchHelperAdapter mAdapter;

    public SimpleItemTouchHelperCallback(ItemTouchHelperAdapter adapter) 
        mAdapter = adapter;
    

    @Override
    public boolean isLongPressDragEnabled() 
        return true;
    

    @Override
    public boolean isItemViewSwipeEnabled() 
        return false;
    

    @Override
    public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) 
        final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
        final int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;
        return makeMovementFlags(dragFlags, swipeFlags);
    

    @Override
    public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder source, RecyclerView.ViewHolder target) 
        mAdapter.onItemMove(source.getAdapterPosition(), target.getAdapterPosition());
        return true;
    

    @Override
    public void onSwiped(RecyclerView.ViewHolder viewHolder, int i) 
        mAdapter.onItemDismiss(viewHolder.getAdapterPosition());
    

    @Override
    public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) 
        if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) 
            ItemTouchHelperViewHolder itemViewHolder = (ItemTouchHelperViewHolder) viewHolder;
            itemViewHolder.onItemSelected();
        

        super.onSelectedChanged(viewHolder, actionState);
    

    @Override
    public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) 
        super.clearView(recyclerView, viewHolder);

        ItemTouchHelperViewHolder itemViewHolder = (ItemTouchHelperViewHolder) viewHolder;
        itemViewHolder.onItemClear();
    

然后您必须更改 RecyclerViewAdapter,并在那里实现 onItemMove 方法,正如我们在 oder cmets 中所说的那样。你也应该像这样实现onStartDragListener

    public interface OnStartDragListener 
    /**
     * Called when a view is requesting a start of a drag.
     *
     * @param viewHolder The holder of the view to drag.
     */
    void onStartDrag(RecyclerView.ViewHolder viewHolder);

然后在你的适配器onBindViewHolder中使用(记得在类声明中实现所有接口)像这样(你需要根据你的变量名更改这段代码):

holder.handleView.setOnTouchListener(new View.OnTouchListener() 
            @Override
            public boolean onTouch(View v, MotionEvent event) 
                if (MotionEventCompat.getActionMasked(event) == MotionEvent.ACTION_DOWN) 
                    mDragStartListener.onStartDrag(holder);
                
                return false;
            
        );

其中 mDragListener 是一个 OnStartDragListener 变量。

最后查看本指南了解更多信息:http://valokafor.com/remember-drag-and-drop-position-with-recyclerview/

【讨论】:

我已经尝试过了,但是我得到一个错误并且无法实现它,因为Override 没有覆盖它的超类 您的方法是“public void”,但父方法 id 是“public boolean”。尝试更改它,或者直接使用 ctrl+o 看看是否可以从列表中添加它。 我尝试了一个布尔值,只是复制粘贴了你的代码,但仍然是同样的错误。抱歉,我以前从未使用过 ctrl+o - 我在找什么?截图:puu.sh/unuvj/b3984a734b.png 我还建议查看此代码示例:github.com/iPaulPro/Android-ItemTouchHelper-Demo 基本上 ctrl+o 让你选择可以@Override 的方法。

以上是关于为啥列表元素不交换?的主要内容,如果未能解决你的问题,请参考以下文章

使用模式匹配交换列表中的元素对

交换 BindingList<SomeClass> 元素需要很多时间,为啥会这样,我该怎么办?

交换列表中元素的更好方法?

为啥思科2950交换机配置链路聚合不成功

在Python中交换两个元素[重复]

路由器和交换机连接起来的IP地址为啥不一样