2014-04-09 95 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 
}