美文网首页Android面试
真正完美解决EditText嵌套ScrollView的滑动冲突

真正完美解决EditText嵌套ScrollView的滑动冲突

作者: 我喂自己袋丶夏洛克 | 来源:发表于2017-08-17 16:57 被阅读1129次

    最近项目有需要 用到 edittext 嵌套在 srolllview的情况,由于edittext 如果多行的情况下,是可以上下滑动的,但是由于嵌套了scrollview,所以会产生滑动冲突,所以我随手网上一搜解决方案,不出所料,很多解决方案。

    微笑微笑 然后当我应用于项目中,实际测试了一下,发现并不完美。

    网上的方案是,直接将滑动事件交由edittex处理,但是这种方案并不完美,因为只有滑动edittext区域外的地方才能滑动ScrollView,这样如果你的edittext的高度很大,甚至占满了一个屏幕,那么很抱歉,因为点不到edittext区域外的地方了,所以Scrollview就不能再滑动了,是不是很坑爹。


    微笑微笑

    我们的需求是当edittext是多行需要上下滑动的时候,将滑动事件交给edittetx,并且 edittext滑动到底部或者顶部的时候,将事件还给 scrollview,
    以此实现滑动联动。所以我简单的对网上的方案修改了一下,最终代码如下,大家可以直接拿去用,将自己项目种的edittext替换掉就行了,亲测有效。

    **
     * Created by Sherlock on 2017/6/14.
     * 用于解决嵌套Scrollview的时候由于多行而产生的滑动冲突问题
     */
    public class EditTextWithScrollView extends EditText {
    
        //滑动距离的最大边界
        private int mOffsetHeight;
    
        //是否到顶或者到底的标志
        private boolean mBottomFlag = false;
        private boolean mCanVerticalScroll;
    
        public EditTextWithScrollView(Context context) {
            super(context);
            init();
        }
    
        public EditTextWithScrollView(Context context, AttributeSet attrs) {
            super(context, attrs);
            init();
        }
    
        public EditTextWithScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init();
        }
    
        private void init() {
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            mCanVerticalScroll = canVerticalScroll();
        }
    
        @Override
        public boolean dispatchTouchEvent(MotionEvent event) {
            if (event.getAction() == MotionEvent.ACTION_DOWN)
                //如果是新的按下事件,则对mBottomFlag重新初始化
                mBottomFlag = false;
            //如果已经不要这次事件,则传出取消的信号,这里的作用不大
            if (mBottomFlag)
                event.setAction(MotionEvent.ACTION_CANCEL);
    
            return super.dispatchTouchEvent(event);
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            boolean result = super.onTouchEvent(event);
            if (mCanVerticalScroll) {
                //如果是需要拦截,则再拦截,这个方法会在onScrollChanged方法之后再调用一次
                if (!mBottomFlag)
                    getParent().requestDisallowInterceptTouchEvent(true);
            } else {
                getParent().requestDisallowInterceptTouchEvent(false);
            }
            return result;
        }
    
        @Override
        protected void onScrollChanged(int horiz, int vert, int oldHoriz, int oldVert) {
            super.onScrollChanged(horiz, vert, oldHoriz, oldVert);
            if (vert == mOffsetHeight || vert == 0) {
                //这里触发父布局或祖父布局的滑动事件
                getParent().requestDisallowInterceptTouchEvent(false);
                mBottomFlag = true;
            }
        }
    
        /**
         * EditText竖直方向是否可以滚动
         *
         * @return true:可以滚动   false:不可以滚动
         */
        private boolean canVerticalScroll() {
            //滚动的距离
            int scrollY = getScrollY();
            //控件内容的总高度
            int scrollRange = getLayout().getHeight();
            //控件实际显示的高度
            int scrollExtent = getHeight() - getCompoundPaddingTop() - getCompoundPaddingBottom();
            //控件内容总高度与实际显示高度的差值
            mOffsetHeight = scrollRange - scrollExtent;
    
            if (mOffsetHeight == 0) {
    
                return false;
            }
    
            return (scrollY > 0) || (scrollY < mOffsetHeight - 1);
        }
    }
    

    参考了以下两位作者的文章
    http://blog.csdn.net/z191726501/article/details/50701165
    http://blog.csdn.net/sahadev_/article/details/51207068

    相关文章

      网友评论

        本文标题: 真正完美解决EditText嵌套ScrollView的滑动冲突

        本文链接:https://www.haomeiwen.com/subject/rilnrxtx.html