我有一个ListView,其中包含一个签名捕获控件。当用户触摸签名捕获控件时,我需要阻止ListView滚动 - 现在发生的是捕获控件上的水平笔划工作,但是垂直笔划绘制一条小线然后开始滚动ListView。 p>
我无法找到一种简单的方法来打开和关闭ListView滚动。 StackOverflow上有一些例子,但是很少有人接受了答案,我尝试了许多看起来很有希望而没有成功的解决方案。我觉得可能有一种方法可以告诉签名捕获组件拦截触摸事件而不是将它们传递到事件链中,但我不知道那是什么。
我的签名捕获是稍微修改过的版本:http://www.mysamplecode.com/2011/11/android-capture-signature-using-canvas.html
功能代码完全相同。
有关问题的SS,请参阅http://imgur.com/WbfgTkj。绿色突出显示的区域是签名捕获区域。请注意,它位于列表视图的底部,必须滚动才能到达它。
答案 0 :(得分:2)
好吧,我明白了;我想对于那个偶然发现这个问题的人来说,留下一个答案是公平的。我事先向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)告诉它停止滚动listview并将所有ACTION_MOVE事件分派给特定的View。然后,您可以调用ResetToNormalListViewBehavior()使其再次开始滚动。使用我原始帖子中链接的签名捕获代码,您需要做的就是在onTouchEvent中更改以下内容:
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
...
listView.SetUpDispatch(this);
return true;
case MotionEvent.ACTION_UP:
listView.ResetToNormalListViewBehavior();
case MotionEvent.ACTION_MOVE:
...
不确定是否有人会遇到这个问题,但它似乎有一些一般的应用程序,所以如果你读过这个就好运。
答案 1 :(得分:0)
在ListView Capture Signature Class上试试这个:
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
}