ScrollView嵌套EditText聯帶滑動的解決辦法

解決ScrollView嵌套EditText的滑動事件,而且實現它們二者之間的聯帶滑動。什麼是聯帶滑動呢,就是當EditText滑動到底部的時候,這時就應該讓外部的ScrollView跟着滑動,好讓它們之間完成連貫的滑動事件。先來看看效果把。android

網上沒找到完整實現的例子,只好本身擼demo了。
代碼裏有註釋,所有代碼以下:git

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光標一直在,很難看。github

@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下載地址ide

相關文章
相關標籤/搜索