2013-12-09 17 views
5

Tôi không chắc đây có phải là vấn đề về thiết bị hay không, nhưng tôi đã tạo một danh sách có thể kéo có thể kéo bằng cách sử dụng bố cục tương đối và chế độ xem hình ảnh. Tôi có những lý do rất cụ thể để thực hiện nó theo cách này và đó không phải là câu hỏi của tôi.Android/kindle drag drop freezing thỉnh thoảng

Sự cố tôi gặp phải đôi khi nó sẽ đóng băng hoàn toàn ứng dụng của tôi. Mục sẽ bị kẹt trong trạng thái kéo. Nếu tôi nhấc ngón tay của mình, đối tượng bóng (kéo) vẫn còn trên màn hình và nếu tôi chạm vào màn hình nó sẽ di chuyển đến vị trí đó. Điều này sẽ tiếp tục trong khoảng một phút và sau đó tôi sẽ nhận được thông báo lỗi cho biết ứng dụng không phản hồi với tùy chọn giết hoặc chờ. Bit chỉ có ích trong logcat là như sau:

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

Sau đó, khi lần ứng dụng ra tôi có được điều này là một lỗi

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 

Tôi googled thông báo lỗi này và các thông tin chỉ là một ai đó không có kéo người nghe và một người khác nói đó là cảm biến thiết bị cảm ứng không theo kịp.

Lý tưởng nhất, tôi rất muốn khắc phục lỗi này và ngăn điều đó xảy ra ngay từ đầu. Nó dường như xảy ra chủ yếu nếu tôi kéo nhanh, nhưng tôi không thể yêu cầu người dùng của tôi không kéo nhanh ... đúng không?

Cách khác, có cách nào để tôi có thể phát hiện rằng việc kéo đã làm đóng ứng dụng và làm gián đoạn quá trình kéo. Giống như thiết lập một bộ đếm thời gian trên người nghe cảm ứng và nếu không có tin nhắn drag_location trong vòng một hoặc hai lần gián đoạn kéo? Công cụ hẹn giờ tôi biết cách làm, nhưng tôi không biết làm thế nào tôi sẽ buộc kéo để dừng lại trong khi nó bị đóng băng. Bất kỳ ý tưởng?

Dưới đây là các mã:

thiết lập

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

Mở liên lạc

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

On Kéo

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

Một vài điều tôi đã cố gắng

  • Loại bỏ người nghe kéo hoàn toàn
  • Luôn luôn trả về true từ onDrag
  • Luôn luôn trả về false từ onDrag
  • Về cơ bản tất cả các kết hợp của sự trở lại đúng/sai trong kéo và chạm vào
  • Xóa phần 2 ngón tay và Action_Move và kích hoạt thao tác kéo trên Action_down thay vì

Kết quả tương tự. Kéo và thả hoạt động hoàn hảo khoảng 70% thời gian và sau đó đột nhiên thực hiện hành vi đóng băng được mô tả ở trên. Đôi khi nó là lần đầu tiên kéo nó đôi khi nó sau vài. Tôi đã nhận thấy trên mẫu nhất quán ngoại trừ có thể là tốc độ kéo. Dường như thường xảy ra khi tôi kéo nhanh, nhưng kéo hướng hoặc nơi tôi kéo đến dường như không quan trọng.

+0

Là một cựu nhân viên Amazon và nhà phát triển Kindle, tôi sẽ xem bạn có thể làm cho nó liên tục repro với một ứng dụng thử nghiệm nhỏ và sau đó gửi một báo cáo lỗi. –

+0

@CarlAnderson Cảm ơn, tôi đã thử nghiệm thủ công một vài ngày và tôi không thể thấy bất kỳ mẫu nào. Bạn có lời khuyên nào về cách xây dựng một ứng dụng thử nghiệm cho loại hành vi này không? Có cách nào để mô phỏng đầu vào cảm ứng/kéo-thả không? – Lenny

+0

Không có gì tôi biết, và thật không may nếu bạn không thể làm cho nó liên tục repro họ có lẽ sẽ không nhìn vào nó. –

Trả lời

2

YAY! Tôi đã hiểu rồi.Đây là câu trả lời trong trường hợp nó giúp ai đó trong tương lai.

cuối cùng tôi đã thu hẹp nó xuống để chỉ mục danh sách hàng đầu (không biết làm thế nào tôi bị mất đó) và sau đó bắt đầu cho ý kiến ​​ra đường cho đến khi nó không phá vỡ mà thu hẹp nó xuống dòng này:

view.setVisibility(View.GONE); 

Cách danh sách của tôi được thiết lập mỗi mục được sử dụng Thuộc tính bố cục DƯỚI ĐÂY trong bố cục tương đối (ngoại trừ mục trên cùng). Khi tôi đã xóa mục trên cùng khỏi chế độ xem, mục thứ 2 đến trên cùng bên dưới một mục có khả năng hiển thị GONE nên nó không biết phải làm gì. Giải pháp là đặt tham số của mục tiếp theo trong dạng xem. May mắn là tôi đặt ID chế độ xem của các nút theo dõi theo cách thủ công (có các chế độ xem khác cuộn quá .. nhãn và như vậy) để chúng được tuần tự. Vì vậy, sửa chữa của tôi đã được chỉ đơn giản là tìm kiếm các mục với id + 1 và làm cho nó trở thành mục hàng đầu bằng cách thiết lập DƯỚI 0 như thế này ...

// 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); 
Các vấn đề liên quan