android----側(cè)邊欄(DrawerLayout)(完美解決只能在邊緣滑出)

一步一步
第一步: 創(chuàng)建空項目

image.png

第二步: 修改布局文件

<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/drawer_layout_root"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#000">

<!--  主頁面  -->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#fff"
        >
        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center"
            android:text="首頁"
            />
    </LinearLayout>

<!--  側(cè)邊欄  -->
    <LinearLayout
        android:id="@+id/drawer_start"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#eda02c"
        android:layout_gravity="start"
        >
        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center"
            android:text="側(cè)邊欄"
            android:textColor="#fff"
            />
    </LinearLayout>

</androidx.drawerlayout.widget.DrawerLayout>

此時app效果圖為:


cebianlan_demo.gif

可以看到只能從邊緣觸發(fā)側(cè)邊欄, 想要類似qq側(cè)邊欄, 可以從中間滑出來, 網(wǎng)上有大部分有兩種方法, 一種反射修改mEdgeSize的值來實現(xiàn), 另一種通過activity事件分發(fā)配合mDrawerLayout.opDrawer(GravityCompat.START)來實現(xiàn), 后者必須手指離開屏幕才能觸發(fā), 體驗不好, 我們這里用第一種方法, 通過反射修改mEdgeSize的值

在onCreate()方法里進(jìn)行編寫

    DrawerLayout mDrawerLayout;//根布局
    LinearLayout mLinearLayout;//側(cè)邊欄布局
    View mContent;//主頁面布局

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //--------------------START--------------------------------
        mDrawerLayout = findViewById(R.id.drawer_layout_root);//獲取根布局
        mLinearLayout = findViewById(R.id.drawer_start);//獲取側(cè)邊欄布局
        mContent = mDrawerLayout.getChildAt(0);//獲取主頁面布局, 可以看到主頁面布局是父布局的第一個子布局, 可以這樣獲得, 也可以定義id

        try {
            Field leftDraggerField = mDrawerLayout.getClass().getDeclaredField("mLeftDragger");//通過反射獲得DrawerLayout類中mLeftDragger字段
            leftDraggerField.setAccessible(true);//私有屬性要允許修改
            ViewDragHelper vdh = (ViewDragHelper) leftDraggerField.get(mDrawerLayout);//獲取ViewDragHelper的實例, 通過ViewDragHelper實例獲取mEdgeSize字段
            Field edgeSizeField = vdh.getClass().getDeclaredField("mEdgeSize");//依舊是通過反射獲取ViewDragHelper類中mEdgeSize字段, 這個字段控制邊緣觸發(fā)范圍
            edgeSizeField.setAccessible(true);//依然是私有屬性要允許修改
            int edgeSize = edgeSizeField.getInt(vdh);//這里獲得mEdgeSize真實值
            Log.d("AAA", "mEdgeSize: "+edgeSize);//這里可以打印一下看看值是多少

            //Start 獲取手機屏幕寬度,單位px
            Point point = new Point();
            getWindowManager().getDefaultDisplay().getRealSize(point);
            //End 獲取手機屏幕

            Log.d("AAA", "point: "+point.x);//依然可以打印一下看看值是多少
            edgeSizeField.setInt(vdh, Math.max(edgeSize, point.x));//這里設(shè)置mEdgeSize的值?。?!,Math.max函數(shù)取得是最大值,也可以自己指定想要觸發(fā)的范圍值,如: 500,注意單位是px
            //寫到這里已經(jīng)實現(xiàn)了,但是你會發(fā)現(xiàn),如果長按觸發(fā)范圍,側(cè)邊欄也會彈出來,而且速度不太同步,穩(wěn)定

            //Start 解決長按會觸發(fā)側(cè)邊欄
            //長按會觸發(fā)側(cè)邊欄是DrawerLayout類的私有類ViewDragCallback中的mPeekRunnable實現(xiàn)導(dǎo)致,我們通過反射把它置空
            Field leftCallbackField = mDrawerLayout.getClass().getDeclaredField("mLeftCallback");//通過反射拿到私有類ViewDragCallback字段
            leftCallbackField.setAccessible(true);//私有字段設(shè)置允許修改
            ViewDragHelper.Callback vdhCallback = (ViewDragHelper.Callback) leftCallbackField.get(mDrawerLayout);//ViewDragCallback類是私有類,我們返回類型定義成他的父類
            Field peekRunnableField = vdhCallback.getClass().getDeclaredField("mPeekRunnable");//我們依然是通過反射拿到關(guān)鍵字段,mPeekRunnable
            peekRunnableField.setAccessible(true);//不解釋了
            //定義一個空的實現(xiàn)
            Runnable nullRunnable = new Runnable(){
                @Override
                public void run() {

                }
            };
            peekRunnableField.set(vdhCallback, nullRunnable);//給mPeekRunnable字段置空
            //End 解決長按觸發(fā)側(cè)邊欄

        } catch (NoSuchFieldException | IllegalAccessException e) {
            e.printStackTrace();
        }
        //--------------------END--------------------------------
    }

至此側(cè)邊欄邊緣問題解決,與當(dāng)前版本qq側(cè)邊欄一樣


cebianlan_demo_finish.gif

原文鏈接:
完美開啟DrawerLayout全屏手勢側(cè)滑 - 簡書 (jianshu.com)
以上解決方案搬的是評論中 Febers 的評論?。?!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 原攻略來自于:How To Create a Cool 3D Sidebar Animation Like in ...
    好尼桑閱讀 1,434評論 0 4
  • 16宿命:用概率思維提高你的勝算 以前的我是風(fēng)險厭惡者,不喜歡去冒險,但是人生放棄了冒險,也就放棄了無數(shù)的可能。 ...
    yichen大刀閱讀 7,832評論 0 4
  • 公元:2019年11月28日19時42分農(nóng)歷:二零一九年 十一月 初三日 戌時干支:己亥乙亥己巳甲戌當(dāng)月節(jié)氣:立冬...
    石放閱讀 7,449評論 0 2

友情鏈接更多精彩內(nèi)容