Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

After onLongPress, first view in gridview gets NullPointerException in startDrag

I have a GridView. Each of the items in the GridView is a Horizontal (or Vertical) Layout (depending upon orientation). Inside that layout is an ImageView and a TextView.

When I perform a "Long Touch" on any ImageView other than the first in the GridView, everything works as planned. In the onLongPress() handler, I call the startDrag on the ImageView and everything works as planned. If I perform a "Long Touch" on the first ImageView in the GridView, I get a NullPointer exception in Android View's startDrag() method.

08-16 10:11:04.425: E/View(2456): Unable to initiate drag
08-16 10:11:04.425: E/View(2456): java.lang.NullPointerException
08-16 10:11:04.425: E/View(2456):   at android.view.View.startDrag(View.java:16281)
08-16 10:11:04.425: E/View(2456):   at org.xyzzy.test.GridLauncher$ShortCutTouchListener$ShortcutGestureListener.onLongPress(RemoteLauncher.java:650)
08-16 10:11:04.425: E/View(2456):   at android.view.GestureDetector.dispatchLongPress(GestureDetector.java:675)

I was able to verify that all of the arguments passed to startDrag were non-null - a ClipData, a DragShadowBuilder, and my ImageView as the LocalState. Here's that code snippet:

ClipData data = ClipData.newPlainText("", "");
DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(mView);
boolean doingDrag = mView.startDrag(data, shadowBuilder, mView, 0);

startDrag returns false and the logcat contains the Unable to start drag message and the exception trace.

This only happens on the first ImageView in the gridview. All others work just fine.

I poked around the Android View source looking for a clue - finding the build/tag for my device was trial and error but one of the few I found where line 16281 was in startDrag was with tag jb-mr1-release (my Nexus 10 is 4.2.1 so it may be the right one). The code at 16281 is:

Point shadowSize = new Point();
Point shadowTouchPoint = new Point();
shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);

if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
        (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
    throw new IllegalStateException("Drag shadow dimensions must not be negative");
}

if (ViewDebug.DEBUG_DRAG) {
    Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
            + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
}
Surface surface = new Surface();
try {
    IBinder token = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
            flags, shadowSize.x, shadowSize.y, surface);
    if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token=" + token
            + " surface=" + surface);

Line 16281 is the first statement in the try: IBinder token = mAttachInfo.mSession ...

If my sleuthing is correct (I have the right JB/View.java source), it would appear that the issue is with the mAttachInfo or one of its fields being null. shadowSize was vetted earlier and surface was just created. Is there some reason why the first View would not have an "mAttachInfo" value (presuming it means it isn't attached to a window)? Or it is possible that it is some other line within the try block (the exception is getting caught).

like image 865
BJV Avatar asked Aug 16 '13 16:08

BJV


1 Answers

I encountered this problem too. I worked around it by adding an ImageView which contained an image of the view and used it as I would have the original view being dragged and it is working.

Bitmap b = Bitmap.createBitmap(originalView.getWidth(), originalView.getHeight(), Bitmap.Config.ARGB_8888);


Canvas c = new Canvas(b);
            originalView.draw(c);
            mImageView.setImageBitmap(b);
shadowBuilder = new View.DragShadowBuilder(mImageView);
                    mImageView.startDrag(data, shadowBuilder, mImageView, 0);
                    mImageView.setVisibility(View.INVISIBLE);
like image 170
user3483525 Avatar answered Sep 20 '22 16:09

user3483525