0

I'v got a Button inside a ScrollView.

<ScrollView>
    <LinearLayout>
        ...
        <Button/>
        ...
    <LinearLayout/>
</ScrollView>

I'm using this button for recoding voice. When it catches MotionEvent.ACTION_DOWN event, I start recording, and on MotionEvent.ACTION_UP event I stop it.

buttomRecord.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if(event.getAction() == MotionEvent.ACTION_DOWN){
            startRecording();
            return true;
        }
        else if(event.getAction() == MotionEvent.ACTION_UP){
            stopRecording();
            return true;
        }
        return false;
    }
});

The problem is when user is recording voice, if this ScrollView scrolls down or up, this button will loose focus and will never catch MotionEvent.ACTION_UP event.

How can I lock focus on Button while I'm holding it or disable ScrollView scrolling?

netpork
  • 552
  • 7
  • 20
Saman Salehi
  • 1,995
  • 1
  • 22
  • 36

2 Answers2

7

You can use

mScrollView.requestDisallowInterceptTouchEvent(true);

to disallow touch event of scrollview

So your code will be

    buttomRecord.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if(event.getAction() == MotionEvent.ACTION_DOWN){
            startRecording();
            mScrollView.requestDisallowInterceptTouchEvent(true);
            return true;
        }
        else if(event.getAction() == MotionEvent.ACTION_UP){
            stopRecording();
            mScrollView.requestDisallowInterceptTouchEvent(false);
            return true;
        }
        return false;
    }
});
Paresh P.
  • 6,677
  • 1
  • 14
  • 26
0

Use this custom scroll view:

public class CustomScrollView extends ScrollView {

private boolean mScrollable = true;

public void setScrollingEnabled(boolean enabled) {
    mScrollable = enabled;
}

public boolean isScrollable() {
    return mScrollable;
}

public CustomScrollView(Context context) {
    super(context);
}

@Override
public boolean onTouchEvent(MotionEvent ev) {
    switch (ev.getAction()) {
        case MotionEvent.ACTION_DOWN:
            // if we can scroll pass the event to the superclass
            if (mScrollable) return super.onTouchEvent(ev);
            // only continue to handle the touch event if scrolling enabled
            return mScrollable; // mScrollable is always false at this point
        default:
            return super.onTouchEvent(ev);
    }
}

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    // Don't do anything with intercepted touch events if
    // we are not scrollable
    if (!mScrollable) return false;
    else return super.onInterceptTouchEvent(ev);
}}

And then in your xml:

<your.package.name.CustomScrollView
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            Android: scrollbars="vertical">
   <!--whatever widgets you want to add-->
</your.package.name.CustomScrollView>

In your activity:

buttomRecord.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if(event.getAction() == MotionEvent.ACTION_DOWN){
            scrollView.setScrollingEnabled(false);
            startRecording();
            return true;
        }
        else if(event.getAction() == MotionEvent.ACTION_UP){
            stopRecording();
            return true;
        }
        return false;
    }
});
Kaustubh Kadam
  • 182
  • 3
  • 13
  • It's not a good solution while there is a just-one-line-code solution... See the correct answer... thanks anyway ;) – Saman Salehi Mar 08 '17 at 06:19