RecyclerView拖拽项被ImageView遮挡,如何使其显示在视图上方?
RecyclerView拖拽项被ImageView遮挡,无法悬浮在上方
我有一个RecyclerView和一个ImageView,需求是将RecyclerView列表中的项拖拽至ImageView上方(后续将实现放置功能)。但当前拖拽的项会被ImageView遮挡,显示在其下方。原本以为默认拖拽行为会让视图悬浮在所有元素上方,无法定位问题所在。
Activity代码片段
private void updateRecycler(RecyclerView myrecyclerview) { RecyclerView r = myrecyclerview; itemsAdapter=new skutest_recyclerview_viewadapter(itmlist); runOnUiThread(() -> { if (r.getLayoutManager()==null) { r.setLayoutManager(new LinearLayoutManager(MainActivity.this)); } r.setAdapter(itemsAdapter); ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new ItemTouchHelperCallback(itemsAdapter)); itemTouchHelper.attachToRecyclerView(r); }); }
ItemTouchHelperAdapter接口
public interface ItemTouchHelperAdapter { void onItemMoved(int fromPosition, int toPosition); void onItemDropped(int position); // Optional for handling dropped items on image }
RecyclerView Adapter代码
public class skutest_recyclerview_viewadapter extends RecyclerView.Adapter<skutest_recyclerview_viewadapter.ViewHolder> implements ItemTouchHelperAdapter { RecyclerView mRecyclerView; List<cl_sku_info> skulist; public skutest_recyclerview_viewadapter(List<cl_sku_info> skulist) { this.skulist=skulist; } @NonNull @Override public skutest_recyclerview_viewadapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { LayoutInflater inflater = LayoutInflater.from(parent.getContext()); ItemBinding b = ItemBinding.inflate(inflater, parent, false); return new ViewHolder(b); } @Override public void onBindViewHolder(@NonNull skutest_recyclerview_viewadapter.ViewHolder holder, int position) { holder.setData(skulist.get(position)); } @Override public int getItemCount() { return skulist==null ? 0 : skulist.size(); } @Override public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) { super.onAttachedToRecyclerView(recyclerView); mRecyclerView = recyclerView; } @Override public void onItemMoved(int fromPosition, int toPosition) { } @Override public void onItemDropped(int position) { } public static class ViewHolder extends RecyclerView.ViewHolder { private final ItemBinding binding; public ViewHolder(ItemBinding binding) { super(binding.getRoot()); this.binding=binding; } public void setData(cl_sku_info clSkuInfo) { binding.label.setText("*****");//clSkuInfo.getSTOCK_NO()); binding.image.setImageBitmap(images.getInstance().getimage(clSkuInfo.getSTOCK_NO(),100)); } } }
ItemTouchHelperCallback代码
import androidx.annotation.NonNull; import androidx.recyclerview.widget.ItemTouchHelper; import androidx.recyclerview.widget.RecyclerView; public class ItemTouchHelperCallback extends ItemTouchHelper.Callback { private final ItemTouchHelperAdapter adapter; public ItemTouchHelperCallback(ItemTouchHelperAdapter adapter) { this.adapter = adapter; } @Override public int getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) { final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.RIGHT | ItemTouchHelper.LEFT; final int swipeFlags = 0; // Disable swiping for now return makeMovementFlags(dragFlags, swipeFlags); } @Override public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) { adapter.onItemMoved(viewHolder.getAdapterPosition(), target.getAdapterPosition()); return true; } @Override public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) { } }
布局文件代码
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/main" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" android:weightSum="2" android:hardwareAccelerated="false" tools:context=".activities.MainActivity"> <androidx.recyclerview.widget.RecyclerView android:id="@+id/myrecyclerview" android:layout_width="0dp" android:layout_height="match_parent" tools:itemCount="20" android:layout_weight="1" tools:listitem="@layout/item" /> <ImageView android:id="@+id/imageView" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:background="@drawable/i1" android:scaleType="center" /> </LinearLayout>
解决方案
问题原因
ItemTouchHelper默认将拖拽视图添加在RecyclerView的内部层级中,而你的布局里ImageView和RecyclerView是LinearLayout的同级子View,且ImageView在RecyclerView之后声明。根据Android布局的绘制顺序,后声明的View层级更高,会遮挡前面View的内容,包括拖拽视图。
解决方法
方法1:调整布局顺序
将ImageView移到RecyclerView之前声明,这样RecyclerView的层级更高,拖拽视图就不会被遮挡:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/main" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" android:weightSum="2" android:hardwareAccelerated="false" tools:context=".activities.MainActivity"> <ImageView android:id="@+id/imageView" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:background="@drawable/i1" android:scaleType="center" /> <androidx.recyclerview.widget.RecyclerView android:id="@+id/myrecyclerview" android:layout_width="0dp" android:layout_height="match_parent" tools:itemCount="20" android:layout_weight="1" tools:listitem="@layout/item" /> </LinearLayout>
方法2:设置RecyclerView的Z轴层级
通过给RecyclerView设置更高的translationZ,让它的内容(包括拖拽视图)悬浮在ImageView上方:
- 在布局中添加属性:
<androidx.recyclerview.widget.RecyclerView android:id="@+id/myrecyclerview" android:layout_width="0dp" android:layout_height="match_parent" tools:itemCount="20" android:layout_weight="1" android:translationZ="2dp" tools:listitem="@layout/item" />
- 或者在代码中设置:
myrecyclerview.setTranslationZ(2f);
方法3:自定义拖拽视图层级(进阶)
重写ItemTouchHelperCallback的onChildDraw方法,手动提升拖拽视图的Z轴层级:
@Override public void onChildDraw(@NonNull Canvas c, @NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) { super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive); // 给拖拽中的item设置更高的Z轴,确保悬浮 viewHolder.itemView.setTranslationZ(10f); } @Override public void clearView(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) { super.clearView(recyclerView, viewHolder); // 拖拽结束后恢复Z轴 viewHolder.itemView.setTranslationZ(0f); }
后续放置功能提示
如果要实现拖拽到ImageView上的放置逻辑,需要监听拖拽的位置,通过getGlobalVisibleRect获取ImageView的屏幕坐标范围,判断拖拽视图的位置是否在该范围内,然后在onItemDropped或clearView中处理放置逻辑。
内容的提问来源于stack exchange,提问作者blm99
相关产品推荐
相关产品推荐

