拖放从 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
仍然没有明显覆盖onItemSelected
和onItemClear
的超类;这两种方法也是灰色的,好像它们没有被使用一样,而且我也无法解析setOrder
或adapter
。【参考方案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的主要内容,如果未能解决你的问题,请参考以下文章