本文介绍了如何创建自定义拖动阴影?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要达到的目标:

我想在 Android 中创建拖放功能.我想使用特定布局(不同于被拖动对象本身)作为拖动阴影.

I want to create a drag and drop functionality in Android. I'd like to use a specific layout (different from the dragged object itself) as a drag shadow.

我得到了什么结果:

我的两种方法都没有按预期工作 - 我最终没有可见的拖动阴影(尽管目标确实收到了拖放).

Neither of my approaches works as expected - I end up with no visible drag shadow at all (although the target does receive the drop).

我尝试了什么:

我试过了

  • 在活动中扩展 drag_item 布局,然后将其作为参数传递给影子构建器的构造函数
  • inflating the drag_item layout in the activity, then passing it as an argument to the shadow builder's constructor

  • 在阴影生成器的 onDrawShadow 方法中扩展 drag_item 布局,然后在 canvas
  • 上绘制它
  • inflating the drag_item layout in the shadow builder's onDrawShadow method, then drawing it on the canvas

布局:

我的活动布局:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:tools="http://schemas.android.com/tools"
              android:id="@+id/container"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              tools:context="com.example.app.DragDropTestActivity"
              tools:ignore="MergeRootFrame">
    <TextView
        android:id="@+id/tvReceiver"
        android:text="Drop here"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    <Button
        android:id="@+id/btnDragged"
        android:layout_height="wrap_content"
        android:text="Drag me"
        android:layout_width="match_parent"/>
</LinearLayout>

我想用作拖影的布局:

dragged_item.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Dragged Item"/>
</LinearLayout>

源代码:

这是两种方法的代码(分别由 1BuilderOne2BuilderTwo 表示):

Here's the code with both approaches (represented by 1, BuilderOne and 2, BuilderTwo, respectively):

package com.example.app;

import android.graphics.Canvas;
import android.graphics.Point;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;

public class DragDropTestActivity extends ActionBarActivity
{
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_drag_drop_test);
        Button dragged = (Button) findViewById(R.id.btnDragged);

        dragged.setOnTouchListener(
            new View.OnTouchListener()
            {
                @Override
                public boolean onTouch(View v, MotionEvent event)
                {
                    if (event.getAction() != MotionEvent.ACTION_DOWN) {
                        return false;
                    }
                    LayoutInflater inflater = getLayoutInflater();

                    int approach = 1;
                    // both approaches fail
                    switch (approach) {
                        case 1: {
                            View draggedItem = inflater.inflate(R.layout.dragged_item, null);
                            BuilderOne builder = new BuilderOne(draggedItem);
                            v.startDrag(null, builder, null, 0);
                            break;
                        }
                        case 2: {
                            BuilderTwo builder = new BuilderTwo(inflater, v);
                            v.startDrag(null, builder, null, 0);
                            break;
                        }
                    }

                    return true;
                }
            });
    }

我的 BuilderOne 类:

    public static class BuilderOne extends View.DragShadowBuilder
    {
        public BuilderOne(View view)
        {
            super(view);
        }

        @Override
        public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint)
        {
            super.onProvideShadowMetrics(
                shadowSize,
                shadowTouchPoint);
        }
    }

BuilderTwo类:

    public static class BuilderTwo extends View.DragShadowBuilder
    {
        final LayoutInflater inflater;

        public BuilderTwo(LayoutInflater inflater, View view)
        {
            super(view);
            this.inflater = inflater;
        }

        @Override
        public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint)
        {
            super.onProvideShadowMetrics(
                shadowSize,
                shadowTouchPoint);
        }

        @Override
        public void onDrawShadow(Canvas canvas)
        {
            final View draggedItem = inflater.inflate(R.layout.dragged_item, null);
            if (draggedItem != null) {
                draggedItem.draw(canvas);
            }
        }
    }
}

问题:

我做错了什么?

更新:

已添加赏金.

推荐答案

Kurty 是正确的,在这种情况下您不需要继承 DragShadowBuilder.我的想法是,您传递给 DragShadowBuilder 的视图实际上并不存在于布局中,因此它不会呈现.

Kurty is correct in that you shouldn't need to subclass DragShadowBuilder in this case. My thought is that the view you're passing to the DragShadowBuilder doesn't actually exist in the layout, and therefore it doesn't render.

与其将 null 作为第二个参数传递给 inflater.inflate,不如尝试将膨胀的 View 实际添加到层次结构的某个位置,然后将其传递给常规 DragShadowBuilder:

Rather than passing null as the second argument to inflater.inflate, try actually adding the inflated View to the hierarchy somewhere, and then passing it to a regular DragShadowBuilder:

View dragView = findViewById(R.id.dragged_item);
mDragShadowBuilder = new DragShadowBuilder(dragView);
v.startDrag(null, mDragShadowBuilder, null, 0);

编辑

我知道让 dragged_item 视图一直呈现并不是您想要的,但如果它有效,那么至少我们知道问题出在哪里并且可以寻找解决方案改为那个!

I'm aware that having the dragged_item view being rendered all the time isn't what you want, but if it works then at least we know where the problem is and can look for a solution to that instead!

这篇关于如何创建自定义拖动阴影?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-14 10:14