I have this problem when opening drawer on gingerbread and behind is google map v2. Map that should be on screen behind gets on top of everything.
Now I could bypass this by hiding map when drawer opens and show it when closes but I'm looking for more elegant solution if someone came up with any?
Just wrap SupportMapFragment with FrameLayout and put transparent View above like this:
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- Map fragment -->
<fragment
android:id="#+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"
class="com.google.android.gms.maps.SupportMapFragment" />
<!-- Transparent view -->
<View
android:layout_width="match_parent"
android:layout_height="match_parent" />
Tested with Android 4.0.4 - works fine for me
There is a bug with google maps api v2 and black space. Maybe you have got similar problem. For solutions look here:
https://github.com/jfeinstein10/SlidingMenu/issues/228
and here:
https://github.com/jfeinstein10/SlidingMenu/issues/168
As far as I remember solutions are one of this:
extending Google Maps and make it to redraw every view more often
set map's z index on top param to true
put transparent overlay over Google Maps view
I have got the same problem here on ICS 4.0.4. The solutions mentioned in jfeinstein10's github post seems not working for me. But I have found a workaround, even it is not the best.
When creating DrawerToggle object I override this event
#Override
public void onDrawerSlide(View drawerView, float slideOffset)
{
super.onDrawerSlide(drawerView, slideOffset);
mDrawerLayout.bringChildToFront(drawerView);
mDrawerLayout.requestLayout();
mDrawerLayout.setScrimColor(Color.TRANSPARENT);
}
bringChildToFront and requestLayout method should overcome the drawer rendering problem while setScrimColor will get rid of the shadow. Too bad that I haven't found a workaround to render the shadow correctly as well. Hope this helps.
You should override the onDrawerSlide function and move the drawer to front
Toolbar toolbar = (Toolbar) findViewById(R.id.tool_bar);
DrawerLayout Drawer = (DrawerLayout) findViewById(R.id.DrawerLayout);
mDrawerToggle = new ActionBarDrawerToggle(this, Drawer, toolbar, R.string.openDrawer, R.string.closeDrawer) {
#Override
public void onDrawerSlide(View drawerView, float slideOffset)
{
super.onDrawerSlide(drawerView, slideOffset);
Drawer.bringChildToFront(drawerView);
Drawer.requestLayout();
Drawer.setScrimColor(Color.TRANSPARENT);
}
};
Related
Hello developer and programmers. I just start learning android app development. Found awesome navigation bar style and want to develop similar design. It has background image and it moves when scroll.
Please help me to develop the same. Thanks. I added an example gif as link.
https://media.giphy.com/media/l4FGv7VknT1zpZACQ/giphy.gif
This can be achieved by using a custom layout for your navigation drawer alongside a custom implementation of DrawerLayout.DrawerListener. Below is a very simple example that can be easily adapted to the code generated by Android Studio's "New Project -> Navigation Drawer Activity".
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<include
layout="#layout/app_bar_main"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<FrameLayout
android:id="#+id/nav_view"
android:layout_width="#dimen/navdrawer_width"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#ccc">
<ImageView
android:id="#+id/image"
android:layout_width="256dp"
android:layout_height="256dp"
android:layout_gravity="center"
android:src="#drawable/mydrawable"/>
</FrameLayout>
</android.support.v4.widget.DrawerLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity {
private ImageView iv;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
iv = (ImageView) findViewById(R.id.image);
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
DrawerLayout.DrawerListener listener = new MyActionBarDrawerListener();
drawer.addDrawerListener(listener);
}
private class MyActionBarDrawerListener extends DrawerLayout.SimpleDrawerListener {
#Override
public void onDrawerSlide(View drawerView, float slideOffset) {
super.onDrawerSlide(drawerView, slideOffset);
int navdrawerWidth = getResources().getDimensionPixelSize(R.dimen.navdrawer_width);
float closedAmount = (1 - slideOffset);
int marginStart = 2 * (int) (navdrawerWidth * closedAmount);
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) iv.getLayoutParams();
MarginLayoutParamsCompat.setMarginStart(params, marginStart);
iv.setLayoutParams(params);
}
}
}
The core of the solution is that you provide a background image but update its marginStart attribute as the drawer slides. You can fiddle with the exact numbers to get the amount of sliding that you like.
Note that I've omitted a lot of code in order to improve readability. In practice you would probably have MyActionBarDrawerListener extend from ActionBarDrawerToggle so that you'd get the navigation icon etc.
Look it's not that hard but still it's not that easy Because this type of effect is said to be Parallax effect. I done a solid googling but still can't find a helpful library. So you have to do this your self
Steps are
Learn about custom navigation layout which is made by your fragment.
Once you are done with drawer layout add an Image as a background of your fragment
call mSlidingDrawer.addDrawerListner(new YourDrawerListner()) method // just like Ben P.
Implement onDrawerSlide(View drawerView, float slideOffset)
get the Your Fragment Background Image Instance (I used mImage)
in onDrawerSlide(...) use offset
In your image instance call mImage.animate().setTranslationX(offset).start()
Update
Ben P. answer is better But you can use mine also just add the DrawerListner part of Ben P. to my answer also
Core
It is parallax effect. based on relative motion of elements
Currently, when the navigation drawer in my app opens, it appears on top of the mainActivity view.
My question being, is it possible to animate the mainActivity view so that the left side of said view matches the right side of the navigation drawer when it opens?
It is (almost) always possible. But i think it is a bad idea, as it will not follow the ui guidelines from google for an android app.
However if you really want to do it, you have two options :
Easy. When the drawer is open start animation on the rest of the layout, and do the opposite animation when the drawer is closed. It is less effort, but probably poor result.
Implement your own drawer. You will be able to have the perfect animation and behavior you desire. In this case you probably want to use fragment. The main fragment will be the content and another fragment will be the drawer. When you need to do it, you can animate both fragment with a translation to "open" your drawer.
You can read more about animation here.
All you have to do is setX() of your main_content in the Activity
my_activity.xml
<android.support.v4.widget.DrawerLayout
android:id="#+id/drawer_layout"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- The main content view -->
<RelativeLayout
android:id="#+id/main_content_rl"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/material_grey_100">
<include
layout="#layout/content"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
<!-- The navigation 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:menu="#menu/menu_drawer"/>
</android.support.v4.widget.DrawerLayout>
MyActivity java file
mDrawerToggle =
new ActionBarDrawerToggle(this, mDrawerLayout, toolbar, R.string.drawer_open,
R.string.drawer_close) {
#Override
public void onDrawerSlide(View drawerView, float slideOffset) {
float width = drawerView.findViewById(R.id.main_header_rl).getWidth();
final int movement= (int) (width * slideOffset);
findViewById(R.id.main_content_rl).setX(movement);
super.onDrawerSlide(drawerView, slideOffset);
}
};
mDrawerLayout.setDrawerListener(mDrawerToggle);
Where main_header_rl is the id of my header_navigation_drawer
<RelativeLayout
android:id="#+id/main_header_rl"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">
...
</RelativeLayout>
Does anyone know how to turn 180 degrees icon ic_drawer in NavigationDrawer after clicking on the drop-down menu?
Currently, after expanding the Menu icon animates to the left - I would like to animating to the right (or the other way around than it is).
Sorry for my English.
you have to use Toolbar which is introduced in support 21+
<android.support.v7.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/mtoolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/primary" />
also add dependencies in your project .
The last thing to use ActionBarDrawerToggle in your class.
ActionBarDrawerToggle mDrawerToggle = new ActionBarDrawerToggle(MainActivity.this,
mDrawerLayout,mToolbar,"Drawer opentitle","Drawer closetitle");
Constructor's parameter need toolbar object ,so you have to use Toolbar.
check this out ToolBar
I have a Navigation Drawer issue.
On my Navigation Drawer app, sometimes Drawer is displayed behind the other content view. So only the part of the drawer is shown (the other parts are hidden by content area).
I tried everything but it does not works.
drawer.bringToFront();
drawer.buildLayer();
drawer.clearFocus();
drawer.requestLayout();
drawer.forceLayout();
But in this situation, if I touch option button or change focus, screen is refreshed and it displays drawer well.
So I want to know what kinds of methods are called when I touch option button. Then I think I can call that method when drawer is opened.
Thank you so much in advanced.
I am posting a sample code try to check with your code.
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<RelativeLayout
android:id="#+id/relative_home"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/tile_image_data" >
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="48dip" >
</android.support.v4.view.ViewPager>
</RelativeLayout>
<ListView
android:id="#+id/drawer"
android:layout_width="240dp"
android:layout_height="fill_parent"
android:layout_gravity="right"
android:cacheColorHint="#00000000"
android:divider="#19000000"
android:background="#drawable/tile_image_data"
android:choiceMode="singleChoice" />
</android.support.v4.widget.DrawerLayout>
I had the same problem. I solved it by changing android:id in the FrameLayout from #android:id/content to #+id/content. Apparently it's not always a good idea to use system resource ids.
I had the same problem. When the main view called onWindowsFocusChange() the drawer opened behind the main view. This happened with a Unity3D view.
I've solved the issue calling in the function
onDrawerSlide(View drawerView, float slideOffset)
,which is a method inside the DrawerListener, drawerView.bringToFront().
I had the same problem, but it seems that it just only happen on versions prior KITKAT. Thanks to #jack, after I updated the code following, it is ok:
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, R.string.drawer_open,
R.string.drawer_close) {
#Override
public void onDrawerSlide(View drawerView, float slideOffset) {
super.onDrawerSlide(drawerView, slideOffset);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
drawerView.bringToFront();
getWindow().getDecorView().requestLayout();
getWindow().getDecorView().invalidate();
}
}
};
You may want to know why do I invoke requestLayout() and invalidate(), just see the doc for bringToFront().
I have successfully implemented a NavigationDrawer for my application.
My app displays a drawer that opens on the left of the screen.
My problem is I need to add a button on the left. That button might be clicked or swiped to open the left drawer. That I can do.
But the button is supposed to look like it's a part of the drawer that would overflow into the screen.
That means the button should slide simultaneously as the drawer opens and closes.
CLOSED STATE :
OPENING STATE
I tried adding the button into the left drawer's layout, but it seems you can't make stuff appear outside of its boundaries, and the drawer will always get completely hidden when you close it.
Now I'm trying adding it to add a button to the main DrawerLayout and make it align to the right of the left drawer... But no luck... It looks like a DrawerLayout can't have more than two children...
Any help will be appreciated.
I'm using the Support library (v4)
[EDIT]
And I am supporting API level 8... So can't use ImageView.setTranslationX or View.OnAttachStateChangeListener
It's quite tricky.
I think this is similar to what is done to the drawer handle in new Google Maps app. Don't take my word, not sure. :)
I have written toggle that stays on the edge of the Activity content view.
When the DrawerLayout is dragged, I translated the view on the x-axis by the amount of the minimal child (which is DrawerLayout content view) minus the shadow (if any). Since the shadow casted + content view of the DrawerLayout gives the full measured width of the entire drawer.
I quickly multiply the slided offset and the minimal child and find the x translation.
[Edit: Code has been removed for readability and it has been moved to the link provided below]
In your activity:
mDrawerToggle = new DrawerLayoutEdgeToggle(
this,
mDrawerLayout,
R.drawable.ic_launcher,
R.drawable.ic_launcher,
Gravity.LEFT,
true) {
#Override
public void onDrawerClosed(View view) {
super.onDrawerClosed(view); //must call super
}
#Override
public void onDrawerOpened(View view) {
super.onDrawerOpened(view); //must call super
}
#Override
public void onDrawerSlide(View view, float slideOffset) {
super.onDrawerSlide(view, slideOffset); //must call super
}
};
mDrawerLayout.setDrawerListener(mDrawerToggle);
Creativity boost:
You can add more cosmetics like distance from ActionBar which you can set as margin to the handle.
Also you can mimic "single-zipper effect" by moving the handle up/down along left/right just by translating on the Y axis. :)
Edit: Its available on my GitHub here
Edit 2: For those that can't get the handle appear at the beginning just use mDrawerToggle.setVerticalPostionOffset(0)
I found a way of doing this pretty easily thanks to the Aniqroid library written by Mobistry (SO pseudo)
I use the SlidingTray class which is a copy of android SlidingDrawer but lets you position the drawer to any corner of the screen.
I declared the element via xml
<com.sileria.android.view.SlidingTray
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/drawer"
android:layout_width="match_parent"
android:layout_height="270dp"
android:content="#+id/content"
android:handle="#+id/handle" >
<ImageView
android:id="#+id/handle"
android:layout_width="320dp"
android:layout_height="24dp"
android:background="#drawable/tray_btn" />
<LinearLayout
android:id="#+id/content"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="fill_vertical"
android:orientation="vertical" >
</LinearLayout>
</com.sileria.android.view.SlidingTray>
And just had to call
Kit.init(this);
in my main Activity before inflating the layout.
I thank aniqroid devs!
https://code.google.com/p/aniqroid/