在onLongPress之后,gridview中的第一个视图在startDrag中获得NullPointerException

时间:2013-08-16 16:09:13

标签: android gridview drag-and-drop nullpointerexception

我有一个GridView。 GridView中的每个项目都是水平(或垂直)布局(取决于方向)。在该布局中是ImageView和TextView。

当我在除GridView中的第一个以外的任何ImageView上执行“长触摸”时,一切都按计划进行。在onLongPress()处理程序中,我在ImageView上调用startDrag,一切都按计划运行。如果我在GridView中的第一个ImageView上执行“长触摸”,我会在Android View的startDrag()方法中获得NullPointer异常。

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)

我能够验证传递给startDrag的所有参数都是非null - 一个ClipData,一个DragShadowBuilder和我的ImageView作为LocalState。这是代码片段:

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

startDrag返回false,logcat包含无法启动拖动消息和异常跟踪。

这只发生在gridview中的第一个ImageView上。所有其他人都工作得很好。

我在Android视图源周围寻找线索 - 发现我的设备的构建/标记是试验和错误,但是我发现第16281行在startDrag中的少数几个是标签jb-mr1-release(我的Nexus 10是4.2.1所以它可能是正确的)。 16281的代码是:

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

第16281行是try中的第一个语句:IBinder token = mAttachInfo.mSession ...

如果我的侦探是正确的(我有正确的JB / View.java源),那么问题似乎是mAttachInfo或其中一个字段为null。 shadowSize之前已经过审核,表面刚刚创建。是否有一些原因导致第一个View没有“mAttachInfo”值(假设它意味着它没有附加到窗口)?或者它可能是try块中的其他一行(异常被捕获)。

3 个答案:

答案 0 :(得分:1)

我也遇到过这个问题。我通过添加一个包含视图图像的ImageView来处理它并使用它,因为我将拖动原始视图并且它正在工作。

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

答案 1 :(得分:0)

如果未附加视图,则#startDrag将抛出NPE。

视图#isAttachedToWindow可以告诉您视图是否附加,但此方法仅适用于KITKAT。

我要提交错误。

答案 2 :(得分:0)

我知道这是旧的,但我遇到了这个问题。 在我的自定义适配器中,我试图使项目成为正方形,所以我做了像

这样的事情
imageView.setLayoutParams(new AbsListView.LayoutParams(width, width));

对我有用的是

imageView.getLayoutParams().width = width;
imageView.getLayoutParams().height = width;