我不确定这是设备问题还是我的代码问题,但我使用相对布局和图像视图创建了一个简单的可拖动可排序列表.我有非常具体的理由这样做,这不是我的问题.
我遇到的问题偶尔会完全冻结我的应用程序.该项目将陷入拖动状态.如果我抬起手指,阴影(拖动)对象仍然在屏幕上,如果我触摸屏幕,它将移动到那个位置.这将持续大约一分钟,然后我会收到一个错误,说应用程序没有响应,可以选择杀死它或等待.logcat中唯一有用的位如下:
12-09 14:23:13.157: W/WindowManager(16415): Drag is in progress but there is no drag window handle.
然后,当应用程序超时时,我将此视为错误
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
我搜索了这个错误消息,唯一的信息是没有拖拽监听器的人和另一个人说这是设备触摸传感器无法跟上.
理想情况下,我喜欢修复此错误并防止它首先发生.如果我快速拖动它似乎确实发生了,但我不能很好地要求我的用户不要快速拖动......对吧?
或者,是否有一种方法可以检测到拖动已冻结应用程序并中断拖动.就像在触摸监听器上设置一个计时器一样,如果在一两秒内没有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());
在触摸
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; } } }
在拖动
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; } }
我已经尝试过的一些事情
完全删除拖动侦听器
始终从onDrag返回true
始终从onDrag返回false
基本上每个组合都会在拖动和触摸时返回true/false
取而代之的是移除2个手指和Action_Move部件并触发对Action_down的拖动
结果相同.拖放在大约70%的时间内完美地工作,然后突然完成上述的冻结行为.有时它会在第一次拖动时有时会在几次之后.除了可能的拖动速度之外,我注意到了一致的模式.当我快速拖动时似乎通常会发生,但拖动方向或拖动到哪里似乎并不重要.