不累赘,直接上方案
这里还是说下我们主要用到的方法是ViewParent.requestDisallowInterceptTouchEvent
/**
* Called when a child does not want this parent and its ancestors to
* intercept touch events with
* {@link ViewGroup#onInterceptTouchEvent(MotionEvent)}.
*
* <p>This parent should pass this call onto its parents. This parent must obey
* this request for the duration of the touch (that is, only clear the flag
* after this parent has received an up or a cancel.</p>
*
* @param disallowIntercept True if the child does not want the parent to
* intercept touch events.
*/
public void requestDisallowInterceptTouchEvent(boolean disallowIntercept);
什么意思呢?先提供三种翻译吧,看完有个大概的了解
百度翻译:
/**
*当子级不希望此父级及其祖先
*拦截触摸事件
*{@link ViewGroup#onInterceptTouchEvent(MotionEvent)}。
*<p>此父级应将此调用传递给其父级。这个家长必须服从
*此请求的持续时间为触摸(即,只清除标志
*在这个家长收到up或cancel后</p>
*@param disallowtercept如果孩子不想让父母
*拦截触摸事件。
*/
谷歌翻译:
/ **
*当孩子不希望这个父母及其祖先去世时调用
*拦截触摸事件
* {@link ViewGroup#onInterceptTouchEvent(MotionEvent)}。
* <p>此父级应将此呼叫传递给其父级。 这位父母必须服从
*此请求在触摸期间(即,仅清除标志
*在此父母收到补办或取消订单后。</ p>
* @param disallowIntercept如果孩子不希望父母去做,则为True
*拦截触摸事件。
* /
有道翻译
/ * *
*当子程序不希望父程序和父程序被调用
用。拦截触摸事件
* {@link ViewGroup # onInterceptTouchEvent (MotionEvent)}。
这个父节点应该将这个调用传递给它的父节点。这个家长必须服从
*此请求的持续时间为触摸(即,只清除标志
*在父节点接收到up或cancel后。
* @param disallowIntercept为真,如果子线程不希望父线程为真
拦截触摸事件。
* /
我总结翻译一下:
当子类不想其父类和基类调用onInterceptTouchEvent 方法
这个父类应该传递到它的父类,这父类必须在触摸的这段时间里遵循这个请求
(即,在这个父类收到up或cancel之后,清除标记)
(这个请求指 父类不调用onInterceptTouchEvent方法)
方法一
自定义EditText ,然后重写onTouchEvent,然后正常使用即可
package com.mm.michat.collect.widget;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.EditText;
/**
* Created by cgg on 2020/7/17.
* 用于解决嵌套Scrollview的时候由于多行而产生的滑动冲突问题
*/
public class EditTextWithScrollView extends EditText {
public EditTextWithScrollView(Context context) {
super(context);
}
public EditTextWithScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public EditTextWithScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
//通知父控件不要干扰
getParent().requestDisallowInterceptTouchEvent(true);
} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
//通知父控件不要干扰
getParent().requestDisallowInterceptTouchEvent(true);
} else if (event.getAction() == MotionEvent.ACTION_UP) {
}
return super.onTouchEvent(event);
}
}
方法二
在代码里重写onTouch方法,然后添加了一个滑动判断
editText.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent event) {
//触摸的是EditText并且当前EditText可以滚动则将事件交给EditText处理;否则将事件交由其父类处理
if ((view.getId() == R.id.et_title && canVerticalScroll(editText))) {
view.getParent().requestDisallowInterceptTouchEvent(true);
if (event.getAction() == MotionEvent.ACTION_UP) {
view.getParent().requestDisallowInterceptTouchEvent(false);
}
}
return false;
}
});
private boolean canVerticalScroll(EditText editText) {
//滚动的距离
int scrollY = editText.getScrollY();
//控件内容的总高度
int scrollRange = editText.getLayout().getHeight();
//控件实际显示的高度
int scrollExtent = editText.getHeight() - editText.getCompoundPaddingTop() - editText.getCompoundPaddingBottom();
//控件内容总高度与实际显示高度的差值
int scrollDifference = scrollRange - scrollExtent;
if (scrollDifference == 0) {
return false;
}
return (scrollY > 0) || (scrollY < scrollDifference - 1);
}
效果图: