2014-04-09 96 views
1

我有一個ListView,它有一個簽名捕獲控件。當用戶觸摸簽名捕獲控件時,我需要防止ListView滾動 - 現在發生的情況是捕獲控件上的水平筆劃工作,但垂直筆劃繪製一條小線,然後開始滾動ListView。Android:打開和關閉ListView滾動

我找不到一個簡單的方法來打開和關閉ListView滾動。在StackOverflow上有一些例子,但很少有人接受答案,並且我已經嘗試了許多看起來很有前途而沒有成功的解決方案。我覺得可能有辦法告訴簽名捕獲組件攔截觸摸事件,而不是將它們進一步傳遞給事件鏈,但我不知道那是什麼。

我的簽名採集是一個發現這裏的一個稍微修改後的版本:http://www.mysamplecode.com/2011/11/android-capture-signature-using-canvas.html

功能的代碼都是一樣的。

請參閱http://imgur.com/WbfgTkj瞭解問題的SS。以綠色突出顯示的區域是簽名捕獲區域。請注意,它位於列表視圖的底部,必須滾動才能觸及它。

回答

1

我想通了;我想爲下一個絆倒在這個問題上的人留下一個答案是公平的。我事先向Java純粹主義者道歉,我寫了像C#這樣的Java。我也很喜歡在我去的時候搞清楚這個Android的東西。

解決方案是創建一個自定義ListView。其中的神奇之處在於它可以選擇是否打開和關閉觸摸事件分派(特別是ACTION_MOVE,它是滾動的)。代碼如下:

public class UnScrollingListView extends ListView { 

public UnScrollingListView(Context context, AttributeSet attrs, int defStyle) {  super(context, attrs, defStyle); } 
public UnScrollingListView(Context context, AttributeSet attrs)     {  super(context, attrs);    } 
public UnScrollingListView(Context context)          {  super(context);      } 

public boolean DisableTouchEventScroll = false; 

protected boolean DispatchMoveEventInsteadOfConsumingIt = false; 
protected View DispatchTarget = null; 

public void ResetToNormalListViewBehavior() { 
    DisableTouchEventScroll = false; 
    DispatchMoveEventInsteadOfConsumingIt = false; 
    DispatchTarget = null; 
} 

public void SetUpDispatch(View v) { 
    DisableTouchEventScroll = true; 
    DispatchMoveEventInsteadOfConsumingIt = true; 
    DispatchTarget = v; 
} 

protected static float[] GetRelativeCoordinates(View innerView, MotionEvent e) { 
    int[] screenCoords = new int [2];  //not sure if I have to preallocate this or not. 
    innerView.getLocationOnScreen(screenCoords); 
    return new float[] { 
     e.getRawX() - screenCoords[0], 
     e.getRawY() - screenCoords[1]}; 
} 

@Override 
public boolean dispatchTouchEvent(MotionEvent ev){ 
    if(DispatchMoveEventInsteadOfConsumingIt && DispatchTarget != null) { 
     //convert coordinate systems 
     float[] newCoords = GetRelativeCoordinates(DispatchTarget, ev); 
     ev.setLocation(newCoords[0], newCoords[1]); 

     DispatchTarget.onTouchEvent(ev); 
     return true; 
    } 

    if(DisableTouchEventScroll && ev.getAction() == MotionEvent.ACTION_MOVE) { 
     return true; 
    } 

    return super.dispatchTouchEvent(ev); 
} 
} 

默認情況下,它的行爲與普通列表視圖相似。您可以調用SetUpDispatch(View)來告訴它停止滾動列表視圖並將所有ACTION_MOVE事件分派給特定的視圖。然後,您可以調用ResetToNormalListViewBehavior()使其重新開始滾動。在我原來的職位掛鉤的簽名捕捉代碼,所有你需要做的是改變了的onTouchEvent如下:

switch (event.getAction()) 
{ 
    case MotionEvent.ACTION_DOWN: 
     ... 
     listView.SetUpDispatch(this); 
     return true; 

    case MotionEvent.ACTION_UP: 
     listView.ResetToNormalListViewBehavior(); 

    case MotionEvent.ACTION_MOVE: 
     ... 

不知道會不會有人曾經遇到這樣的問題,但它似乎有一些一般的應用,如果你讀過這個,祝你好運。

0

試試這個在您的ListView捕獲Signature類:

public boolean onTouchEvent(MotionEvent e) { 
    super.onTouchEvent(e); 

    ViewParent v = this.getParent(); 
    while (v != null){ 
     if(v instanceof ScrollView || v instanceof HorizontalScrollView){ 
      FrameLayout f = (FrameLayout)v; 
      f.requestDisallowInterceptTouchEvent(true); 
     } 
     v = v.getParent(); 
    } 
    //... rest of the code 
}