Android/kindle偶尔会下降

Len*_*nny 5 android drag-and-drop relativelayout imageview kindle-fire

我不确定这是设备问题还是我的代码问题,但我使用相对布局和图像视图创建了一个简单的可拖动可排序列表.我有非常具体的理由这样做,这不是我的问题.

我遇到的问题偶尔会完全冻结我的应用程序.该项目将陷入拖动状态.如果我抬起手指,阴影(拖动)对象仍然在屏幕上,如果我触摸屏幕,它将移动到那个位置.这将持续大约一分钟,然后我会收到一个错误,说应用程序没有响应,可以选择杀死它或等待.logcat中唯一有用的位如下:

12-09 14:23:13.157: W/WindowManager(16415): Drag is in progress but there is no drag window handle.
Run Code Online (Sandbox Code Playgroud)

然后,当应用程序超时时,我将此视为错误

12-09 14:59:09.782: E/ActivityManager(16415): ANR in com.appname.appname (com.appname.appname/.MainActivity)
12-09 14:59:09.782: E/ActivityManager(16415): Reason: keyDispatchingTimedOut
Run Code Online (Sandbox Code Playgroud)

我搜索了这个错误消息,唯一的信息是没有拖拽监听器的人和另一个人说这是设备触摸传感器无法跟上.

理想情况下,我喜欢修复此错误并防止它首先发生.如果我快速拖动它似乎确实发生了,但我不能很好地要求我的用户不要快速拖动......对吧?

或者,是否有一种方法可以检测到拖动已冻结应用程序并中断拖动.就像在触摸监听器上设置一个计时器一样,如果在一两秒内没有drag_location消息中断拖动?计时器的东西,我知道该怎么做,但我不知道如何阻止阻力在它被冻结时停止.有任何想法吗?

这是代码:

建立

//happens once when the app loads
RelativeLayout trackList = (RelativeLayout) findViewById(R.id.nsTrackList1);    
trackList.setOnDragListener(new MyTrackDragListener(this));

//happens in a loop for each "track" (image view)
trackButton = new ImageView(this);
trackButton.setImageDrawable(nsPackages[trackId].banner[bannerSizeSelector]);
trackButton.setOnTouchListener(new MyTrackTouchListener());
Run Code Online (Sandbox Code Playgroud)

在触摸

public class MyTrackTouchListener implements OnTouchListener {
    boolean isDragging=false;
    float prevX, prevY;
    public boolean onTouch(View view, MotionEvent motionEvent) {
        if(motionEvent.getPointerCount() < 2 && !isDragging) return false;
        if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
            isDragging=false;
            prevX=0;
            prevY=0;
            return true;
        } else if (motionEvent.getAction() == MotionEvent.ACTION_MOVE) {
            if(isDragging) return true;
            boolean wasFirst = (prevX == 0 || prevY == 0);
            float theTotalDiff = Math.abs(prevX - motionEvent.getX()) + Math.abs(prevY - motionEvent.getY());
            prevX=motionEvent.getX();
            prevY=motionEvent.getY();
            if(wasFirst) return true;
            if(theTotalDiff <3) return true;
            ClipData data = ClipData.newPlainText("", "");
            DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(view);

            view.startDrag(data, shadowBuilder, view, 0);
            int thisViewId = view.getId();
            //hide view
            view.setVisibility(View.GONE);

            isDragging=true;    
            return true;
        } else if (motionEvent.getAction() == MotionEvent.ACTION_UP || motionEvent.getAction() == MotionEvent.ACTION_CANCEL) {
            isDragging=false;
            return true;
        }else {

            Integer thisAction = motionEvent.getAction();
            Log.d("looper","Motion action: "+thisAction.toString());
            return false;
        }
    }
} 
Run Code Online (Sandbox Code Playgroud)

在拖动

class MyTrackDragListener implements OnDragListener {
    public static boolean isDragging=false;
private MainActivity parent;

public MyTrackDragListener(MainActivity myAct){
    parent=myAct;
}       
    @Override
    public boolean onDrag(View v, DragEvent event) {
        int action = event.getAction();
        switch (event.getAction()) {
        case DragEvent.ACTION_DRAG_STARTED:
            isDragging=true;
            // do nothing
            return true;
        case DragEvent.ACTION_DROP:
            View view = (View) event.getLocalState();
            parent.doDropSort(view,(int) event.getY());
            return true;
        case DragEvent.ACTION_DRAG_ENDED:
            if(isDragging && event.getResult()==false){
                View view2 = (View) event.getLocalState();
                parent.doDropSort(view2,(int) event.getY(),true);
                return true;
            }
            isDragging=false;
            break;
        case DragEvent.ACTION_DRAG_LOCATION:
            parent.doDragHover((int) event.getY());
            return true;
        default:
            Log.d("looper","drag other... "+String.valueOf(event.getAction()));
        }
        return false;
    }
}
Run Code Online (Sandbox Code Playgroud)

我已经尝试过的一些事情

  • 完全删除拖动侦听器
  • 始终从onDrag返回true
  • 始终从onDrag返回false
  • 基本上每个组合都会在拖动和触摸时返回true/false
  • 取而代之的是移除2个手指和Action_Move部件并触发对Action_down的拖动

结果相同.拖放在大约70%的时间内完美地工作,然后突然完成上述的冻结行为.有时它会在第一次拖动时有时会在几次之后.除了可能的拖动速度之外,我注意到了一致的模式.当我快速拖动时似乎通常会发生,但拖动方向或拖动到哪里似乎并不重要.

Len*_*nny 2

耶!我想到了。这是答案,以防它对将来的某人有所帮助。

我最终将其范围缩小到只有顶部列表项(不知道我是如何错过的),然后开始注释行,直到它没有中断,从而将范围缩小到这一行:

view.setVisibility(View.GONE);
Run Code Online (Sandbox Code Playgroud)

我的列表的设置方式是在相对布局中使用下面的布局属性(顶部项目除外)。一旦我从视图中删除了顶部项目,第二个顶部项目就位于可见性消失的项目下方,因此它不知道该怎么做。解决方案是设置视图中下一项的参数。幸运的是,我手动设置了轨道按钮的视图 ID(还有其他滚动的视图......标签等),因此它们是连续的。所以我的解决办法就是简单地找到 id+1 的项目,并通过将下面设置为零来使其成为顶部项目,如下所示......

// the top item in my list is ALWAYS view id 1
if(thisViewId == 1){
    ImageView nextTrackButton = (ImageView) trackList.findViewById(thisViewId+1);
    LayoutParams ntLP = (LayoutParams) nextTrackButton.getLayoutParams();
    ntLP.addRule(RelativeLayout.BELOW,0);
    nextTrackButton.setLayoutParams(ntLP);
}           

//hide view
view.setVisibility(View.GONE);
Run Code Online (Sandbox Code Playgroud)