拖放从 SQLiteDatabase 填充的 RecyclerView

Posted

技术标签:

【中文标题】拖放从 SQLiteDatabase 填充的 RecyclerView【英文标题】:Drag and Drop RecyclerView Which is Populated from SQLiteDatabase 【发布时间】:2017-06-11 00:01:45 【问题描述】:

信息:

我有一个RecyclerView,我用ListAdapter 类中的ArrayList dataList 填充它。我从SQLiteDatabase 表中获取 dataList 的数据:DbHelper 类中的 TABLE_USERdETAIL。我正在尝试通过使用SimpleItemTouchHelperCallback 类将拖放重新组织到RecyclerView;然而,虽然我现在可以移动 RecyclerView 元素,但列表不会重新排序或移动;我只能暂时将列表元素相互拖动,如下图所示,但这意味着将列表元素永久地插入到它所持有的任何位置:

我希望问题出现在 ListAdapter 类中,在方法 onItemMove 中,但我不知道如何解决我的问题。

问题:如何让这个拖放功能真正重新组织RecyclerView 数据列表?

更新 5:我已更新当前代码以获得更多帮助。

ListAdapter 类

public class ListAdapter extends RecyclerView.Adapter<ListAdapter.ListViewHolder> 

    Context context;
    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 + " ");

        if(dataList.get(position).description.isEmpty()) 
            holder.tv_description.setVisibility(View.GONE);
        

        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 implements ItemTouchHelperViewHolder 
        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);
        
        @Override
        public void onItemSelected() 
            Log.d("ListViewHolder", "item selected");
        

        @Override
        public void onItemClear() 
            Log.d("ListViewHolder", "item clear");
            for (int count = 0; count < dataList.size(); count++) 
                UserData u = dataList.get(count);
                u.setSort(count);
                dbHelper.updateUserData(u);
            
            notifyDataSetChanged();
        
    

    public void onItemDismiss(int position) 
        dataList.remove(position);
        //dbHelper = DbHelper.getInstance(context);
        //dbHelper.deleteRowItem(position + 1);
        notifyItemRemoved(position);
    

    //Collections.swap(dataList, fromPosition, toPosition);
    //notifyItemMoved(fromPosition, toPosition);


    public boolean onItemMove(int fromPosition, int toPosition) 
        if (fromPosition < toPosition) 
            for (int i = fromPosition; i < toPosition; i++) 
                Collections.swap(dataList, i, i + 1);
            
         else 
            for (int i = fromPosition; i > toPosition; i--) 
                Collections.swap(dataList, i, i - 1);
            
        
        notifyItemMoved(fromPosition, toPosition);
        return true;
    

SimpleItemTouchHelperCallback 类

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


    public SimpleItemTouchHelperCallback(ListAdapter adapter) 
        mAdapter = adapter;
    

    @Override
    public boolean isLongPressDragEnabled() return true; 

    @Override
    public boolean isItemViewSwipeEnabled()  return false; 

    @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());
    

    @Override
    public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) 
        // We only want the active item to change
        if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) 
            if (viewHolder instanceof ItemTouchHelperViewHolder) 
                // Let the view holder know that this item is being moved or dragged
                Log.i("ADAPTER", "----DRAGGING----");
                ItemTouchHelperViewHolder itemViewHolder = (ItemTouchHelperViewHolder) viewHolder;
                itemViewHolder.onItemSelected();
            
        

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

        if (viewHolder instanceof ItemTouchHelperViewHolder) 
            // Tell the view holder it's time to restore the idle state
            ItemTouchHelperViewHolder itemViewHolder = (ItemTouchHelperViewHolder) viewHolder;
            itemViewHolder.onItemClear();
        
    

DbHelper 类

公共类 DbHelper 扩展 SQLiteOpenHelper

   private static final String DATABASE_NAME = "UserDatabase";
    private static final int DATABASE_VERSION = 2;
    private static DbHelper mDbHelper;

    public static String TABLE_USERdETAIL = "userdetail";

    private static final String _ID = "_id";
    private static final String SORT_ID = "sort_id";
    private static final String NAME = "name";
    private static final String QUANTITY = "quantity";
    private static final String WEIGHT = "weight";
    private static final String WEIGHTTOTAL = "weighttotal";
    private static final String VALUE = "value";
    private static final String VALUETOTAL = "valuetotal";
    private static final String DESCRIPTION = "description";

    public static synchronized DbHelper getInstance(Context context) 
        if (mDbHelper == null) 
            mDbHelper = new DbHelper(context.getApplicationContext());
        
        return mDbHelper;
    

    public DbHelper(Context context) 
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    


    @Override
    public void onCreate(SQLiteDatabase db) 

        String CREATE_USERDETAIL_TABLE = "CREATE TABLE " + TABLE_USERdETAIL +
                "(" +
                _ID + " INTEGER PRIMARY KEY , " +
                SORT_ID + " INTEGER," +
                NAME + " TEXT," +
                QUANTITY + " INTEGER," +
                WEIGHT + " INTEGER," +
                WEIGHTTOTAL + " INTEGER," +
                VALUE + " INTEGER," +
                VALUETOTAL + " INTEGER," +
                DESCRIPTION + " TEXT" +
                ")";

        db.execSQL(CREATE_USERDETAIL_TABLE);
    



    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) 
        if (oldVersion != newVersion) 
            db.execSQL("ALTER TABLE " + TABLE_USERdETAIL + " ADD COLUMN " + WEIGHT + " INTEGER DEFAULT 0");
            db.execSQL("ALTER TABLE " + TABLE_USERdETAIL + " ADD COLUMN " + WEIGHTTOTAL + " INTEGER DEFAULT 0");
            db.execSQL("ALTER TABLE " + TABLE_USERdETAIL + " ADD COLUMN " + VALUE + " INTEGER DEFAULT 0");
            db.execSQL("ALTER TABLE " + TABLE_USERdETAIL + " ADD COLUMN " + VALUETOTAL + " INTEGER DEFAULT 0");
        
    

    /**
   Insert a  user detail into database
   */
    public void insertUserDetail(UserData userData) 

        SQLiteDatabase db = getWritableDatabase();

        db.beginTransaction();

        try 
            ContentValues values = new ContentValues();
            values.put(SORT_ID, userData.sort_id);
            values.put(NAME, userData.name);
            values.put(QUANTITY, userData.quantity);
            values.put(WEIGHT, userData.weight);
            values.put(WEIGHTTOTAL, userData.weighttotal);
            values.put(VALUE, userData.value);
            values.put(VALUETOTAL, userData.valuetotal);
            values.put(DESCRIPTION, userData.description);


            db.insertOrThrow(TABLE_USERdETAIL, null, values);
            db.setTransactionSuccessful();
         catch (SQLException e) 
            e.printStackTrace();
         finally 
            db.endTransaction();
        


    

    public void updateUserDetail(int id, String v1, String v2, String v3, String v4, String v5, String v6, String v7)
        SQLiteDatabase db = this.getWritableDatabase();

        ContentValues values = new ContentValues();
        values.put(NAME, v1);
        values.put(QUANTITY, v2);
        values.put(DESCRIPTION, v3);
        values.put(WEIGHT, v4);
        values.put(WEIGHTTOTAL, v5);
        values.put(VALUE, v6);
        values.put(VALUETOTAL, v7);
        db.update(TABLE_USERdETAIL, values, "_id="+id, null);
    

   /**
   fetch all data from UserTable
    */
    public List<UserData> getAllUser() 
        List<UserData> usersdetail = new ArrayList<>();

        String USER_DETAIL_SELECT_QUERY = "SELECT * FROM " + TABLE_USERdETAIL + " ORDER BY " + SORT_ID + " COLLATE NOCASE;";

        SQLiteDatabase db = getReadableDatabase();
        Cursor cursor = db.rawQuery(USER_DETAIL_SELECT_QUERY, null);

        try 
            if (cursor.moveToFirst()) 
                do 
                    UserData userData = new UserData();
                    userData.id = cursor.getString(cursor.getColumnIndex(_ID));
                    userData.sort_id = cursor.getInt(cursor.getColumnIndex(SORT_ID));
                    userData.name = cursor.getString(cursor.getColumnIndex(NAME));
                    userData.quantity = "Quantity: " + cursor.getString(cursor.getColumnIndex(QUANTITY));
                    userData.weight = cursor.getString(cursor.getColumnIndex(WEIGHT));
                    userData.weighttotal = cursor.getString(cursor.getColumnIndex(WEIGHTTOTAL));
                    userData.value = cursor.getString(cursor.getColumnIndex(VALUE));
                    userData.valuetotal = cursor.getString(cursor.getColumnIndex(VALUETOTAL));
                    userData.description = cursor.getString(cursor.getColumnIndex(DESCRIPTION));

                    usersdetail.add(userData);
                 while (cursor.moveToNext());
            
         catch (Exception e) 
            e.printStackTrace();
         finally 
            if (cursor != null && !cursor.isClosed()) 
                cursor.close();
            
        
        return usersdetail;

    

    /**
   Delete single row from UserTable
     */
    void deleteRow(String name) 
        SQLiteDatabase db = getWritableDatabase();
        try 
            db.beginTransaction();
            db.execSQL("delete from " + TABLE_USERdETAIL + " where name ='" + name + "'");
            db.setTransactionSuccessful();
         catch (SQLException e) 
            e.printStackTrace();
         finally 
            db.endTransaction();
        
    

    void deleteRowItem(int id) 
        SQLiteDatabase db = getWritableDatabase();
        try 
            db.beginTransaction();
            db.execSQL("delete from " + TABLE_USERdETAIL + " where _id ='" + id + "'");
            db.setTransactionSuccessful();
         catch (SQLException e) 
            e.printStackTrace();
         finally 
            db.endTransaction();
        
    

    public UserData getSingleUserDetail(String userId) 
        SQLiteDatabase db = this.getWritableDatabase();
        UserData userData = null;

        //Cursor cursor = db.rawQuery("SELECT * FROM " + TABLE_USERdETAIL, null);

        // this is the code to order the RecyclerView by _ID:
        Cursor cursor = db.rawQuery("SELECT * FROM " + TABLE_USERdETAIL + " WHERE " + _ID + "= ?", new String[]userId);
        try 
            while (cursor.moveToNext()) 
                userData = new UserData();
                userData.name = cursor.getString(cursor.getColumnIndex(NAME));
                userData.quantity = cursor.getString(cursor.getColumnIndex(QUANTITY));
                userData.weight = cursor.getString(cursor.getColumnIndex(WEIGHT));
                userData.weighttotal = cursor.getString(cursor.getColumnIndex(WEIGHTTOTAL));
                userData.value = cursor.getString(cursor.getColumnIndex(VALUE));
                userData.valuetotal = cursor.getString(cursor.getColumnIndex(VALUETOTAL));
                userData.description = cursor.getString(cursor.getColumnIndex(DESCRIPTION));
            
            cursor.close();
         catch (Exception e) 
            e.printStackTrace();
         finally 
            if (cursor != null && !cursor.isClosed()) 
                cursor.close();
            
        
        return userData;
    

    public int getTotalWeight() 
        SQLiteDatabase db = this.getWritableDatabase();
        Cursor cur = db.rawQuery("SELECT SUM(WEIGHTTOTAL) FROM userdetail", null);
        if(cur.moveToFirst())
        
            return cur.getInt(0);
        
        cur.close();
        return getTotalWeight();
    

    public int getTotalQuantity() 
        SQLiteDatabase db = this.getWritableDatabase();
        Cursor cur = db.rawQuery("SELECT SUM(QUANTITY) FROM userdetail", null);
        if(cur.moveToFirst())
        
            return cur.getInt(0);
        
        cur.close();
        return getTotalQuantity();
    

    public int getTotalValue() 
        SQLiteDatabase db = this.getWritableDatabase();
        Cursor cur = db.rawQuery("SELECT SUM(VALUETOTAL) FROM userdetail", null);
        if(cur.moveToFirst())
        
            return cur.getInt(0);
        
        cur.close();
        return getTotalValue();
    

    public int getMaxColumnData() 
        SQLiteDatabase db = this.getWritableDatabase();
        final SQLiteStatement stmt = db
                .compileStatement("SELECT MAX(SORT_ID) FROM " + TABLE_USERdETAIL);

        return (int) stmt.simpleQueryForLong();
    

    public void updateUserData(UserData userData) 

        SQLiteDatabase db = this.getWritableDatabase();

        ContentValues values = new ContentValues();

        values.put(NAME, userData.getName());
        values.put(QUANTITY, userData.getQuantity());
        values.put(DESCRIPTION, userData.getDescription());
        values.put(WEIGHT, userData.getWeight());
        values.put(WEIGHTTOTAL, userData.getWeighttotal());
        values.put(VALUE, userData.getValue());
        values.put(VALUETOTAL, userData.getValuetotal());
        values.put(SORT_ID, userData.getSort());

        Log.i("DBhelper", "USER UPDATED = " + userData.getName());

        db.update(TABLE_USERdETAIL, values, _ID + "=?", new String[]String.valueOf(userData.getId()));

    

用户数据

import java.io.Serializable;

public class UserData implements Serializable 
    String id, name, quantity, weight, weighttotal, value, valuetotal, description;
    int sort_id;

    public UserData() 
        super();
    

    public void setId(String id)
        this.id= id;
    
    public String getId()
        return id;
    
    public void setSort(int sort)
        this.sort_id= sort;
    
    public int getSort()
        return sort_id;
    

    public void setName(String name)
        this.name= name;
    
    public String getName()
        return name;
    
    public void setDescription(String description)
        this.description= description;
    
    public String getDescription()
        return description;
    
    public void setQuantity(String quantity)
        this.quantity= quantity;
    
    public String getQuantity()
        return quantity;
    
    public void setWeight(String weight)
        this.weight= weight;
    
    public String getWeight()
        return weight;
    
    public void setWeighttotal(String weighttotal)
        this.weighttotal= weighttotal;
    
    public String getWeighttotal()
        return weighttotal;
    
    public void setValue(String value)
        this.value= value;
    
    public String getValue()
        return value;
    
    public void setValuetotal(String valuetotal)
        this.quantity= valuetotal;
    
    public String getValuetotal()
        return quantity;
    

ItemTouchHelperViewHolder 类

public interface ItemTouchHelperViewHolder 
    void onItemSelected();
    void onItemClear();

主要活动

public class MainActivity extends AppCompatActivity implements ListAdapter.Listener 


    RecyclerView recyclerView;
    DbHelper dbHelper;
    ListAdapter adapter;
    private ItemTouchHelper mItemTouchHelper;

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


        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);
        mItemTouchHelper = new ItemTouchHelper(callback);
        mItemTouchHelper.attachToRecyclerView(recyclerView);

    


    @Override
    public boolean onCreateOptionsMenu(Menu menu) 
        getMenuInflater().inflate(R.menu.main_menu, menu);
        return super.onCreateOptionsMenu(menu);


    

    @Override
    public boolean onOptionsItemSelected(MenuItem item) 
        switch (item.getItemId()) 
            case R.id.about_task:
                Intent intentChangeActivity2 = new Intent(MainActivity.this, AboutActivity.class);
                startActivity(intentChangeActivity2);
                return true;
            case R.id.encumbrance_task:
                Intent intentChangeActivity = new Intent(MainActivity.this, EncumbranceActivity.class);
                startActivity(intentChangeActivity);
                return true;
            default:
                return super.onOptionsItemSelected(item);
        
    

    @Override
    public void onResume() 
        super.onResume();
        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));

    

    @Override
    public void nameToChnge(String name) 
        dbHelper.deleteRow(name);

        adapter = new ListAdapter(this, dbHelper.getAllUser());
        recyclerView.setAdapter(adapter);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
    

错误日志:

8-26 11:20:49.443 23533-23533/name.appE/androidRuntime: FATAL EXCEPTION: main
                                                                       Process: name.app, PID: 23533
                                                                       java.lang.NullPointerException: Attempt to invoke virtual method 'void name.app.DbHelper.updateUserData(name.app.UserData)' on a null object reference
                                                                           at name.app.ListAdapter$ListViewHolder.onItemClear(ListAdapter.java:95)
                                                                           at name.app.SimpleItemTouchHelperCallback.clearView(SimpleItemTouchHelperCallback.java:63)
                                                                           at android.support.v7.widget.helper.ItemTouchHelper$3.onAnimationEnd(ItemTouchHelper.java:619)
                                                                           at android.support.v4.animation.HoneycombMr1AnimatorCompatProvider$AnimatorListenerCompatWrapper.onAnimationEnd(HoneycombMr1AnimatorCompatProvider.java:115)
                                                                           at android.animation.ValueAnimator.endAnimation(ValueAnimator.java:1149)
                                                                           at android.animation.ValueAnimator.doAnimationFrame(ValueAnimator.java:1309)
                                                                           at android.animation.AnimationHandler.doAnimationFrame(AnimationHandler.java:146)
                                                                           at android.animation.AnimationHandler.-wrap2(AnimationHandler.java)
                                                                           at android.animation.AnimationHandler$1.doFrame(AnimationHandler.java:54)
                                                                           at android.view.Choreographer$CallbackRecord.run(Choreographer.java:869)
                                                                           at android.view.Choreographer.doCallbacks(Choreographer.java:683)
                                                                           at android.view.Choreographer.doFrame(Choreographer.java:616)
                                                                           at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:857)
                                                                           at android.os.Handler.handleCallback(Handler.java:751)
                                                                           at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                           at android.os.Looper.loop(Looper.java:154)
                                                                           at android.app.ActivityThread.main(ActivityThread.java:6123)
                                                                           at java.lang.reflect.Method.invoke(Native Method)
                                                                           at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
                                                                           at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:757)

【问题讨论】:

您好,这个问题太长了,我认为您应该简化以获得更多关注。另一方面,如果我理解,请告诉我,当你 d&d 一个项目时,它会回到原来的位置?也许您可以尝试在 ViewHolder 类中实现 ItemTouchHelper,然后在 OnItemClear 方法中将订单存储在您的数据库中。希望对您有所帮助! @noe 我很欣赏你的观点,我会重新写下这个问题。是的,它只是回到原来的位置,我会试试你的建议 - 感谢你的 cmets。 @Tom,重新组织 RecyclerView 数据列表是什么意思?当您拖放一个项目时,它只会占据新位置,而其他项目会向下或向上移动。这种行为实际上是重新组织de list吧? @leobelizquierdo 是的,当我拖放一个项目时,我希望该项目占据列表中的新位置。但是,我的应用程序只拖动该项目,然后将其放回原来的位置,它实际上并没有改变列表的顺序 @Tom,你确定onMove 被调用了吗? onItemMove 执行后你的日志显示什么? 【参考方案1】:

我不确定是否发现了您的问题,但我注意到了(希望这会有所帮助): 在您的onItemMove 中,您正在通过交换项目重构dataList,但适配器仅通知一般更改。

猜测移动项目(并保存动画)的最简单方法是删除它并再次添加:

UserData item = dataList.remove(fromPosition);
dataList.add(i, toPossition);
notifyItemMoved(fromPosition, toPosition);

【讨论】:

您不需要删除该项目并重新添加它,只需swap两个涉及的项目并通过notifyItemMoved(fromPosition, toPosition)通知适配器。 我尝试实现您的答案,但 remove(fromPosition) 导致错误以 java.lang.IndexOutOfBoundsException: Invalid index 1, size is 1 开头 dataList 是否在开始时包含 2 个条目? onItemMove 打了多少次电话? @user5599807 onItemMove 每次被拖动到不同位置时都会调用。如果dataList 有 2 个条目,则调用一次。 我尝试实现您的答案,但拖放行为没有变化,【参考方案2】:

已编辑:查看完整示例 here

我测试了您的代码,您的 OnItemMove 方法按预期工作。 可能,您在将订单存储在数据库中时遇到问题?

这里有一个例子:

1- 创建ItemTouchHelperViewHolder 接口:

public interface ItemTouchHelperViewHolder 
    void onItemSelected();
    void onItemClear();

现在在您的 ViewHolder 类中实现它。

2- 转到SimpleItemTouchHelperCallback 类并添加这两个方法:

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

        if (viewHolder instanceof ItemTouchHelperViewHolder) 
            // Tell the view holder it's time to restore the idle state
            ItemTouchHelperViewHolder itemViewHolder = (ItemTouchHelperViewHolder) viewHolder;
            itemViewHolder.onItemClear();
        
    

3- 在OnItemClear(ViewHolder 类)中存储新订单:

 @Override
        public void onItemClear() 
            for (int count = 0; count < dataList.size(); count++) 
                UserData u = dataList.get(count);
                u.setOrder(count);
                mDbHelper.updateOrder(u);
            
            adapter.notifyDataSetChanged();
        

【讨论】:

我是否将代码示例 1 和 3 放在 ListAdapter 类中? 在你的名为 ListViewHolder 的类中 我很难理解,抱歉。我看不到代码示例 1 是如何放入 ListViewHolder 中的,它说 “内部类不能有静态声明”,但我可以将它放入 ListAdapter 类的其余部分中。我也不知道将代码示例 3 放在哪里,它说 Override 并没有覆盖它的超类。 @TomJames 先生,您尝试过我的建议吗?我的代码工作正常,它在回收站视图中对文本视图执行拖放操作后保存所有位置,并根据您的要求管理项目的位置。 @Noe 对不起,您的代码对我来说仍然太不清楚。我同样复制了您的ListAdapter 类样本,但是Override 仍然没有明显覆盖onItemSelectedonItemClear 的超类;这两种方法也是灰色的,好像它们没有被使用一样,而且我也无法解析setOrderadapter【参考方案3】:

我不确定是否会遇到您的问题。但是我已经使用给定的代码实现了相同的功能。此代码不使用 SQLite,但它使用一些文本视图在回收器视图中执行拖放操作。你可以看看我的代码:

MovieTouchHelper.java

public class MovieTouchHelper extends ItemTouchHelper.SimpleCallback 
private MovieAdapter mMovieAdapter;

public MovieTouchHelper(MovieAdapter movieAdapter)
    super(ItemTouchHelper.UP | ItemTouchHelper.DOWN, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT);
    this.mMovieAdapter = movieAdapter;


@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) 
    mMovieAdapter.swap(viewHolder.getAdapterPosition(), target.getAdapterPosition());
    return true;


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


MovieAdapter.java

public class MovieAdapter extends RecyclerView.Adapter<MovieAdapter.ViewHolder> 
private Context mContext;
private List<Movie> mMovies;

public MovieAdapter(Context context, List<Movie> movies)
    this.mContext = context;
    this.mMovies = movies;


@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) 
    return new ViewHolder(LayoutInflater.from(mContext).inflate(R.layout.list_item_movie, parent, false));


@Override
public void onBindViewHolder(ViewHolder holder, int position) 
    holder.bindMovie(mMovies.get(position));


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


public void remove(int position) 
    mMovies.remove(position);
    notifyItemRemoved(position);


public void swap(int firstPosition, int secondPosition)
    Collections.swap(mMovies, firstPosition, secondPosition);
    notifyItemMoved(firstPosition, secondPosition);


public class ViewHolder extends RecyclerView.ViewHolder
    public final TextView movieNameTextView;

    public ViewHolder(View view)
        super(view);
        movieNameTextView = (TextView) view.findViewById(R.id.movie_name);
    

    public void bindMovie(Movie movie)
        this.movieNameTextView.setText(movie.getName());
    


您可以根据需要编辑代码。 希望这会有所帮助!

【讨论】:

我试过你的答案,但问题仍然存在。我相信这是由于我的 ArrayList 来自 SQL - 它有自己的顺序并且不允许更改。【参考方案4】:

onItemMove 中,您不需要创建所有swap,因为每次所选项目与旁边的项目更改其位置时都会调用该方法。因此,for 中的每次迭代都会关注对方法的每次调用。

您应该在适配器中将项目从旧位置 (dragged.getAdapterPosition()) 移动到新位置 (target.getAdapterPosition()),并调用 RecyclerView.Adapter.notifyItemMoved(int, int)。

您的onItemMove 应该如下所示:

@Override
public void onItemMove(int fromPosition, int toPosition) 
    Collections.swap(mItems, fromPosition, toPosition);
    notifyItemMoved(fromPosition, toPosition);

【讨论】:

我已更新我的问题以包括处理我的项目移动的类,这是否会改变您建议我使用 setOnLongClickListener 的答案? @Tom,SimpleItemTouchHelperCallback 课程已经在你之前的帖子中了。抱歉,默认情况下,ItemTouchHelper 会在长按 View 时开始拖动,而且您也将 isLongPressDragEnabled 设置为 true,因此您不必设置 setOnLongClickListener

以上是关于拖放从 SQLiteDatabase 填充的 RecyclerView的主要内容,如果未能解决你的问题,请参考以下文章

JQuery-UI 在 Re-Drag 上拖放和重新拖动克隆

我拖放一个表视图小部件 (Qt)。填充元素后如何调整大小?

WPF 拖放 C# 也可以拖动图像

通过拖放复制引导 td

填充listView时数组自适应给出空指针异常

拖放、可重新排序的列表的低级(无框架)示例?