Android: Turn ListView Scrolling on and off

北城以北 提交于 2019-12-11 10:03:59

问题


I have a ListView that has a signature capture control in it. When the user touches down on the signature capture control I need to prevent the ListView from scrolling -- what happens now is that horizontal strokes on the capture control work, but vertical strokes draw a small line and then start the scroll the ListView.

I cannot find an easy way to turn ListView scrolling on and off. There are some examples on StackOverflow, but few have accepted answers, and I've tried many of the solutions that looked promising without success. I feel like there is probably a way to tell the signature capture component to intercept the touch events and not pass them further up the event chain, but I don't know what that is.

My signature capture is a slightly modified version of the one found here: http://www.mysamplecode.com/2011/11/android-capture-signature-using-canvas.html

The functional code is all the same.

See http://imgur.com/WbfgTkj for a SS of the issue. The area highlighted in green is the signature capture area. Note that it is at the bottom of the listview and must be scrolled to reach it.


回答1:


Well I figured it out; I guess it's only fair to leave an answer behind for the next guy who stumbles onto this question. I apologize in advance to Java purists, I write Java like C#. I'm also kind of figuring out this Android thing as I go.

The solution was to create a custom ListView. The magic in it is that it has the option to turn touch-event dispatching (specifically ACTION_MOVE, which is the one that does scrolling) on and off. Here's the code:

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

This behaves like a normal listview by default. You can call SetUpDispatch(View) to tell it to stop scrolling the listview and dispatch all ACTION_MOVE events to a specific View. You can then call ResetToNormalListViewBehavior() to make it start scrolling again. With the signature capture code linked in my original post, all you need to do is change the following in the onTouchEvent:

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

    case MotionEvent.ACTION_UP:
        listView.ResetToNormalListViewBehavior();

    case MotionEvent.ACTION_MOVE:
        ...

Not sure if anyone will ever encounter this problem, but it seems to have some general applications, so good luck with it if you ever read this.




回答2:


Try this on your 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
}


来源:https://stackoverflow.com/questions/22970331/android-turn-listview-scrolling-on-and-off

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!