【问题标题】:Is it possible to make a drag shadow opaque?是否可以使拖动阴影不透明?
【发布时间】:2014-01-13 08:59:03
【问题描述】:

如问题所述。这是我的 dragshadowbuilder 供参考。如您所知,拖动时创建的阴影是半透明的。反正有没有让它不透明? (完全固体)

public class MyDragShadowBuilder extends View.DragShadowBuilder {
    View view;
    int width;
    int height;
    Bitmap bitmap;
    public MyDragShadowBuilder(View v) {
        super(v);
        view = v;
        ImageView b = (ImageView)view;
        int x = Character.getNumericValue(b.getContentDescription().charAt(0));
        int y = Character.getNumericValue(b.getContentDescription().charAt(1));
        bitmap = InGameActivity.currentBoardState[x][y].getPicture();
        width = bitmap.getWidth();
        height = bitmap.getHeight();
    }

    @Override
    public void onDrawShadow(Canvas canvas) {
        Rect source = new Rect(0, 0, InGameActivity.chessSquareHeightWidth, InGameActivity.chessSquareHeightWidth);
        canvas.drawBitmap(bitmap, null, source, null);
    }

    @Override
    public void onProvideShadowMetrics(Point shadowSize, Point touchPoint) {
        shadowSize.set(InGameActivity.chessSquareHeightWidth, InGameActivity.chessSquareHeightWidth);
        touchPoint.set(InGameActivity.chessSquareHeightWidth/2, InGameActivity.chessSquareHeightWidth/2);
    }
}

编辑:这是我当前的 onTouch 代码,我还将提供应用程序的背景。

OnTouchListener myOnTouchListener = new OnTouchListener() {

                @Override
                public boolean onTouch(View view, MotionEvent event) {
                    System.out.println(event.toString());
                    if (event.getAction() == MotionEvent.ACTION_DOWN) {
                        ImageView b = (ImageView)view;
                        int x = Character.getNumericValue(b.getContentDescription().charAt(0));
                        int y = Character.getNumericValue(b.getContentDescription().charAt(1));
                        if (!currentBoardState[x][y].isEmpty()) {
                            ((ImageView)view).setImageBitmap(null);
                            DragShadowBuilder shadowBuilder = new MyDragShadowBuilder(view);  
                            view.startDrag(null, shadowBuilder, view, 0);
                        }

                        moveChessPiece;
                        return true;
                    }

                    return false;
                }
            });

好的,这就是您需要了解的内容。我正在开发一个国际象棋应用程序。我有一个 8x8 GridLayout,我将其命名为 currentBoardState。因此,目前我希望能够拖动该作品,但我希望拖动的作品是不透明的,以便用户感觉到他/她实际上是在移动作品而不是单击然后像以前一样点击目的地。

【问题讨论】:

  • 您的意思是您的视图是半透明的,但您希望它的拖动阴影是不透明的?

标签: android


【解决方案1】:

不知道有没有人知道, 我们可以使用标志 DRAG_FLAG_OPAQUE 实现相同的目的, 所以对应的 startDrag 方法如下所示:

    View.DragShadowBuilder dragShadowBuilder = new View.DragShadowBuilder(view);
    view.startDrag(clipData, dragShadowBuilder, view, DRAG_FLAG_OPAQUE);

【讨论】:

  • 如何在较低的 api 级别上实现此结果?
【解决方案2】:

正如@Ernir 所说,没有API 获取DragShadow。但是我们知道拖动位置和拖动视图,所以我们可以自己绘制。

我写了一个简单且功能有限的demo,大家可以下载here

它实现了一个名为 DragContainer 的自定义 ViewGroup,使用它将原始根视图包装在布局 xml 中。

<info.dourok.android.demo.DragContainer xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/root"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <!-- original root view -->
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
         <!-- ... -->
    </RelativeLayout>

</info.dourok.android.demo.DragContainer>

调用 DragContainer#startDragChild 开始拖拽(演示有更多细节):

在活动中:

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mDragContainer = (DragContainer) findViewById(R.id.root);
        View drag = mDragContainer.findViewById(R.id.drag);
        View drop = mDragContainer.findViewById(R.id.drop);
        drag.setTag(IMAGEVIEW_TAG);
        drag.setOnLongClickListener(new View.OnLongClickListener() {
            public boolean onLongClick(View v) {
                ClipData.Item item = new ClipData.Item((CharSequence) v
                        .getTag());
                ClipData dragData = new ClipData((CharSequence) v.getTag(),
                        new String[] { ClipDescription.MIMETYPE_TEXT_PLAIN },
                        item);
                return mDragContainer.startDragChild(v, dragData, // the data to
                                                                    // be
                                                                    // dragged
                        null, // no need to use local data
                        0 // flags (not currently used, set to 0)
                        );

            }
        });


    }

您也可以扩展 DragContainer 来绘制自定义拖动阴影,这是您的需求示例。

public class MyDragContainer extends DragContainer {
    public MyDragContainer(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MyDragContainer(Context context) {
        super(context, null);
    }

    public MyDragContainer(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    int width;
    int height;
    Bitmap bitmap;

    @Override
    protected void onSetDragTarget(View v) {
        ImageView b = (ImageView) v;
        int x = Character.getNumericValue(b.getContentDescription().charAt(0));
        int y = Character.getNumericValue(b.getContentDescription().charAt(1));
        bitmap = InGameActivity.currentBoardState[x][y].getPicture();
        width = bitmap.getWidth();
        height = bitmap.getHeight();
    }

    @Override
    protected void drawDragShadow(Canvas canvas) {
        Rect source = new Rect(0, 0, InGameActivity.chessSquareHeightWidth, InGameActivity.chessSquareHeightWidth);

        int w =  InGameActivity.chessSquareHeightWidth;
        int h = InGameActivity.chessSquareHeightWidth;

        canvas.translate(getDragX() - w / 2, getDragY() - h / 2);

        canvas.drawBitmap(bitmap, null, source, null);
    }
}

我希望它会有所帮助。

【讨论】:

  • 嗨,@Clay 你运行演示了吗?
  • 嗨@Clay,我已经更新了你需要重新下载的演示。
  • 您必须在您的活动布局xml中声明DragContainer为根视图,并在setContentView之后获取引用。例如:mDragContainer = (DragContainer) findViewById(R.id.root);
  • DragContainer 不是DragShadowBuilder。这是一个Viewgroup,是您原始活动视图的父级。您可以通过 gtalk 与我联系。
【解决方案3】:

我认为实现这一点的正确方法是:

/* Create the shadow from a view */
View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(view);
/* Access the view created and set the alpha of it to 1 (totally opaque)*/
shadowBuilder.getView().setAlpha(1);
/* Start dragging the object */
view.startDrag(data, shadowBuilder, view, 0);

编辑 它似乎不适用于 4.4 及更高版本:(

【讨论】:

    【解决方案4】:

    不,不幸的是,据我所知这是不可能的。

    阴影Bitmap 绘制在您无法触及的表面上。唯一的解决方案是像在 API 11 之前那样实现拖放。它实际上并不像您想象的那么难。

    一些帮助您入门的链接:

    Link 1

    Link 2 *更新

    【讨论】:

    • 您提供的第二个链接,有不透明的阴影吗?我可以试试看,但也许你已经知道了
    • 对不起,第二个链接错了,现在我只是让您寄予厚望:/。我已经编辑了我的回复。
    • 如果我给你我的 onTouch 代码,你能帮我把它和你的第二个链接整合起来吗?
    • 请查看我的编辑,如果您需要任何其他信息,请随时询问
    • 你只是把任务交给我了吗?对不起,这行不通。你应该自己做,但如果你遇到问题,我可以帮助你。
    【解决方案5】:

    这是不可能实现的。这就是startDragAndDrop 创建要拖动的表面的方式:

    final SurfaceControl surfaceControl = new SurfaceControl.Builder(session)
                .setName("drag surface")
                .setParent(root.getSurfaceControl())
                .setBufferSize(shadowSize.x, shadowSize.y)
                .setFormat(PixelFormat.TRANSLUCENT)
                .setCallsite("View.startDragAndDrop")
                .build();
    

    如您所见,格式设置为 PixelFormat.TRANSLUCENT,没有选项可以更改

    【讨论】:

      猜你喜欢
      • 2015-09-07
      • 1970-01-01
      • 2018-02-13
      • 2012-07-17
      • 1970-01-01
      • 2012-03-23
      • 1970-01-01
      • 1970-01-01
      • 2011-01-09
      相关资源
      最近更新 更多