【问题标题】:Android drag and drop image crash on ICS (4.0.3)ICS(4.0.3)上的Android拖放图像崩溃
【发布时间】:2012-03-29 14:37:01
【问题描述】:

我的应用做的很简单:

它在 GridView 上显示 sdcard 上所有图像的缩略图 以及这些缩略图角落上的图标,以便用户可以触摸它来开始 拖动图像的阴影。

这个阴影可以放在已经设置了拖动监听器的视图上。当那个 发生时,将使用图像文件路径 Uri 作为额外的调用新意图 新意图。到目前为止,一切顺利。

当我开始在没有任何视图的视图上放置阴影时,就会出现问题 拖动监听器,最终冻结屏幕并导致移动设备崩溃!

我在堆栈跟踪中得到的只是:

03-29 14:24:14.803: I/ViewRootImpl(2496): Reporting drop result: false
03-29 14:24:14.803: W/WindowManager(274): Drag is in progress but there is no drag window handle.
03-29 14:24:15.062: I/ViewRootImpl(2496): Reporting drop result: false
03-29 14:24:15.062: W/WindowManager(274): Drag is in progress but there is no drag window handle.
03-29 14:24:15.294: I/ViewRootImpl(2496): Reporting drop result: false
03-29 14:25:06.972: I/Process(274): Sending signal. PID: 274 SIG: 3
03-29 14:25:06.972: I/dalvikvm(274): threadid=3: reacting to signal 3
03-29 14:25:07.092: I/dalvikvm(274): Wrote stack traces to '/data/anr/traces.txt'
03-29 14:25:10.012: W/ActivityManager(274): Timeout of broadcast BroadcastRecord{2c09ce28 android.intent.action.TIME_TICK} - receiver=android.app.LoadedApk$ReceiverDispatcher$InnerReceiver@2bf0c4e8, started 10009ms ago
03-29 14:25:10.012: W/ActivityManager(274): Receiver during timeout: BroadcastFilter{2bf0cd08 ReceiverList{2bf0c660 274 system/1000 local:2bf0c4e8}}
03-29 14:25:20.022: W/ActivityManager(274): Timeout of broadcast BroadcastRecord{2c09ce28 android.intent.action.TIME_TICK} - receiver=android.app.LoadedApk$ReceiverDispatcher$InnerReceiver@2bef04e8, started 10008ms ago
03-29 14:25:20.022: W/ActivityManager(274): Receiver during timeout: BroadcastFilter{2bef0760 ReceiverList{2bef06e8 274 system/1000 local:2bef04e8}}
03-29 14:25:37.092: W/Watchdog(274): WATCHDOG PROBLEM IN SYSTEM SERVER: com.android.server.wm.WindowManagerService
03-29 14:25:37.102: I/Process(274): Sending signal. PID: 274 SIG: 3
03-29 14:25:37.102: I/dalvikvm(274): threadid=3: reacting to signal 3
03-29 14:25:37.182: I/dalvikvm(274): Wrote stack traces to '/data/anr/traces.txt'
03-29 14:25:37.192: I/Process(274): Sending signal. PID: 475 SIG: 3
03-29 14:25:37.192: I/dalvikvm(475): threadid=3: reacting to signal 3
03-29 14:25:37.202: I/dalvikvm(475): Wrote stack traces to '/data/anr/traces.txt'
03-29 14:25:39.204: I/Watchdog_N(274): dumpKernelStacks
03-29 14:25:39.492: I/CrashMonitor(1186): CrashMonitorService: invokeService: android.intent.action.DROPBOX_ENTRY_ADDED
03-29 14:25:39.492: W/Watchdog(274): *** WATCHDOG KILLING THE SYSTEM: com.android.server.wm.WindowManagerService

我的适配器类(我在其中执行 view.startDrag() 方法):

public class ImageCursorAdapter extends CursorAdapter {

    private LayoutInflater mInflater;
    private final static int mImageColumnID = 0;
    private Options mOptions = new Options();;
    private Cursor mCursor;

    public ImageCursorAdapter(Context context, Cursor c) {
        super(context, c);

        mInflater = LayoutInflater.from(context);
        mOptions.inSampleSize = 4;
    }

    @Override
    public void bindView(View view, Context context, Cursor cursor) {
        mCursor = cursor;
        ViewHolder holder = (ViewHolder) view.getTag();
        ImageThumbnailLoader imageLoader = new ImageThumbnailLoader(
            holder.thumbImg, cursor.getLong(mImageColumnID),
            context.getContentResolver(), false);
        imageLoader.execute();
//      holder.thumbImg.setImageBitmap(MediaStore.Images.Thumbnails.getThumbnail(
//                  context.getContentResolver(), cursor.getLong(mColumnID),
//                  MediaStore.Images.Thumbnails.MICRO_KIND, mOptions));
        holder.dragImg.setTag(holder.thumbImg);
        holder.dragImg.setId(cursor.getPosition());
        holder.dragImg.setOnTouchListener(new OnTouchListener() {

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                int action = event.getAction();
                if (action == MotionEvent.ACTION_DOWN) {
                    mCursor.moveToPosition(v.getId());
                    int dataColumn = mCursor.getColumnIndex(MediaStore.Images.Media.DATA);
                    ClipData dragData = ClipData.newPlainText("filename",
                        mCursor.getString(dataColumn));
                    DragShadowBuilder shadow = new DragShadowBuilder((View) v.getTag());
                    return v.startDrag(dragData, shadow, null, 0);
                }
                return false;
            }
        });
        Log.i("Prototype", "bindView : " + cursor.getPosition());
    }

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {
        Log.i("Prototype", "newView : " + cursor.getPosition());
        View view = mInflater.inflate(R.layout.grid_item, null);
        ViewHolder holder = new ViewHolder(view);
        view.setTag(holder);
        return view;
    }


    private static class ViewHolder {
        ImageView thumbImg, dragImg;

        ViewHolder(View base) {
            thumbImg = (ImageView) base.findViewById(R.id.thumbImage);
            dragImg = (ImageView) base.findViewById(R.id.dragImage);
        }
    }

}

关于这里发生了什么的任何想法/线索?我真的很感激这方面的帮助。

提前致谢。

【问题讨论】:

    标签: android drag-and-drop crash android-4.0-ice-cream-sandwich


    【解决方案1】:

    如果您的 'onDrag(View v, DragEvent event)' 方法中有一个 switch case 语句,那么您应该在其中添加 case 'DragEvent.ACTION_DRAG_LOCATION'。在那里您可以定义,如果您的图标/图像放置在非拖动字段上会发生什么。

    这是一个例子:

    public class MyDragListener implements OnDragListener {
    
      @Override
      public boolean onDrag(View v, DragEvent event) {
        int action = event.getAction();
        switch ( action ) {
        case DragEvent.ACTION_DRAG_STARTED:
            break;
        case DragEvent.ACTION_DRAG_ENTERED:
            break;
        case DragEvent.ACTION_DRAG_EXITED:
            break;
        case DragEvent.ACTION_DROP:
            View view = (View) event.getLocalState();
            ViewGroup owner = (ViewGroup) view.getParent();
            owner.removeView(view);
            RelativeLayout container = (RelativeLayout) v;
            container.addView(view);
            view.setVisibility(View.VISIBLE);
            break;
        case DragEvent.ACTION_DRAG_ENDED:
                        break;
        case DragEvent.ACTION_DRAG_LOCATION:
            view.setVisibility(View.VISIBLE);
            break;
        }
      }
    
    }
    

    【讨论】:

    • 我已经在我的课堂上实现了这个,但仍然发生冻结。它并不总是发生这种情况,只有当我尝试反复拖动图标时......
    • @ImNotAnUser 你有没有想过这个问题?
    • @DJayC 不,我没有。最终实现了我自己的拖放框架。
    • @ImNotAnUser 是的,我最终做了同样的事情。你在什么设备上?我注意到我没有看到 Jelly Bean 上的崩溃,并且我能够找到对 JB 源的提交,该提交修复了拖放和输入通道的一些问题。
    【解决方案2】:

    我遇到了类似的问题,我不希望布局接受放置操作。

    通过 setOnDragListener 将拖动侦听器附加到您的视图。

    view.setOnDragListener(new MyDragListener());

    检查 onDrag 事件中的目标视图是否是您需要的视图。如果条件为假,请将您想要的代码放在那里。

    class MyDragListener implements OnDragListener {
    
    @Override
    public boolean onDrag(View v, DragEvent event) {
    
      switch (event.getAction()) {
      case case DragEvent.ACTION_DROP:
             //check whether it has not been dropped onto your view
              if(v!=view)
                  //your code here
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-10-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-17
      • 2012-06-14
      • 2015-11-22
      相关资源
      最近更新 更多