如何从 Recycler 视图中拖放图像并将其置于其他布局中

Evi*_*gle 3 android drag-and-drop imageview android-recyclerview

我有一个水平 Recycler 视图,其中包含一个项目列表。每个项目都有一个文本视图和图像视图来表示项目(例如一个正方形的图像和图像上方的文本“Square”)。回收器视图位于它自己位于屏幕顶部的相对布局内。我需要做的是从回收站视图中拖出一个图像,然后将它放到它外面的另一个布局中,这个布局低于这个布局。但是,从回收器视图中拖动的图像不得删除,而应将图像的副本放置到外部布局中。图像还必须放置在布局中用户松开手指的确切位置。有没有办法实现这一目标?

这方面的一个例子可能就像在游戏中一样,其中用户有一个对象列表可以拖放到游戏世界中。

这是一个例子来说明我的意思:

例子

Recycler View 的适配器类:

public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.ViewHolder> {

private List<ListItems> listItems;
private Context context;

public RecyclerAdapter(List<ListItems> listItems, Context context) {
    this.listItems = listItems;
    this.context = context;
}

@Override
public RecyclerAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View v = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.layout_recycler_view_row_one, parent, false);

    ViewHolder vh = new ViewHolder(v);
    return vh;
}

@Override
public void onBindViewHolder(RecyclerAdapter.ViewHolder holder, int position) {

    ListItems listItems = listItems.get(position);

    holder.textView.setText(listItems.getItemName());
    holder.imageView.setImageResource(listItems.getImageDrawable());
}


@Override
public int getItemCount() {
    return listItems.size();
}

public class ViewHolder extends RecyclerView.ViewHolder {

    public ImageView imageView;
    public TextView textView;

    public ViewHolder(View itemView) {
        super(itemView);
        imageView = (ImageView) itemView.findViewById(R.id.item_image_view);
        textView = (TextView) itemView.findViewById(R.id.item_name_text_view);

    }
}
Run Code Online (Sandbox Code Playgroud)

MainActivity.class:

 public class MainActivity extends AppCompatActivity {

RelativeLayout relativeLayoutMiddle;

private RecyclerView recyclerView;
private RecyclerView.LayoutManager layoutManager;
private RecyclerView.Adapter adapter;
private List<ListItems> listItems;

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

    listItems = new ArrayList<>();

    for (int i = 0; i < 4; i++) {
        if(i==0)
        {
            ListItems listItems = new ListItems("Square", R.drawable.square);
            listItems.add(listItems);
        }
        else if(i==1)
        {
            ListItems listItems = new ListItems("Circle", R.drawable.circle);
            listItems.add(listItems);
        }
        else if(i==2)
        {
            ListItems listItems = new ListItems("Rectangle", R.drawable.rectangle);
            listItems.add(listItems);
        }
        else if(i==3)
        {
            ListItems listItems = new ListItems("Triangle", R.drawable.triangle);
            listItems.add(listItems);
        }
    }

    recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
    recyclerView.setHasFixedSize(true);
    layoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
    recyclerView.setLayoutManager(layoutManager);
    adapter = new RecyclerAdapter(listItems, this);
    recyclerView.setAdapter(adapter);

    relativeLayoutMiddle = (RelativeLayout) findViewById(R.id.relativeLayoutMiddle);
Run Code Online (Sandbox Code Playgroud)

adn*_*eal 7

这基本上可以使用Android 拖放 api在几行代码中完成。

  1. 称呼 View.startDragAndDrop
  2. 将 a 附加View.OnDragListener到您的放置容器
  3. 等待DragEvent.ACTION_DROP,然后充气并定位您的形状

在你的RecyclerView.Adapter,附上一个View.OnLongClickListener然后调用View.startDragAndDrop。就像是:

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    final View v = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.layout_recycler_view_row_one, parent, false);
    final ViewHolder holder = new ViewHolder(v);
    final View shape = holder.imageView;
    holder.itemView.setOnLongClickListener(v -> {
        final ListItems item = listItems.get(holder.getAdapterPosition());
        final DragData state = new DragData(item, shape.getWidth(), shape.getHeight());
        final DragShadowBuilder shadow = new DragShadowBuilder(shape);
        ViewCompat.startDragAndDrop(shape, null, shadow, state, 0);
        return true;
    });
    return holder;
}
Run Code Online (Sandbox Code Playgroud)

public class DragData {

    public final ListItems item;
    public final int width;
    public final int height;

    public DragData(ListItems item, int width, int height) {
        this.item= item;
        this.width = width;
        this.height = height;
    }

}
Run Code Online (Sandbox Code Playgroud)

在您Activity或在您膨胀底部容器布局的任何地方,调用View.setOnDragListener和调用时DragEvent.ACTION_DROP我们可以膨胀View您调用的副本startDragAndDrop。就像是:

@Override
public boolean onDrag(View v, DragEvent event) {
    switch (event.getAction()) {
        case DragEvent.ACTION_DRAG_ENTERED:
            dropContainer.setBackgroundColor(GREEN);
            break;
        case DragEvent.ACTION_DRAG_EXITED:
            dropContainer.setBackgroundColor(RED);
            break;
        case DragEvent.ACTION_DRAG_ENDED:
            dropContainer.setBackgroundColor(WHITE);
            break;
        case DragEvent.ACTION_DROP:
            final float dropX = event.getX();
            final float dropY = event.getY();
            final DragData state = (DragData) event.getLocalState();

            final ImageView shape = (ImageView) LayoutInflater.from(this).inflate(
                    R.layout.view_shape, dropContainer, false);
            shape.setImageResource(state.item.getImageDrawable());
            shape.setX(dropX - (float) state.width / 2);
            shape.setY(dropY - (float) state.height / 2);
            shape.getLayoutParams().width = state.width;
            shape.getLayoutParams().height = state.height;
            dropContainer.addView(shape);
            break;
        default:
            break;
    }
    return true;
}
Run Code Online (Sandbox Code Playgroud)

结果