I have a DrawerLayout with three sections: one of them is a two pane layout implemented like the android studio template, so two fragment, one next to the other, contained in a LinearLayout. Here is the layout:
<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">
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:baselineAligned="false"
android:orientation="vertical">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:baselineAligned="false"
android:id="#+id/twoPaneLayut"
android:divider="?android:attr/dividerHorizontal"
android:showDividers="middle">
<FrameLayout
android:id="#+id/alarm_list_container"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<FrameLayout
android:id="#+id/alarm_detail_container"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2" />
</LinearLayout>
</FrameLayout>
<ListView
android:id="#+id/left_drawer"
android:layout_width="#dimen/drawer_width"
android:layout_height="match_parent"
android:layout_gravity="start"
android:choiceMode="singleChoice"
android:divider="#android:color/transparent"
android:dividerHeight="0dp"
android:background="#111" />
Now, the other sections are composed by a single Fragment so I was trying to replace the main content of the external FrameLayout with a FragmentTransaction.
The problem is that the inner LinearLayout obviously is not removed.
So what is the best strategy to follow? removing programmatically the LinearLayout? Setting its visibilty to GONE?
FrameLayout will not work with weightSum it is by design meant to fill up your layout. Try using a LinearLayout or RelativeLayout instead.
Secondly, when it comes to swapping all your content, you have a few options.
Option 1
Use one FrameLayout, for your 2 panel layout create a Fragment that contains 2 Fragments. Yes, you can have Fragments within Fragments.
In this scenario, your Activity's layout will look more like the implementation that Google recommends and it is your fragments layout that will contain the 2 panel layout.
Option 2
You can swap out one of the LinearLayouts for your fragment and hide the other LinearLayout. There is no reason you can only swap a FrameLayout for a fragment, you should be able to swap out a LinearLayout for a Fragment as well.
Option 3
The DrawerLayout implementation is just a recommendation. You can move the layout for your drawer into a fragment and use a different Activity for your different layouts. To be clear, instead of a ListView for your drawer, you will have a fragment. In this scenario, put all the code to add the toggle controls in a helper class so you can easily reuse it, your drawer view will be in a fragment and hence it will be easier to include in multiple activities.
I've included an example of how to do this, because you need to wrap your navigation drawer fragment in a frame layout and give the frame layout the layout_gravity property otherwise the fragment will fill up the whole screen and not close.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<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" >
<!-- The main content view -->
<FrameLayout
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- The navigation drawer -->
<FrameLayout
android:id="#+id/nav_drawer_container"
android:layout_gravity="start"
android:layout_width="240dp"
android:layout_height="match_parent" >
<fragment
android:id="#+id/nav_drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
class="com.alimuzaffar.myapp.fragment.NavigationMenuFragment" />
</FrameLayout>
</android.support.v4.widget.DrawerLayout>
The code for the toggle helper can be something like the setupNavigationDrawer() method below. Just call this code from the onCreate() of any activity you want to have the navigation drawer.
public static void setupNavigationDrawer() {
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
if (mDrawerLayout != null) {
// ActionBarDrawerToggle ties together the the proper interactions
// between the sliding drawer and the action bar app icon
mDrawerToggle = new ActionBarDrawerToggle(this, /* host Activity */
mDrawerLayout, /* DrawerLayout object */
R.drawable.ic_drawer, /* nav drawer image to replace 'Up' caret */
R.string.drawer_open, /* "open drawer" description for accessibility */
R.string.drawer_close /* "close drawer" description for accessibility */
) {
#Override
public void onDrawerClosed(View view) {
getSupportActionBar().setTitle(mTitle);
supportInvalidateOptionsMenu(); // creates call
// to
// onPrepareOptionsMenu()
}
#Override
public void onDrawerOpened(View drawerView) {
getSupportActionBar().setTitle("");
supportInvalidateOptionsMenu(); // creates call
// to
// onPrepareOptionsMenu()
}
};
// set a custom shadow that overlays the main content when the drawer opens
mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
mDrawerLayout.setDrawerListener(mDrawerToggle);
}
}
Related
I am using Android Design Support Library to get navigation drawer pattern. I have following main activity layout:
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res/pl.dzielins42.skinflint.android"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="http://schemas.android.com/apk/res-auto"
tools:ignore="MergeRootFrame" >
<!-- The main content view -->
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- The navigation drawer -->
<android.support.design.widget.NavigationView
android:id="#+id/drawer_navigation_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="#layout/view_nav_drawer_header"
app:menu="#menu/drawer" />
</android.support.v4.widget.DrawerLayout>
The container layout is where I inflate my fragments. Some of the fragments have Toolbar in their layouts. I use navigation drawer to move between these fragments. In each of the fragments with Toolbar I set it as activity's actionbar using setSupportActionBar, and later
supportActionBar.setDisplayHomeAsUpEnabled(true);
supportActionBar.setHomeButtonEnabled(true);
The problem is that on the first fragment (inflated in activity's onCreate) the "hamburger" icon is displayed properly, but after I change the fragment to another fragment with Toolbar, the icon changes to standard back-arrow.
I have tried to fix it by using ActionBarDrawerToggle (v7) and calling syncState in onDrawerClosed. This fixes it partially, as the "hamburger" icon is set but only after drawer is fully closed, so while it is still closing, back arrow-icon is visible.
Can someone provide better solution?
set the ActionBarDrawerToggle properly:
mDrawerToggle.setDrawerIndicatorEnabled(true);
I'd like to create a navigation drawer effect, but rather than the drawer sliding out from the left, it must be "behind" the main view, so the item that slides is the view itself (i.e. to the right) - the drawer doesn't move at all, but is "revealed" by sliding the main view out of the way. The finger swipe (and tap on hamburger icon) action is the same as with the drawer, just the reveal effect is different.
The way the main view moves is the same to what can be achieved here
How to move main content with Drawer Layout left side
but in my case I want the "drawer" to stay statically underneath the main view.
I've achieved the desired effect by overlaying views and making the drawer transparent - of course this means that the drawer is no longer used for navigation; just for effect. Using the code in the above link
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/whole_frame"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- everything here is now the new "drawer" -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="BOO I am hiding!"
android:id="#+id/tv2"
android:layout_gravity="left|top" />
<!-- /everything here is now the new "drawer" -->
<android.support.v4.widget.DrawerLayout
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<!-- The This is the main content frame -->
<FrameLayout
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/colorPrimary">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="MOOOOOO!"
android:id="#+id/textView"
android:layout_gravity="left|top" />
</FrameLayout>
<!-- The see-through navigation drawer -->
<RelativeLayout
android:layout_width="280dp"
android:layout_height="match_parent"
android:id="#+id/left_drawer"
android:clickable="false"
android:background="#drawable/transparent_bg" <!-- #00FFFFFF -->
android:layout_gravity="start">
</RelativeLayout>
</android.support.v4.widget.DrawerLayout>
Everything is perfect except that id/tv2 (or other items on that layer) are not clickable when the "drawer" is opened.
I've tried:
1)
Making the layouts above not clickable (drawer_layout, content_frame and left_drawer setClickable(false) without effect).
2)
The code in the above link moves the content_frame on X axis and not the drawyer_layout - I tried moving drawer_layout instead of the frame - this doesn't work properly as you can no longer click on the far right to close the drawer again.
3)
Changing the android:layout_width of the drawer_layout to fill_parent, but this is still a problem as it is not the layer being moved out of the way.
My guess is that DrawerLayout ( android.support.v4.widget.DrawerLayout ) is not meant to be above another layout and I might need to create my own drawer to achieve the desired effect - any ideas or suggestions would be great.
I believe I've figured out a relatively simple solution. The following DrawerLayout setup is pretty standard - i.e., the content ViewGroup first, the drawer View last, using standard attributes, etc. Additionally, a technique similar to that shown in your posted link is used to slide the content with the drawer.
The trick in the example is the setup of the drawer itself. We're going to use two nested ViewGroups - the outer one is the regular sliding drawer View; the inner, a ViewGroup for the actual drawer contents. We'll then slide the inner content ViewGroup opposite the direction of the drawer's slide using a DrawerListener (an ActionBarDrawerToggle in our example), making the drawer appear static against the left side.
The example DrawerLayout, main.xml. Note the standard drawer attributes set on the drawer_container ViewGroup:
<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"
android:background="#000000">
<FrameLayout
android:id="#+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#cccccc" />
<FrameLayout
android:id="#+id/drawer_container"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start">
<LinearLayout
android:id="#+id/drawer_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:id="#+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:src="#drawable/ic_launcher" />
...
</LinearLayout>
</FrameLayout>
</android.support.v4.widget.DrawerLayout>
This example Activity shows the few extra lines we need to add to a regular Navigation Drawer setup. Other than getting references to the Views, the main bit is in the ActionBarDrawerToggle's onDrawerSlide() method:
public class MainActivity extends Activity {
ActionBarDrawerToggle toggle;
DrawerLayout drawerLayout;
View drawerContainer;
View drawerContent;
View mainContent;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
drawerContainer = findViewById(R.id.drawer_container);
drawerContent = findViewById(R.id.drawer_content);
mainContent = findViewById(R.id.main_content);
toggle = new ActionBarDrawerToggle(...) {
#Override
public void onDrawerSlide(View drawer, float slideOffset) {
super.onDrawerSlide(drawer, slideOffset);
drawerContent.setTranslationX(drawerContainer.getWidth() * (1 - slideOffset));
mainContent.setTranslationX(drawerContainer.getWidth() * slideOffset);
}
};
drawerLayout.addDrawerListener(toggle);
}
}
Keep in mind that DrawerLayout restores the drawer opened/closed state during Activity re-creation, so you might need to account for that, for example, during orientation changes, etc.
I like to open sliding drawer from any out side button not with its child button handle , If any one have any answer or tutorial please help me?
I want to open a slider from any other button in layout not from handle button ... not from its child button ??
like if I have any button in xml.. and when I click on it slider open .
Android Sliding Up View
please check it and see the screen shot I don't have that much reputation so that I upload Image
I want to click on show button the slider opens not on slider
The "Navigation Drawer" can be opened programmatically with mDrawerLayout.openDrawer(mDrawerContentLayout). Here's some info how to set it up:
private DrawerLayout mDrawerLayout;
private RelativeLayout mDrawerContentLayout;
Get the reference to drawerView in your Activity onCreate():
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawerContentLayout = (RelativeLayout) findViewById(R.id.drawer_content);
Call this on your button click when you want drawer opened:
mDrawerLayout.openDrawer(mDrawerContentLayout);
I used a RelativeLayout as content view of my drawer, but you can use any which suits you. Just remember, the mDrawerLayout layout should be inside mDrawerLayout (which is actually a android.support.v4.widget.DrawerLayout) and should have the android:layout_gravity="start" attribute.
Here's the (abbreviated) activity layout that I used:
<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" >
<android.support.v4.view.ViewPager
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<android.support.v4.view.PagerTitleStrip
android:id="#+id/pager_title_strip"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:background="#33b5e5"
android:paddingBottom="4dp"
android:paddingTop="4dp"
android:textColor="#fff" />
</android.support.v4.view.ViewPager>
<RelativeLayout
android:id="#+id/drawer_content"
android:layout_width="#dimen/nav_drawer_width"
android:layout_height="match_parent"
android:layout_gravity="start" >
<ListView
... />
</android.support.v4.widget.DrawerLayout>
You can find more details in the API documentation, the developer docs and the design patterns.
Okay, if you want to open slider on it's button's click then use below code.
sliding_menu = (Button) findViewById(R.id.slidingMenu);
sliding_menu.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
menu.showMenu();
}
});
What I want is to show the bar that is hidden on the left, when a user enters a layout, the idea is that you know that there is that bar without having to put an icon on the actionbar that signal its existence
If you want to open the navigationdrawer the first time the activity is created you can simply do something like this:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_drawer_activity);
drawer = (ListView) findViewById(R.id.left_drawer); // the drawer itself (ListView for example)
drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); // the drawer layout itself
drawerLayout.openDrawer(drawer);
}
Your xml may look something like this:
<?xml version="1.0" encoding="utf-8"?>
<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"
android:background="?attr/background_activity_color">
<!-- The main content view -->
<FrameLayout
android:id="#+id/fragmentFrame"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- The navigation drawer -->
<ListView
android:id="#+id/left_drawer"
android:layout_width="250dp"
android:layout_height="match_parent" />
</android.support.v4.widget.DrawerLayout>
I am using a Navigation Drawer as shown here: Android Example. At the moment, the Actionbar is static, it does not move when the Drawer opens/closes (only it's title changes). How can I apply this effect:
I want the entire ActionBar to move with the Sliding fragment. And the Name and Buttons on the ActionBar to remain as they are. Please tell me what code you would need to see.
ALSO, Question 2:
When you're using DrawerLayout you include in the xml the FrameLayout (for the content_frame) and ListView (where you add your navigation settings... In that Drawer, can you modify the layout so that you can add not just ListView but other Views aswell? On top or bottom of the ListView? Something like this:
I want to add ImageView (not hyperlinked, just Image) and Additional TextViews (for instructions) not hyperlinked.
Consider using SlidingMenu library from GitHub. It's powerfull flexible and also you can do ANYTHING with it. You can slide the actionbar by just simply calling:
setSlidingActionBarEnabled(true);
https://github.com/jfeinstein10/SlidingMenu
To the second point: Sure you can. The NavigationDrawer is not limited to use just the ListView. Just use a ViewGroup like a LinearLayout as the 2nd child of the DrawerLayout and put in any View you want.
But keep in mind to add this line in the specification of your LinearLayout:
<LinearLayout
...
android:layout_gravity="start"
...>
<TextView..../>
<ImageView...../>
<LinearLayout/>
I think this is what you are looking for. This is the code from sample source code of the example you are refering.
// ActionBarDrawerToggle ties together the the proper interactions
// between the sliding drawer and the action bar app icon
mDrawerToggle = new ActionBarDrawerToggle(this, /* host Activity */
mDrawerLayout, /* DrawerLayout object */
R.drawable.ic_drawer, /* nav drawer image to replace 'Up' caret */
R.string.drawer_open, /* "open drawer" description for accessibility */
R.string.drawer_close /* "close drawer" description for accessibility */
) {
public void onDrawerClosed(View view) {
getActionBar().setTitle(mTitle);
invalidateOptionsMenu(); // creates call to
// onPrepareOptionsMenu()
}
public void onDrawerOpened(View drawerView) {
getActionBar().setTitle(mDrawerTitle);
invalidateOptionsMenu(); // creates call to
// onPrepareOptionsMenu()
}
};
mDrawerLayout.setDrawerListener(mDrawerToggle);
I think you can use this kind of layout to implement the some view on the top of the drawer list view..
<!-- The main content view -->
<FrameLayout
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</FrameLayout>
<!-- The navigation drawer -->
<RelativeLayout
android:id="#+id/drawerLeft"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:background="#191919" >
<EditText
android:id="#+id/edit_Search"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FC3A3B"
android:hint=" Search"
android:padding="10dp"
android:textColor="#ffffff"
android:textColorHint="#ffffff" >
<requestFocus />
</EditText>
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/edit_Search"
android:layout_alignParentRight="true"
android:layout_marginBottom="5dp"
android:layout_marginRight="20dp"
android:src="#drawable/icon_small_search" />
<ListView
android:id="#+id/drawer_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/edit_Search"
android:background="#191919"
android:choiceMode="singleChoice"
android:divider="#000000"
android:dividerHeight="1dp" >
</ListView>
</RelativeLayout>