Reputation: 19426
I am using the new Navigation Drawer in my app. It is great except I have not found an easy way to set how the drawer is open. The default behavior is drag from the left edge of the screen to open. This is fine, unless the phone/table has a case on and the edge of phone can not be touched. I would like to allow the user to touch and drag from a margin of the screen to the left. This is easy to set with other nav drawer libs(Sliding lib). I have not seen anything with Google's lib unfortunately.
There is an onTouchEvent() method for the NavigationLayout that could may be used. Of course you could listen to all touch events and trigger an openDrawer, but was hoping for an easy way with less code. Any ideas?
Upvotes: 34
Views: 16406
Reputation: 691
It's a really old question, but I hit that issue nowadays, I tried the original solution, but it didn't work for me.
After hours of trying, I found out that the issue is not with the solution. It's with the library version change.
The accepted answer worked for android.drawerlayout:drawerlayout:1.0.0
but for me, I was using com.google.android.material:material:1.5.0
, which depends on a higher version of drawerlayout:drawerlayout
The android team have added some logic on onLayout
to set the Edge Size.
So I used the original solution, but instead of using it in the activity, I created a Custom View Based on DrawerLayout
.
So here is my custom class:
class CustomDrawerLayout : DrawerLayout {
var swipeEdgeSize = 0
constructor(context: Context) : this(context, null, 0)
constructor(context: Context, attrs: AttributeSet) : this(context, attrs, 0)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
context,
attrs,
defStyleAttr
)
override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
super.onLayout(changed, l, t, r, b)
var leftDraggerField = DrawerLayout::class.java.getDeclaredField("mLeftDragger")
leftDraggerField.isAccessible = true
val viewDragHelper = leftDraggerField[this] as ViewDragHelper
val edgeSizeField = ViewDragHelper::class.java.getDeclaredField("mEdgeSize")
edgeSizeField.isAccessible = true
val origEdgeSize = edgeSizeField[viewDragHelper] as Int
edgeSizeField.setInt(viewDragHelper, max(swipeEdgeSize, origEdgeSize))
}
}
and inside the activity, I will use something like that
class MainActivity :....{
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(....)
setSideMenuAreaRatio(0.8)
....
}
private fun setSideMenuAreaRatio(ration: Double) {
val displaySize = Point()
windowManager.defaultDisplay.getSize(displaySize)
binding.drawerLayout.swipeEdgeSize = (displaySize.x * ration).toInt()
}
}
But if you are starting your new project, use the jetpack compose
. It doesn't have this issue.
Also to make sure that that solution only works with the left/start drawer not the right/end one
Upvotes: 2
Reputation: 2737
Here I've found a solution via reflections
DrawerLayout mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
Field mDragger = mDrawerLayout.getClass().getDeclaredField(
"mLeftDragger");//mRightDragger for right obviously
mDragger.setAccessible(true);
ViewDragHelper draggerObj = (ViewDragHelper) mDragger
.get(mDrawerLayout);
Field mEdgeSize = draggerObj.getClass().getDeclaredField(
"mEdgeSize");
mEdgeSize.setAccessible(true);
int edge = mEdgeSize.getInt(draggerObj);
mEdgeSize.setInt(draggerObj, edge * 5); //optimal value as for me, you may set any constant in dp
Upvotes: 70