How to show custom DragShadow instead of ListViewF

2019-07-30 15:15发布

问题:

I have a ListFragment that has a custom adapter so that I could have a text view and an image view on each row. When dragging this row to my canvas (a separate fragment), it shows the whole row as the drag shadow (default behavior). I want to drag only the icon/image to the canvas. My code sample below produces the original drag shadow (whole row from list view) with the desired image drawn behind the cell (a bit stretched because of the bounds setting code). Pretty picture here.

According to the View.DragShadowBuilder documentation, you can discard the view that is passed into the constructor and draw your own view. Problem I have with that approach is that the canvas/view size is set and I'm new to graphics. I've been unsuccessful in my attempts to resize and/or clear the canvas and draw my own drawable/bitmap on it. I tried coloring over the canvas with something like canvas.drawColor(Color.BLACK), but that just makes the background black but still behind the original cell.

Another possibility mentioned in the documentation is passing in any view that is in scope. To that end, I created an image view and added a bitmap to it. When I drag, I get an empty drag shadow. Debugging tells me that the height and width of the image view are 0 (and therefore the view and canvas end up being 0 in the drag shadow builder). However, if I ask for the height and width of the drawable, it gives me the expected dimensions. Do I need to do something to make the image view update it's size after adding the bitmap?

Which approach is preferred? Do you have a working example of either approach?

Class

public class IconListFragment extends ListFragment
{
    ...
    private void startDraggingItem( View view, int position )
    {
        Log.d( TAG, "Dragging item." );

        // I'd like to use the custom imageview instead of the current view
        ImageView image = new ImageView( getActivity() );
        image.setImageBitmap( getIconBitmap( position ) );
        // Problem: Shows empty drag shadow (debugging shows that the height and width are 0)
        // The drawable is present and has the right dimensions
        // view.startDrag( data, new FlowchartDragShadowBuilder( image, position ), null, ZERO );

        // Start the drag
        // Problem: Shows both images
        view.startDrag( data, new FlowchartDragShadowBuilder( view, position ), null, ZERO );
    }

    private class FlowchartDragShadowBuilder extends View.DragShadowBuilder
    {
        private Drawable shadow;
        int position;

        public FlowchartDragShadowBuilder( View view, int pos )
        {
            super( view );
            Log.d( TAG, "Building shadow." );
            shadow = getIconDrawable( pos );
            shadow.setCallback( view );
            position = pos;
            shadow.setBounds( ZERO, ZERO, view.getWidth(), view.getHeight() );
        }

        @Override
        public void onDrawShadow( Canvas canvas )
        {
            super.onDrawShadow( canvas );

            Log.d( TAG, "Drawing shadow." );
            shadow.draw( canvas );
            getView().draw( canvas );
        }
    }

    ...

回答1:

Not sure what you're doing in getIconBitmap() but maybe that function isn't working.

I use a new imageview:

shadowbm = Bitmap.createBitmap(thisbutton.getWidth(), thisbutton.getHeight(), Bitmap.Config.ARGB_8888);
Canvas m = new Canvas(shadowbm);
thisbutton.draw(m);
thisbutton.setVisibility(View.GONE);
shadow.setImageBitmap(shadowbm);

shadow.setX(thisbutton.getLeft());
shadow.setY(thisbutton.getTop());
shadow.setVisibility(View.VISIBLE);

As long as you can draw onto the new canvas you can make any shadow you want. Just remember to call destroy() on the bitmap to free up the memory.



回答2:

Try enabling the drawing cache. The problem may be because it is not added to any layout.

ImageView image = new ImageView( getActivity() );
image.setDrawingCacheEnabled(true);
image.setImageBitmap( getIconBitmap( position ) );
image.buildDrawingCache();

Then start dragging it. Hope it helps.

Update

In onDrawShadow() get the view bitmap by calling getdrawingCache() method on the imageview

    @Override
    public void onDrawShadow( Canvas canvas )
    {
        super.onDrawShadow( canvas );

        Log.d( TAG, "Drawing shadow." );
        shadow.draw( canvas );
        /* get the bitmap by calling getDrawingCache() on view.*/
        canvas.drawBitmap(getView().getDrawingCache(), left, top, null/*paint*/);
    }