2011-05-16 35 views
20

Tôi có lớp sau đại diện cho Chế độ xem có thể chạm và vẽ Thanh trượt.ACTION_CANCEL khi chạm vào

public class SlideBar extends View { 
private int progress; 
private int max; 

private Paint background; 
private Paint upground; 

private RectF bar; 

private boolean firstDraw; 

public SlideBar(Context context, AttributeSet attrs) { 
    super(context, attrs); 
    progress = 0; 

    upground = new Paint(); 
    upground.setColor(Color.parseColor("#C2296C")); 

    background = new Paint(); 
    background.setColor(Color.parseColor("#777777")); 
} 

private void onFirstDraw() { 
    max = getWidth(); 
    bar = new RectF(0, 19, max, 21); 
} 

public void onDraw(Canvas canvas) { 
    if (!firstDraw) { 
     onFirstDraw(); 
     progress = max; 
     firstDraw = true; 
    } 

    canvas.save(); 
    canvas.drawRoundRect(bar, 5, 5, background); 
    canvas.drawCircle(progress, 20, 9, upground); 
    canvas.restore(); 
} 

public void setValue(int value) { 
    progress = value; 
} 

public boolean onTouchEvent(MotionEvent evt) { 
    System.out.println(evt.getAction()); 
    progress = (int) evt.getX(); 
    invalidate(); 
    return false; 
} 
} 

Nhưng khi chạm và kéo nó, tôi nhận được ACTION_DOWN, một số ACTION_MOVE sau đó nhận được ACTION_CANCEL và không có sự kiện nào khác.

Tại sao điều đó xảy ra? Tôi không muốn hủy sự kiện và cho phép nó tiếp tục kéo thanh.

Trả lời

21

An ACTION_CANCEL xảy ra khi chế độ xem cha mẹ kiểm soát một trong các chế độ xem con của nó.

Hãy xem tài liệu theo phương pháp ViewGroup.onInterceptTouchEvent(MotionEvent). Từ liên kết:

  1. Bạn sẽ nhận được sự kiện xuống tại đây.
  2. Sự kiện xuống sẽ được xử lý bởi con của nhóm lượt xem này hoặc được cung cấp cho phương thức onTouchEvent() của riêng bạn để xử lý; điều này có nghĩa là bạn nên triển khai onTouchEvent() để trả về true, vì vậy bạn sẽ tiếp tục thấy phần còn lại của cử chỉ (thay vì tìm kiếm chế độ xem gốc để xử lý). Ngoài ra, bằng cách trả về true từ onTouchEvent(), bạn sẽ không nhận được bất kỳ sự kiện nào sau đây trong onInterceptTouchEvent() và tất cả xử lý chạm phải xảy ra trong onTouchEvent() như bình thường.
  3. Miễn là bạn trả về false từ chức năng này, mỗi sự kiện sau (lên đến và bao gồm cả trận chung kết) sẽ được gửi đầu tiên tại đây và sau đó đến mục tiêu onTouchEvent() của mục tiêu.
  4. Nếu bạn quay trở lại từ đây, bạn sẽ không nhận được bất kỳ sự kiện nào sau đây: chế độ xem mục tiêu sẽ nhận được cùng một sự kiện nhưng với hành động ACTION_CANCEL và tất cả sự kiện tiếp theo sẽ được gửi đến phương thức onTouchEvent() của bạn và không còn xuất hiện tại đây
+0

tôi nhận ra rằng điều này chỉ xảy ra khi thêm thành phần này vào một PopupWindow, làm thế nào tôi có thể đánh chặn các sự kiện và làm cho tất cả chúng đi đến con của nó? –

+2

Tôi nhận ra đó là một HorizontalScrollView đang nắm lấy các sự kiện của tôi. –

+1

https://www.youtube.com/watch?v=EZAoJU-nUyI điều này có thể hữu ích – kouretinho

41

Điều này sẽ xảy ra khi vùng chứa chính sẽ chặn sự kiện chạm của bạn. Bất kỳ ViewGroup nào ghi đè ViewGroup.onInterceptTouchEvent(MotionEvent) cũng có thể thực hiện điều đó (ví dụ như ScrollView hoặc ListView).

Cách thích hợp để giải quyết vấn đề này là gọi phương thức ViewParent.requestDisallowInterceptTouchEvent(boolean) trên chế độ xem cha mẹ của bạn khi bạn cho rằng mình cần giữ sự kiện chuyển động.

Dưới đây là một ví dụ nhanh (phương pháp attemptClaimDrag được lấy từ mã nguồn Android):

/** 
* Tries to claim the user's drag motion, and requests disallowing any 
* ancestors from stealing events in the drag. 
*/ 
private void attemptClaimDrag() { 
    //mParent = getParent(); 
    if (mParent != null) { 
     mParent.requestDisallowInterceptTouchEvent(true); 
    } 
} 

@Override 
public boolean onTouchEvent(MotionEvent event) { 
    if (event.getAction() == MotionEvent.ACTION_DOWN) { 
     if (iWantToKeepThisEventForMyself(event)) { 
      attemptClaimDrag(); 
     } 
     //your logic here 
    } else { 
     //your logic here 
    } 
} 
+3

Điều này làm việc cho tôi khi tôi có một ViewPager với nội dung có thể vuốt được. Nội dung không nhận được swipes ngang vì chúng bị chặn bởi ViewPager. Tôi chỉ đơn giản là thông qua một tham chiếu đến ViewPager vào khung nhìn con, và bây giờ đứa trẻ gọi mParent.requestDisallowInterceptTouchEvent (true) cho tất cả các sự kiện ACTION_DOWN. – OldSchool4664

+0

Nếu bạn đang sử dụng ViewPager, có lẽ bạn nên sử dụng ViewPager # canScroll (android.view.View, boolean, int, int, int). Phương pháp được bảo vệ này của ViewPager được thực hiện cụ thể để xác định bất cứ khi nào ViewPager sẽ cuộn nội dung của một trang hoặc chuyển sang trang tiếp theo. – Alexey

+0

cảm ơn bạn rất nhiều nó đang làm việc –

Các vấn đề liên quan