一步一步
第一步: 創(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>
<!-- 側邊欄 -->
<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="側邊欄"
android:textColor="#fff"
/>
</LinearLayout>
</androidx.drawerlayout.widget.DrawerLayout>
此時app效果圖為:
cebianlan_demo.gif
可以看到只能從邊緣觸發(fā)側邊欄, 想要類似qq側邊欄, 可以從中間滑出來, 網上有大部分有兩種方法, 一種反射修改mEdgeSize的值來實現(xiàn), 另一種通過activity事件分發(fā)配合mDrawerLayout.opDrawer(GravityCompat.START)來實現(xiàn), 后者必須手指離開屏幕才能觸發(fā), 體驗不好, 我們這里用第一種方法, 通過反射修改mEdgeSize的值
在onCreate()方法里進行編寫
DrawerLayout mDrawerLayout;//根布局
LinearLayout mLinearLayout;//側邊欄布局
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);//獲取側邊欄布局
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));//這里設置mEdgeSize的值3刍病P崂薄!,Math.max函數取得是最大值,也可以自己指定想要觸發(fā)的范圍值勺三,如: 500,注意單位是px
//寫到這里已經實現(xiàn)了,但是你會發(fā)現(xiàn)需曾,如果長按觸發(fā)范圍吗坚,側邊欄也會彈出來,而且速度不太同步呆万,穩(wěn)定
//Start 解決長按會觸發(fā)側邊欄
//長按會觸發(fā)側邊欄是DrawerLayout類的私有類ViewDragCallback中的mPeekRunnable實現(xiàn)導致商源,我們通過反射把它置空
Field leftCallbackField = mDrawerLayout.getClass().getDeclaredField("mLeftCallback");//通過反射拿到私有類ViewDragCallback字段
leftCallbackField.setAccessible(true);//私有字段設置允許修改
ViewDragHelper.Callback vdhCallback = (ViewDragHelper.Callback) leftCallbackField.get(mDrawerLayout);//ViewDragCallback類是私有類,我們返回類型定義成他的父類
Field peekRunnableField = vdhCallback.getClass().getDeclaredField("mPeekRunnable");//我們依然是通過反射拿到關鍵字段谋减,mPeekRunnable
peekRunnableField.setAccessible(true);//不解釋了
//定義一個空的實現(xiàn)
Runnable nullRunnable = new Runnable(){
@Override
public void run() {
}
};
peekRunnableField.set(vdhCallback, nullRunnable);//給mPeekRunnable字段置空
//End 解決長按觸發(fā)側邊欄
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
//--------------------END--------------------------------
}
至此側邊欄邊緣問題解決牡彻,與當前版本qq側邊欄一樣
cebianlan_demo_finish.gif
原文鏈接:
完美開啟DrawerLayout全屏手勢側滑 - 簡書 (jianshu.com)
以上解決方案搬的是評論中 Febers 的評論!3龅庄吼!