EditText嵌套在ScrollView中的滑動(dòng)沖突問題解決

在某些場景下,需要使用EditText來讓用戶輸入信息。當(dāng)EditText設(shè)置maxLines后,用戶輸入行數(shù)超過maxLines后,只能通過上下滑動(dòng)來瀏覽所有文字。

但當(dāng)EditText外層使用ScrollView來讓整個(gè)界面滑動(dòng)時(shí),用戶觸摸EditText區(qū)域時(shí)不能再顯示折疊的文字,而只是滑動(dòng)了整個(gè)srollview。

實(shí)現(xiàn)時(shí)需要注意的是,當(dāng)EditText框內(nèi)容并未超過maxLines時(shí),此時(shí)用戶觸摸EditText區(qū)域進(jìn)行滑動(dòng)時(shí),期望整個(gè)ScrollView是滑動(dòng)的;只有當(dāng)EditText框內(nèi)容大于maxLines時(shí),才需要由EditText自身來處理滾動(dòng)事件。

具體解決方案如下:

//設(shè)置touch事件
mEditText = (EditText) findViewById(R.id.edit_text);
mEditText.setOnTouchListener(this);

//重寫onTouch方法
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
        //觸摸的是EditText控件,且當(dāng)前EditText可以滾動(dòng),則將事件交給EditText處理;否則將事件交由其父類處理
        if ((view.getId() == R.id.edit_text && canVerticalScroll(mEditText))) {
            view.getParent().requestDisallowInterceptTouchEvent(true);
            if (motionEvent.getAction() == MotionEvent.ACTION_UP) {
                view.getParent().requestDisallowInterceptTouchEvent(false);
            }
        }
        return false;
}

/**
* EditText豎直方向是否可以滾動(dòng)
* @param editText  需要判斷的EditText
* @return  true:可以滾動(dòng)   false:不可以滾動(dòng)
*/
private boolean canVerticalScroll(EditText editText) {
        if(editText.canScrollVertically(-1) || editText.canScrollVertically(1)) {
            //垂直方向上可以滾動(dòng)
            return true;
        }
        return false;
}

canScrollVertically的源碼說明及實(shí)現(xiàn)如下:

    /**
     * Check if this view can be scrolled vertically in a certain direction.
     *
     * @param direction Negative to check scrolling up, positive to check scrolling down.
     * @return true if this view can be scrolled in the specified direction, false otherwise.
     */
    public boolean canScrollVertically(int direction) {
        final int offset = computeVerticalScrollOffset();
        final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
        if (range == 0) return false;
        if (direction < 0) {
            return offset > 0;
        } else {
            return offset < range - 1;
        }
    }

該函數(shù)要求sdk的版本是API14及以上。如果需要兼容4.0以下版本,可參考源碼中computeVerticalScrollOffset、computeVerticalScrollRange、computeVerticalScrollExtent的實(shí)現(xiàn)。注意子類可能重寫View中的該方法。

    private boolean canVerticalScroll(EditText editText) {
        //滾動(dòng)的距離
        int scrollY = editText.getScrollY();
        //控件內(nèi)容的總高度
        int scrollRange = editText.getLayout().getHeight();
        //控件實(shí)際顯示的高度
        int scrollExtent = editText.getHeight() - editText.getCompoundPaddingTop() -editText.getCompoundPaddingBottom();
        //控件內(nèi)容總高度與實(shí)際顯示高度的差值
        int scrollDifference = scrollRange - scrollExtent;

        if(scrollDifference == 0) {
            return false;
        }

        return (scrollY > 0) || (scrollY < scrollDifference - 1);
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,255評論 4 61
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,556評論 25 708
  • 輾轉(zhuǎn)了一夜的煙花與哀歌,不曾停歇。 雨落不止,寒風(fēng)凜冽。 雨聲淅瀝,似怨如訴,天地浩大,如同一場孤獨(dú)的對話,你正言...
    旅行客舟閱讀 495評論 0 1
  • 我們每個(gè)人身上都會有同性戀的傾向,只是或多或少。有人說,“同性戀上不了天堂”真的是這樣嗎? 我在現(xiàn)實(shí)生活中沒有遇到...
    蛋蛋蛋蛋蛋琰閱讀 485評論 0 0
  • 整個(gè)十月 半月紅,半月黃 我掛在樹枝上驚嘆 我是紅葉 是我的垂暮染紅了夕陽 我臨終的妝扮,只為來世更好的遇見 與你...
    流沙l閱讀 488評論 2 4