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