Is it possible to make a drag shadow opaque?

前端 未结 5 1048
粉色の甜心
粉色の甜心 2020-12-16 06:14

As question states. here is my dragshadowbuilder for reference. As you know, the shadow that is created when you drag is translucent. Is there anyway to make it opaque? (ful

相关标签:
5条回答
  • 2020-12-16 06:23

    I think the proper way to achieve this is:

    /* 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);
    

    EDIT It doesn't seem to work on 4.4 and beyond :(

    0 讨论(0)
  • 2020-12-16 06:36

    Its not possible to achieve that. This is how startDragAndDrop is creating the surface to drag on:

    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();
    

    As you can see, the format is set to PixelFormat.TRANSLUCENT, and no option to change that

    0 讨论(0)
  • 2020-12-16 06:39

    As @Ernir says, there no API get DragShadow. But we know the drag location and drag view so we can draw it ourselves.

    I write a simple and function limited demo you can download it here.

    It implement a custom ViewGroup named DragContainer, Use it to wrap your original root view in your layout 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>
    

    call DragContainer#startDragChild to start drag like that(the demo have more detail):

    in Activity:

    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)
                            );
    
                }
            });
    
    
        }
    

    You also can extend DragContainer to draw custom drag shadow, This is a example for your requirement.

    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);
        }
    }
    

    I hope it will help.

    0 讨论(0)
  • No, it is unfortunately not possible as far as I can tell.

    The shadow Bitmap is drawn on a surface that you can't reach. The only solution is to implement Drag & Drop like it was done pre API 11. It is actually not as hard as you might think.

    Some links to get you started:

    Link 1

    Link 2 *updated

    0 讨论(0)
  • 2020-12-16 06:44

    Dont know if someone is aware of it or not, We can achieve the same using flag DRAG_FLAG_OPAQUE, So the correspondind startDrag method will look like as below:

        View.DragShadowBuilder dragShadowBuilder = new View.DragShadowBuilder(view);
        view.startDrag(clipData, dragShadowBuilder, view, DRAG_FLAG_OPAQUE);
    
    0 讨论(0)
提交回复
热议问题