android - 如何在 Android 上创建半可拖动的回收视图?
问题描述
我的问题很简单,但在 Android 上实现起来非常棘手。我想知道如何只拖动“可拖动部分”,即标题下方的项目。
我已经按照本教程来实现拖动功能。但是在拖动时如何区分 Header ViewHolder 和 Item ViewHolder 呢?
下面列出了适配器类
public class ColorRecyclerViewAdapter extends
RecyclerView.Adapter<ColorRecyclerViewAdapter.ItemViewHolderSelector> implements TouchCallbackHelperAdapter {
private Context context;
private ArrayList<String> mItems;
private final HelperOnStartDragListener mDragStartListener;
private ItemViewHolderSelector oldHolder;
public ColorRecyclerViewAdapter(Context context, ArrayList<String> data, HelperOnStartDragListener dragStartListener) {
this.context = context;
this.mItems = data;
this.mDragStartListener = dragStartListener;
}
@Override
public void onItemDismiss(int position) {
mItems.remove(position);
notifyItemRemoved(position);
}
@Override
public boolean onItemMove(final int fromPosition, final int toPosition) {
if (fromPosition < toPosition) {
for (int i = fromPosition; i < toPosition; i++) {
Collections.swap(mItems, i, i + 1);
}
} else {
for (int i = fromPosition; i > toPosition; i--) {
Collections.swap(mItems, i, i - 1);
}
}
mDragStartListener.onFinishDrag(null);
notifyItemMoved(fromPosition, toPosition);
return true;
}
public ArrayList<String> getData() {
return mItems;
}
public void addItem(String item) {
mItems.add(item);
notifyItemInserted(mItems.size() - 1);
}
@Override
public ItemViewHolderSelector onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view;
view = LayoutInflater.from(context).inflate(R.layout.color_recycler_view_item_drag_mode, parent, false);
return new ItemViewHolderSelector(view);
}
@Override
public void onBindViewHolder(@NonNull final ItemViewHolderSelector holder, final int position) {
final String item = mItems.get(position);
holder.name.setText(item);
holder.drag.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mDragStartListener.onStartDrag(holder);
break;
}
return true;
}
});
}
@Override
public int getItemCount() {
return mItems != null ? mItems.size() : 0;
}
class ItemViewHolderSelector extends RecyclerView.ViewHolder implements HelperViewHolderSelector {
private TextView name;
private ImageView drag;
private View itemView;
ItemViewHolderSelector(View itemView) {
super(itemView);
this.itemView = itemView;
drag = itemView.findViewById(R.id.color_recycler_view_drag);
name = itemView.findViewById(R.id.color_recycler_view_name);
}
@Override
public void onItemSelected() {
itemView.setBackgroundColor(Color.LTGRAY);
}
@Override
public void onItemClear() {
itemView.setBackgroundColor(0);
}
}
}
编辑:
基于@fernandospr 的回答,我创建了一个包含最终代码的存储库。您可以在此处访问它。
解决方案
仅显示RecyclerView
您在onCreateViewHolder
.
根据您的职位,您需要创建不同的视图。这意味着您将创建一个HeaderViewHolder
当位置对应于标题时以及ItemViewHolder
当位置对应于项目时。
所以你必须重构你ColorRecyclerViewAdapter
的:
private static final int HEADER_VIEW = 0;
private static final int ITEM_VIEW = 1;
@Override
public RecyclerView.ViewHolderSelector onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
if (viewType == ITEM_VIEW) {
...
return new ItemViewHolderSelector(view);
} else {
...
return new HeaderViewHolderSelector(view);
}
}
@Override
public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder holder, final int position) {
if (ITEM_VIEW == holder.getItemViewType()) {
...
} else {
...
}
}
@Override
public int getItemCount() {
return itemsCount + headersCount;
}
在里面onBindViewHolder
你应该只允许通过设置 TouchListener 来拖动项目。
此外,在onMove
and 和onSwiped
方法中,您应该使用位置来了解它是标题还是项目,并允许或不允许执行:
@Override
public void onItemDismiss(int position) {
if (isItemPosition(position)) {
...
}
}
@Override
public boolean onItemMove(final int fromPosition, final int toPosition) {
if (isItemPosition(position)) {
...
}
}
这isItemPosition()
是您需要编写的方法,取决于适配器如何保存项目和标题数据。
推荐阅读
- javascript - django ajax 音频文件上传到views.py
- regex - 正则表达式不包括特定字符
- mysql - 在 mysql 中使用 not exist 来查找尚未分配的 ID
- .net - 是否应该将 netstandard.dll 部署到最终用户
- swift - 如何在swift 4中使用电子邮件身份验证杀死应用程序后保持登录状态
- user-interface - 运行 OMNeT++ 示例时缺少用户界面
- kubernetes - 失败错误:无法连接到任何 etcd 端点 - etcd:0/1 已连接:kubeadm
- api - 我们如何使用 python SDK 在 onelogin 中添加应用程序?
- c# - 如何以两级深度分层检索实体的所有字段?
- r - R 为什么 nclass.FD 返回的 bin 数量与 hist 函数不同?