ScrollView嵌套EditText联带滑动的解决办法

Posted that-jay

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ScrollView嵌套EditText联带滑动的解决办法相关的知识,希望对你有一定的参考价值。

解决ScrollView嵌套EditText的滑动事件,并且实现它们两者之间的联带滑动。什么是联带滑动呢,就是当EditText滑动到底部的时候,这时就应该让外部的ScrollView跟着滑动,好让它们之间完成连贯的滑动事件。先来看看效果把。

技术图片

网上没找到完整实现的例子,只好自己撸demo了。
代码里有注释,全部代码如下:

package chn.fz.thatjay.scrolleditview.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.text.Layout;
import android.util.AttributeSet;
import android.support.v7.widget.AppCompatEditText;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.RelativeLayout;

import chn.fz.thatjay.scrolleditview.R;


public class ScrollMulrowsEditText extends AppCompatEditText 

    private final String TAG = "ScMulrowsEditText";
    //滑动距离的最大边界
    private int mOffsetHeight;

    private int mHeight;


    private int mVert = 0;


    public ScrollMulrowsEditText(Context context) 
        super(context);
    

    public ScrollMulrowsEditText(Context context, AttributeSet attrs) 
        super(context, attrs);
        initAttribute(context, attrs, 0);
    

    public ScrollMulrowsEditText(Context context, AttributeSet attrs, int defStyleAttr) 
        super(context, attrs, defStyleAttr);
        initAttribute(context, attrs, defStyleAttr);
    


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) 
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        int paddingTop;
        int paddingBottom;
        int height;
        int mLayoutHeight;

        //获得内容面板
        Layout mLayout = getLayout();
        //获得内容面板的高度
        mLayoutHeight = mLayout.getHeight();
        //获取上内边距
        paddingTop = getTotalPaddingTop();
        //获取下内边距
        paddingBottom = getTotalPaddingBottom();

        //获得控件的实际高度
        height = mHeight; // getHeight()第一次得到0,所以最好从外部指定设置值

        //计算滑动距离的边界  mOffsetHeight 当内容少,没有滚动条时候,值为0
        mOffsetHeight = mLayoutHeight + paddingTop + paddingBottom - height;

        setOnTouchListener();
        if(getId() == R.id.edittext2) 
            Log.d(TAG, "ffffaaaa onMeasure == " + mOffsetHeight);
        
    

    private void initAttribute(Context context, AttributeSet attrs, int defStyleAttr) 
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.ScrollMulrowsEditText, defStyleAttr, 0);
        int count = array.getIndexCount();
        for (int i = 0; i < count; i++) 
            int attr = array.getIndex(i);
            switch (attr) 
                case R.styleable.ScrollMulrowsEditText_sc_mul_edit_height:
                    mHeight = array.getDimensionPixelSize(attr, 0);
                    break;
            
        
        array.recycle();
    

    @Override
    protected void onScrollChanged(int horiz, int vert, int oldHoriz, int oldVert) 
        super.onScrollChanged(horiz, vert, oldHoriz, oldVert);
        mVert = vert;
        if(getId() == R.id.edittext2)
            Log.d(TAG,"ffffaaaa mOffsetHeight == " + mOffsetHeight + "  ,, vert ===  " + vert );
        
        if (vert == mOffsetHeight || vert == 0) 
            //这里触发父布局或祖父布局的滑动事件
            getParent().requestDisallowInterceptTouchEvent(false);
            Log.d(TAG, "vert requestDisallowInterceptTouchEvent  false ");
        
    

    //滑动到上边缘
    public boolean isUpperEdge()
        return mVert == 0;
    

    //滑动到下边缘
    public boolean isLowerEdge()
        return mVert == mOffsetHeight;
    

    private float scrollBeginY;
    public void setOnTouchListener()
        setOnTouchListener(new View.OnTouchListener() 
            @Override
            public boolean onTouch(View v, MotionEvent event) 
                //canScrollVertically()方法为判断指定方向上是否可以滚动,参数为正数或负数,负数检查向上是否可以滚动,正数为检查向下是否可以滚动
                if(MotionEvent.ACTION_DOWN == event.getAction())
                    scrollBeginY = event.getY();
                    v.getParent().requestDisallowInterceptTouchEvent(true);//要求父类布局不在拦截触摸事件
                    return false;
                
                Log.d(TAG, "event.getY" + event.getY());//edittext 如果在最边缘,getY得到的也不是固定的值
                if(canScrollVertically(1))//可以向下滚动
                    if(isUpperEdge() && event.getY() >= scrollBeginY)//已经在上边缘,向下手势滑动
                        v.getParent().requestDisallowInterceptTouchEvent(false);//交给父布局
                     else 
                        v.getParent().requestDisallowInterceptTouchEvent(true);
                    
                 else if(canScrollVertically(-1))//可以向上滚动
                    if(isLowerEdge() && event.getY() <= scrollBeginY)//已经在下边缘,向上手势滑动
                        v.getParent().requestDisallowInterceptTouchEvent(false);//交给父布局
                     else 
                        v.getParent().requestDisallowInterceptTouchEvent(true);
                    
                 else 
                    v.getParent().requestDisallowInterceptTouchEvent(false);//交给父布局
                
                //getY  手机屏幕上边 getY  值小
                //getY  手机屏幕下边 getY  值大
                return false;
            
        );
    


 

activity代码,下面是ImmersionBar的第三方库,用来监听输入法键盘消失的时候,让edittext失去焦点,否则edittext光标一直在,很难看。

@Override
protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initStatusBar(edittext1, edittext2, edittext3, edittext4, edittext5);

public void initStatusBar(final EditText... ets)
        ImmersionBar.with(this)
                .fitsSystemWindows(true)
                .statusBarColor(R.color.color1)
                .keyboardEnable(true)
                .setOnKeyboardListener(new OnKeyboardListener() 
                    @Override
                    public void onKeyboardChange(boolean isPopup, int keyboardHeight) 
                        if (!isPopup) 
                            for (EditText et:ets
                            ) 
                                et.clearFocus();
                            
                        
                    
                )
                .init();
    

 

完整项目代码:github下载地址

 

以上是关于ScrollView嵌套EditText联带滑动的解决办法的主要内容,如果未能解决你的问题,请参考以下文章

ScrollView中使用EditText,并解决滑动冲突

解决EditText和ScrollView滑动冲突问题

解决EditText跟ScrollView滑动冲突

关于 ScrollView 中嵌套 EditText,输入多行会使整体滚动的问题

ScrollView内嵌EditText滚动事件冲突处理

(转)ViewPager,ScrollView 嵌套ViewPager滑动冲突解决