3

目的

我已经按照 Android 3.0 拖放框架实现了“从 ListView 重新排序项目”范例。

问题

在 android 4.0.3 和 4.0.4 上看到。未在其他版本上测试。

将 ListView 的一项拖放到 ListView 的最后一项之后。阴影框被清除并且 ListView 无效。这是名义上的行为,90% 的时间都会发生。

但对于剩下的 10%,会发生什么:

  • 注意:下面列出的所有效果都是AFTER onDrag(View, DragEvent)has returned for ACTION_DRAG_ENDED,也就是说整个拖放过程似乎在问题发生之前就完成了。
  • 阴影框在消失前仅显示 10 秒。调用处理程序将纠正view.invalidate()该问题,但不会解决挂起或重启问题(见下文)onDrag(View, DragEvent)ACTION_DRAG_ENDED
  • logcat 中的一些不寻常的痕迹:

I/ViewRootImpl(954):报告丢弃结果:真 I/InputQueue-JNI(210):为输入通道“拖动(客户端)”发送完成信号,因为它在输入消息仍在进行中时被取消注册。I/InputQueue-JNI(210):忽略不再注册的通道上的完成信号。W/WindowManager(210):正在拖动,但没有拖动窗口句柄。I/ViewRootImpl(954): 报告丢弃结果: true

  • 在某些设备上,Android 挂起或重新启动。这取决于设备,但效果始终相同。

源代码

import android.annotation.SuppressLint;
import android.app.ListActivity;
import android.content.ClipData;
import android.content.ClipDescription;
import android.os.Bundle;
import android.view.DragEvent;
import android.view.View;
import android.view.View.DragShadowBuilder;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;

public class TestReorderActivity extends ListActivity {

    @SuppressLint("NewApi")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        ListView listView = getListView();
        String[] listeStrings = { "France", "United States", "Russia" };
        listView.setAdapter(new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_1, listeStrings));

        listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {

            @Override
            public boolean onItemLongClick(AdapterView<?> adapter, View view,
                    int id, long position) {
                ClipData data = ClipData.newPlainText(" ",
                        Long.toString(position));

                DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(
                        view);
                if (view.startDrag(data, shadowBuilder/*
                                                     * new
                                                     * MyDragShadowBuilder(view)
                                                     */, view, 0)) {
                    return true;
                }

                return false;
            }

        });

        listView.setOnDragListener(new ListView.OnDragListener() {

            @Override
            public boolean onDrag(View view, DragEvent event) {
                final int action = event.getAction();

                switch (action) {
                case DragEvent.ACTION_DRAG_STARTED:

                    if (event.getClipDescription().hasMimeType(
                            ClipDescription.MIMETYPE_TEXT_PLAIN)) {
                        // accept drag
                        return true;
                    } else {
                        // reject drag
                        return false;
                    }

                case DragEvent.ACTION_DRAG_ENTERED:
                    // entered drag
                    return true;

                case DragEvent.ACTION_DRAG_LOCATION:
                    // location is returned as event.getX() and event.getY()
                    return true;

                case DragEvent.ACTION_DRAG_EXITED:
                    // cancel drag.
                    return true;

                case DragEvent.ACTION_DROP:
                    // item dropped
                    processDrop(event);
                    return true;

                case DragEvent.ACTION_DRAG_ENDED:
                default: // unknown case
                    return true;
                }
            }

            private boolean processDrop(DragEvent event) {
                ClipData data = event.getClipData();
                if ((data != null) && (data.getItemCount() > 0)) {
                    ClipData.Item item = data.getItemAt(0);
                    CharSequence value = item.getText();
                    long position = Long.valueOf(value.toString());

                    int x = (int) event.getX();
                    int y = (int) event.getY();

                    ListView listView = getListView();

                    int newPosition = listView.pointToPosition(x, y);
                    if (newPosition > ListView.INVALID_POSITION) {

                        swap(position, newPosition);
                        return true;
                    }
                }

                return false;
            }

        });

    }

    // swap(long, long) here
}
4

2 回答 2

0

原因是:你的屏幕上传action_move太懒了。

在正常情况下,即使您的手指不在屏幕上移动,动作动作也会非常频繁地上传。但有些手机屏幕不是那么敏感。

您可以修改手机的阈值。它需要内核支持。

于 2013-03-19T10:19:23.533 回答
0

这是因为:unregisterInputChannel 获取锁失败,发生死锁。

于 2013-03-21T09:24:02.160 回答