I had implement DrawerLayout in my application. Now if suppose I click on screen then the DrawerLayout is getting close. But now I want to implement some operations on onTouch.
My question is how can I prevent the DrawerLayout to close onTouch. I want to implement this like suppose I dismiss the onTouch event of DrawerLayout.
If any suggestion please share with me.
Thanks in advance.
Its not actually a proper solution but is a workaround increase the drawer width so that it covers majority of the screen.Doing this your drawer will get most of the touch events and therefore wont close on touch.
<ListView
android:id="#+id/drawerContentList"
style="#style/Theme.AppCompat.Light.DarkActionBar"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#111"
android:choiceMode="singleChoice" >
</ListView>
increase android:layout_width to say around 320dp
Related
I have a Nav Drawer where the header has a ListView, and the body is a standard menu. I have two implementations of this, each one with its own problem
The drawer should look like this: (white square is the ListView)
The 1st implementation shows both views but doesn't allow scrolling of the ListView in the header. Any scrolling is "intercepted" by the nav Drawer
<android.support.design.widget.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="#layout/nav_header_drawer" //contains my listView
app:menu="#menu/activity_drawer_main" >
</android.support.design.widget.NavigationView>
In the 2nd implementation, I fixed the scrolling issue by includeing the header separately in the navView. It scrolls, but now the menu list is gone. It doesn't show at all.
<android.support.design.widget.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:menu="#menu/activity_drawer_main" >
<include
layout="#layout/nav_header_drawer"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.design.widget.NavigationView>
The drawer should look like the image above, but implementation 1 (pictured) won't scroll, and implementation two doesn't have the menu items (share, send).
Any help figuring out how to fix either implementation is appreciated!
Note: I know I could create a LinearLayout of items in place of the menu, but it doesn't look as nice, with the graying out when tapped. I could code that as well, but I feel like the functionality is built in, (I just can't access it), so why build it from scratch?
I found out how to override the navigation view's intercepting the listview's scroll here https://stackoverflow.com/a/14577399/5202215
This question already has answers here:
Android - Is Navigation Drawer from right hand side possible?
(10 answers)
Closed 6 years ago.
I'm working on this project, and i need to create a double drawer app, it's possible to modify the navigation drawer so it can work both sides? or do I created a double drawer without using the navigation drawer.
try Sliding menu lib
SlidingMenu
You will have to implement the button feature yourself but it shouldn't be too hard!
EDIT:
An example:
SlidingMenu menuS = new SlidingMenu(this);
menuS.setMode(SlidingMenu.LEFT_RIGHT);
menuS.setMenu(R.layout.slideout_list);
menuS.setSecondaryMenu(R.layout.slideout_list2);
As the code shows you need to set the mode to LEFT_RIGHT and must specify a layout for both the left menu (setMenu()) and the right menu (setSecondaryMenu()) along with the other options specifying menu size and shadows etc.
If your navigation drawers needs to display different data (why would you display the same data from the right and the left?) like a navigation on the left and a search filter on the right. You'd better use 2 different drawers, each one with his own data / behaviour.
<android.support.v4.widget.DrawerLayout
android:id="#+id/drawer_layout"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="#layout/content_main_activity"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<android.support.design.widget.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="#layout/nav_header_ad_list"
app:menu="#menu/activity_main_navigation_menu"
headerLayout="#layout/nav_header_ad_list"
menu="#menu/activity_main_navigation_menu"
tools:layout_gravity="start"
/>
<android.support.design.widget.NavigationView
android:id="#+id/activity_main_search_filter"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:layout_gravity="end"
tools:layout_gravity="end"
/>
</android.support.v4.widget.DrawerLayout>
You have to combine some of the methodology. like you have to implement fragment in that navigation view portion in navigation drawer layout. second there is no way both drawer can be opened at same time so implement one fragment over there and on the basis of different click event open drawer layout with different gravity value (GravityCompat.START, GravityCompat.END).
like from drawer button open drawer from left and from filter button open drawer from right and load different fragment view on the basis of that. I hope it will serve your purpose.
I'd like to create an extra-information view similar to that of the Google Drive app (below) on a tablet. When the info button is clicked, this view slides in from the rightcontaining a layout. Another example would be the Google+ app with its notifications slide-out panel:. The SlidingLayer by 6Wunderkinder almost works, but doesn't fade a semi-black background over the views behind the "drawer" and I haven't found another library that does this.
If anybody has any suggestions/solutions please let me know!
Also, I've already looked at this question and none of the answers suggested there are correct either.
For posterity, here's the answer to this question. As Steve Benett's suggestion led me to discover, the correct way to do this is to use two DrawerLayouts, nested within each other like so:
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/drawer_navigation_bar"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.widget.DrawerLayout
android:id="#+id/drawer_sidebar"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="#+id/fragment_main_content"
android:name="MainContentFragment"
android:layout_height="match_parent"
android:layout_width="match_parent" />
<fragment
android:id="#+id/fragment_sidebar"
android:name="SidebarFragment"
android:layout_width="300dp"
android:layout_height="match_parent"
android:layout_gravity="end" />
</android.support.v4.widget.DrawerLayout>
<fragment
android:id="#+id/fragment_navigation_bar"
android:name="NavigationFragment"
android:layout_height="match_parent"
android:layout_width="300dp"
android:layout_gravity="start" />
</android.support.v4.widget.DrawerLayout>
The innermost DrawerLayout contains the main content of the Activity, whether it be a fragment or some other layout components. fragment_sidebar is the fragment that will be swiped out from the right. Then, on the top-level DrawerLayout you have the fragment_nagivation_bar which houses the left Drawer's ListView or whatever.
Then, in the Activity Java code you have:
mDrawerLayoutLeft= (DrawerLayout) findViewById(R.id.drawer_navigation_bar);
mDrawerLayoutRight = (DrawerLayout) findViewById(R.id.drawer_sidebar);
mDrawerLayoutLeft.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
mDrawerLayoutRight.setDrawerShadow(R.drawable.sidebar_shadow, GravityCompat.END);
An optional addition (but recommended, for consistency of UX) is to hide the other Drawer when one is opened, so your screen doesn't consist solely of Drawers.
I hope this has helped somebody!
This is the DrawerLayout. Have a look at the design guide, which illustrates the behavior well.
If you want to use / customize the "semi-black background" use DrawerLayout.setDrawerShadow() with a drawable. Google hands out a set of drawables here. Download the ActionBar Icon Pack and look for the drawable_shadow.9.png.
If you want that the menu appears from the right, set android:layout_gravity="end" as a property in the second child of the layout.
I'm trying to implement the navigation drawer pattern based on my app. I downloaded the sample code from here and i ran it and 90 % of the times the drawer works ok, but sometimes the drawer gets stuck when i try to open it. I have a way of replicating the situation but it doesn't always work. What i do is:
1- Run the sample code as is.
2- Put your finger on the left edge to get the drawer peek
3- Let go of the finger and press it on the main fragment
4- Try to open the drawer as usual
Sometimes the drawer gets stuck on the peek mode no matter how much you swipe your finger to the right to open the drawer more. Has anyone had / fixed this issue?
I faced a similar issue as mentioned by you. I had a list view inside a relative layout (FILL_PARENT). Whenever the content in the list view is less and when I dragged in the area outside the list view, the navigation drawer got struck. Setting android:clickable="true" for the relative layout resolved the problem. Hope this may help.
To clarify on Viji's answer, if you are using something like the navigation drawer example provided:
<!-- A DrawerLayout is intended to be used as the top-level content view using match_parent for both width and height to consume the full space available. -->
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- As the main content view, the view below consumes the entire
space available using match_parent in both dimensions. -->
<FrameLayout
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- android:layout_gravity="start" tells DrawerLayout to treat
this as a sliding drawer on the left side for left-to-right
languages and on the right side for right-to-left languages.
The drawer is given a fixed width in dp and extends the full height of
the container. A solid background is used for contrast
with the content view. -->
<ListView
android:id="#+id/left_drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:choiceMode="singleChoice"
android:divider="#android:color/transparent"
android:dividerHeight="0dp"
android:background="#111"/>
</android.support.v4.widget.DrawerLayout>
Adding android:clickable="true" to the FrameLayout seems to fix the problem.
Two soluctions.
setting android:clickable
copy the source code of drawerlayout and delete peekDrawer function to disabled this feature
Let me explain why the reason of this bug.
DrawerLayout three states
STATE_IDLE, STATE_DRAGGING, STATE_SETTLING
ACTION_DOWN-> onEdgeTouched will be triggered if it is on the edge, DrawerLayout will trigger peekDrawer after 120ms
PeekDrawer actually changes the state of DrawerLayout to STATE_SETTLING, and then lets the Drawer scroll to the specified location. Then set the state to IDLE.
ACTION_MOVE->
If the current state is DRAGGING, drag captureView
If the current state is not DRAGGING, it will try to execute tryCaptureViewForDrag to reset the state to DRAGGING.
And at the same time, it will also determine whether a new edge gesture is triggered (emphasis !!)
If a new edge gesture was dete, it will invoke onEdgeDragStared
and DrawerLayout will go to captureView to captrue the drawer
How the recuurent this bug?
First tap the edge to invoke a 120ms delay function peekDrawer
Before the peekDrawer was invoked, trigger onEdgeDragStared let the drawer layout capture the drawer, the dragState will be seted to STATE_DRAGGING
After 120ms, If your finger are still in the area that drawerLayout want to peek to , the dragState will be set to SETTLING
Before the drawer peek to the destination, move your finger fast out of that area before the peek end, the drawer will not follow your finger because the state is SETTLING, after SETTLING the state will be set to IDLE
Now your finger is totally out of the drawer and the state is IDLE , so you can’t drag the view anymore
So, the solution is to stop the peekDrawer
actually, the drawerlayout has fixed this problem.
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch (action) {
case MotionEvent.ACTION_MOVE: {
// If we cross the touch slop, don't perform the delayed peek for an edge touch.
if (mLeftDragger.checkTouchSlop(ViewDragHelper.DIRECTION_ALL)) {
mLeftCallback.removeCallbacks();
mRightCallback.removeCallbacks();
}
break;
}
}
return interceptForDrag || interceptForTap || hasPeekingDrawer() || mChildrenCanceledTouch;
}
If the child is clickable, the child will consume the event, the onInterceptTouchEvent will invoke many times. and remove the peekDraw while move.
I'm trying to figure out how to add an OnGestureListener or some other way to detect a touch drag across the screen to a button, or some other widget that can be added to a View. I've been trying to figure out how to do this for a while and I can't. I've seen and successfully been able to do it to an activity. Can anyone spell this out for me, because I seem to be having a lot more trouble than I thought I would with this. Thanks.
I'm assuming you've already gone through http://developer.android.com/resources/articles/gestures.html. The trick is that you can have the GestureOverlayView as a transparent layer on top of another View. You can then interpret any gestures detected as belonging to the underlying View.
In the article, they show you a layout like this:
<android.gesture.GestureOverlayView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/gestures"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gestureStrokeType="multiple"
android:eventsInterceptionEnabled="true"
android:orientation="vertical">
<ListView
android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</android.gesture.GestureOverlayView>
Any gestures detected could then be interpreted as coming from the ListView. In your case replace the ListView with your Button, and you should be all set.
It sounds like you should be doing dragging and dropping,
http://developer.android.com/guide/topics/ui/drag-drop.html