I've recently tried to implement a Material Design overhaul in one of my apps, and came across this library from HeinrichReimer (material-design) on implementing the Navigation Drawer for Material Design.
However, I'm getting a problem with showing the Profile part of the Drawer. I've implemented it as shown in the guide:
drawer.setProfile(
new DrawerProfile()
.setAvatar(getResources().getDrawable(R.drawable.zild))
.setBackground(getResources().getDrawable(R.drawable.zild))
.setName(getString(R.string.app_name))
.setDescription(getString(R.string.hello_blank_fragment))
.setOnProfileClickListener(new DrawerProfile.OnProfileClickListener() {
#Override
public void onClick(DrawerProfile drawerProfile) {
// do nothing yet
}
})
);
.. and I've also added some drawer items
drawer.addItem(
new DrawerItem()
.setImage(getResources().getDrawable(R.drawable.ic_launcher))
.setTextPrimary("My Entries")
.setTextSecondary("Yay Entries!")
.setOnItemClickListener(new DrawerItem.OnItemClickListener() {
#Override
public void onClick(DrawerItem drawerItem, int i) {
Toast.makeText(HomeActivity.this, "Clicked first item", Toast.LENGTH_LONG).show();
}
})
);
drawer.addDivider();
drawer.addItem(new DrawerItem()
.setImage(getResources().getDrawable(R.drawable.ic_launcher))
.setTextPrimary("Settings")
.setTextSecondary("Woohoo Settings!")
.setOnItemClickListener(new DrawerItem.OnItemClickListener() {
#Override
public void onClick(DrawerItem drawerItem, int i) {
Toast.makeText(HomeActivity.this, "Clicked second item", Toast.LENGTH_LONG).show();
}
})
);
Below is my layout xml:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<android.support.v7.widget.Toolbar
android:id="#+id/timelog_toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/timelog_primary"
android:minHeight="?attr/actionBarSize"
app:theme="#style/ThemeOverlay.AppCompat.ActionBar" />
<android.support.v4.widget.DrawerLayout
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".HomeActivity">
<!-- The main content view -->
<FrameLayout
android:id="#+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
<!-- The navigation drawer -->
<com.heinrichreimersoftware.material_drawer.DrawerView
android:id="#+id/drawer"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true" />
</android.support.v4.widget.DrawerLayout>
</LinearLayout>
I'm not able to post images yet (reputation too low), so below is a screenshot of my app uploaded to IMGUR:
http://i.imgur.com/IaFPzD1.png
Would anybody happen to implement this library? And were you able to show the profile part?
This is indeed an issue with current Version, i have solved it by updating the code with this pull request:
https://github.com/HeinrichReimer/material-drawer/pull/8
Related
MY PROBLEM:
My current unit test "onClickSkipButtonAndVerifyAppExists" is failing because I'm not able to click on the skip button which is within the include layout="#layout/navigation_bar". The layout for it is basically a skip button on the left and a next button on the right. I'm suspecting that the reason why it's failing it's because it is not able to click on a view from an include tag.
I have the following scenario:
#RunWith(AndroidJUnit4.class)
#LargeTest
public class MainActivityTest {
#Rule
public ActivityTestRule<MainActivity> mActivityRule = new ActivityTestRule<MainActivity>(MainActivity.class, true, true) {
#Override
protected void afterActivityLaunched() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
#Override
protected void afterActivityFinished() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
#Test
public void onClickSkipButtonAndVerifyAppExists() {
onView(withId(R.id.navigation_bar_skip)).perform(click());
}
}
Also, my XML layout file for that specific test is the following:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ignite="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="false">
<android.support.design.widget.CoordinatorLayout
android:id="#+id/main_activity_outer_coordinator"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#+id/bottom_bar">
<RelativeLayout
android:id="#+id/main_activity_inner"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<android.support.design.widget.AppBarLayout
android:id="#+id/toolbar_app_bar"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:theme="#style/AppTheme.AppBarOverlay"
android:background="#color/header_footer">
<com.digitalturbine.igniteui.view.DynamicLayoutToolbar
android:id="#+id/main_toolbar"
android:layout_height="wrap_content"
android:layout_width="match_parent"
ignite:popupTheme="#style/AppTheme.PopupOverlay"
ignite:contentInsetStart="0dp"
android:background="#drawable/toolbarBackground"
ignite:layoutType="left_two_line_title_w_icon"/>
</android.support.design.widget.AppBarLayout>
<FrameLayout
android:id="#+id/content_container"
android:layout_below="#+id/toolbar_app_bar"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
<View
android:id="#+id/main_activity_overlay"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/wizard_disabled_overlay"
android:visibility="gone"/>
</android.support.design.widget.CoordinatorLayout>
<LinearLayout
android:id="#+id/bottom_bar"
android:layout_width="match_parent"
android:orientation="horizontal"
android:layout_height="#dimen/navigation_bar_height"
android:layout_alignParentBottom="true">
<include layout="#layout/navigation_bar"/>
</LinearLayout>
<FrameLayout
android:id="#+id/full_screen_content"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
SUGGESTIONS:
If anybody can provide insights and not think that this is the actual problem, please do. I tried multiple things before concluding that this might be the problem, but again, any thoughts are welcomed.
First you should manually check if skip button is shown and it works (you can click on it). By the look of your XML code, frame layout full_screen_content is going over bottom bar so that could cause a problem.
If the button is visible and clickable, check again if id navigation_bar_skip is correct. Or you can try to use withText method instead of withId...
Also, you don't need to override methods afterActivityLaunched and afterActivityFinished. Test will not start until activity is ready. If you want this pause, you can put it inside #Test method. And for initialization, you should use #Before and #After, that will run before and after every test.
I have a quite simple layout and I animate the showing/hiding of the toolbars with the appended functions. I'm using AppCompat and Toolbars...
PROBLEM
One person reported that the top toolbar is never shown. Any ideas why? What could be the reason? It's working fine on my phone and others...
Function
public void showHideToolbar(boolean forceHide, boolean animate)
{
L.d(this, "showHideToolbar: " + mShowToolbar);
toolbar.clearAnimation();
toolbar2.clearAnimation();
if (mShowToolbar || forceHide)
{
if (animate) {
toolbar.animate().translationY(-toolbar.getBottom()).setInterpolator(new AccelerateInterpolator()).start();
toolbar2.animate().translationY(toolbar2.getBottom()).setInterpolator(new AccelerateInterpolator()).start();
}
else
{
toolbar.setTranslationY(-toolbar.getBottom());
toolbar2.setTranslationY(toolbar2.getBottom());
}
mShowToolbar = false;
}
else
{
if (animate) {
toolbar.animate().translationY(0).setInterpolator(new DecelerateInterpolator()).start();
toolbar2.animate().translationY(0).setInterpolator(new DecelerateInterpolator()).start();
}
else
{
toolbar.setTranslationY(0);
toolbar2.setTranslationY(0);
}
mShowToolbar = true;
}
}
Layout
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/flMain"
android:background="?attr/main_background_color"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:elevation="4dp"
app:theme="?actionBarThemeStyle"
app:popupTheme="?actionBarPopupThemeStyle" />
<android.support.v4.view
android:id="#+id/vpSlides"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar2"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/bottom_bar_background"
android:elevation="0dp"
android:layout_alignParentBottom="true"
android:gravity="top|start"
app:theme="?actionBarThemeStyle"
app:popupTheme="?actionBarPopupThemeStyle" >
</android.support.v7.widget.Toolbar>
</RelativeLayout>
It seems like, even if you make a toolbar to an actionbar, you have to respect layout ordering in the xml. setSupportActionBar won't bring the action bar on top of the main layout...
So the simple solution was to reorder the toolbar to being under the content...
I never ad problems yet as normally I show the content underneath the toolbar, here I didn't want to that and therefore faced the problem
I have faced with weird problem. I am using navigation drawer from support library in my app.
Here is layout
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/navigation_drawer"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/linear_layout_main_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar_main"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
android:visibility="gone" />
</LinearLayout>
<ScrollView
android:id="#+id/layout_drawer_left"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fillViewport="true">
</ScrollView>
<ScrollView
android:id="#+id/layout_drawer_right"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_gravity="end"
android:fillViewport="true" />
</android.support.v4.widget.DrawerLayout>
And I find all views after setting content view.
private FrameLayout mLeftDrawerContainer, mRightDrawerContainer;
private DrawerLayout mDrawerMainLayout;
mDrawerMainLayout = (DrawerLayout) rootBaseView.findViewById(R.id.navigation_drawer);
mLeftDrawerContainer = (ScrollView) rootBaseView.findViewById(R.id.layout_drawer_left);
mRightDrawerContainer = (ScrollView) rootBaseView.findViewById(R.id.layout_drawer_right);
I have tried a lot of ways in order to close drawer, it closes it visually, I mean everything is ok, drawer slowly left the screen and stays closed, but from perspective of code it always return true.
protected boolean isDrawersOpened() {
boolean rightDrawerOpened = mDrawerMainLayout.isDrawerOpen(mRightDrawerContainer);
boolean leftDrawerOpened = mDrawerMainLayout.isDrawerOpen(mLeftDrawerContainer);
return rightDrawerOpened || leftDrawerOpened ;
}
Always true
public void closeDrawer() {
mDrawerMainLayout.closeDrawer(GravityCompat.END);
mDrawerMainLayout.closeDrawer(GravityCompat.START);
mDrawerMainLayout.closeDrawer(mRightDrawerContainer);
mDrawerMainLayout.closeDrawer(mLeftDrawerContainer);
mDrawerMainLayout.closeDrawers();
}
So it should work, but returns always true.
If it is bug in suppor library, no problems I will wait and use boolean variable inside activity to indicate this, but maybe someone dealt with the same problem.
Thank for any help and ideas in advance.
Sorry, for my inattention.
I have made a mistake in my code
if (hasLeftDrawer) {
setupLeftDrawer();
} else {
mDrawerMainLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_OPEN, mLeftDrawerContainer);
}
if (hasRightDrawer) {
setupRightDrawer();
} else {
mDrawerMainLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_OPEN, mRightDrawerContainer);
}
Should be
if (hasLeftDrawer) {
setupLeftDrawer();
} else {
mDrawerMainLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED, mLeftDrawerContainer);
}
if (hasRightDrawer) {
setupRightDrawer();
} else {
mDrawerMainLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED, mRightDrawerContainer);
}
I am using the support
FloatingActionButton
Snackbar
CoordinatorLayout
I need the CoordinatorLayout so that if SnackBar is shown the FloatingActionButton moves up to make room for the Snackbar. For better understanding check this video.
I am using SnackBar for double-back to exit the application, but the SnackBar can be dismissed.
Is there a way to disable the dismiss on the SnackBar?
Snackbar snackbar = Snackbar.make(view, R.string.press_back_again_to_exit, Snackbar.LENGTH_SHORT);
snackbar.setAction(R.string.ok, new View.OnClickListener() {
#Override
public void onClick(View v)
{
}
});
snackbar.setActionTextColor(getResources().getColor(R.color.white));
View view = snackbar.getView();
view.setBackgroundColor(getResources().getColor(R.color.orange_warning));
snackbar.show();
Layout
<android.support.design.widget.CoordinatorLayout
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="match_parent">
<android.support.v4.widget.DrawerLayout
android:id="#+id/drawer_layout"
xmlns:sothree="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/white"
android:fitsSystemWindows="true">
<com.sothree.slidinguppanel.SlidingUpPanelLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="bottom"
sothree:umanoFadeColor="#android:color/transparent"
sothree:umanoPanelHeight="100dp"
sothree:umanoShadowHeight="4dp">
<!-- Toolbar and main content -->
<LinearLayout
android:id="#+id/toolbar_and_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<include layout="#layout/toolbar"/>
<!-- Your content layout -->
<FrameLayout
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"/>
</LinearLayout>
<!-- Sliding up panel layout -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/darker_grey"
android:orientation="vertical">
...
</LinearLayout>
</com.sothree.slidinguppanel.SlidingUpPanelLayout>
<!-- Navigation drawer -->
<ExpandableListView
android:id="#+id/lv_left_drawer"
android:layout_width="280dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#color/white"
android:childDivider="#android:color/transparent"
android:clickable="true"
android:divider="#color/divider_color"
android:dividerHeight="0.6dp"
android:fadeScrollbars="true"
android:groupIndicator="#null"
android:listSelector="#drawable/button_drawer_child_selector"
android:scrollbarSize="0dp"/>
</android.support.v4.widget.DrawerLayout>
<android.support.design.widget.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right|bottom"
android:layout_marginBottom="#dimen/floating_action_button_margin"
android:layout_marginRight="#dimen/floating_action_button_margin"
android:src="#drawable/ic_add"
android:visibility="invisible"
app:backgroundTint="#color/orange"
app:borderWidth="0dp"
app:elevation="6dp"
app:fabSize="normal"/>
</android.support.design.widget.CoordinatorLayout>
P.S.
I am aware of this GitHub library, that has this functionality, but is there a 'native' way to do it?
Snackbar now has actual support disabling swipe to dismiss using the setBehavior method. The great thing here is that before you would always lose some behaviors which are now preserved. You'll also want to use Snackbar.LENGTH_INDEFINITE
Note that the package moved so you have to import the "new" Snackbar in the snackbar package.
Snackbar.make(view, stringId, Snackbar.LENGTH_INDEFINITE)
.setBehavior(new NoSwipeBehavior())
.show();
class NoSwipeBehavior extends BaseTransientBottomBar.Behavior {
#Override
public boolean canSwipeDismissView(View child) {
return false;
}
}
You can alter the duration of Snackbar to be shown. It will be similar to disable dismiss.
int LENGTH_INDEFINITE Show the Snackbar indefinitely.
Check docs.
if it does not work
For this then there is only one way, Implement Your custom Snackbar and override dismiss() method and in that do nothing. :) As dismiss() is a public API.
The answer about just using LENGTH_INDEFINITE is not sufficient.
It is only non-dismissable when the Snackbar is no child of CoordinatorLayout.
When it is a child, you can still swipe away the SnackBar.
What you can do in that case is listen for the dismiss swipe and simply re-show the Snackbar.
public void showAnnoyingSnackBar(View root, String text) {
Snackbar.make(root, text, Snackbar.LENGTH_INDEFINITE)
.setCallback(new Snackbar.Callback() {
#Override public void onDismissed(Snackbar snackbar, int event) {
// recursively call this method again when the snackbar was dismissed through a swipe
if (event == DISMISS_EVENT_SWIPE) showAnnoyingSnackBar(root, text);
}
})
.show();
}
I noticed that when show() method is called, SnackbarLayout is not fully initialised yet.
To lock dissmiss we have to clear behavior after SnackbarLayout initialisation.
the best place to do this is for example in OnPreDrawListener of SnackbarLayout
final Snackbar snack = Snackbar.make(getView(), "I can't be dissmiss", Snackbar.LENGTH_INDEFINITE);
snack.show();
snack.getView().getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
#Override
public boolean onPreDraw() {
snack.getView().getViewTreeObserver().removeOnPreDrawListener(this);
((CoordinatorLayout.LayoutParams) snack.getView().getLayoutParams()).setBehavior(null);
return true;
}
});
I was successful in disabling the swipe-sideways-to-dismiss snackbars with the following hack (after calling snackbar.show())
((android.support.design.widget.CoordinatorLayout.LayoutParams) snackbar.getView().getLayoutParams()).setBehavior(null);
So, I have this
btn_menu.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {if(mDrawerLayout.isDrawerVisible(R.id.drawer_layout) == false) {
mDrawerLayout.openDrawer(mDrawerList);
Log.d("False", "" + mDrawerLayout.isDrawerOpen(R.id.drawer_layout));
} else {
mDrawerLayout.closeDrawer(mDrawerLayout);
Log.d("True", "" + mDrawerLayout.isDrawerOpen(R.id.drawer_layout));
}
}
});
On the "btn_menu" click I will open and close the drawer, thing is that no matter what I do the method "isDrawerOpen" will ALWAYS return false. I don't know what else to do.
Here is the layout:
<?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" >
<FrameLayout
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- The navigation drawer -->
<ExpandableListView
android:id="#+id/left_drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#111"
android:choiceMode="singleChoice"
android:divider="#android:color/transparent"
android:dividerHeight="0dp" />
</android.support.v4.widget.DrawerLayout>
Edit: blipinsk answer was right. But I had to change the if test too.
if (mDrawerLayout.isDrawerOpen(Gravity.LEFT)) {
mDrawerLayout.closeDrawer(Gravity.LEFT);
} else {
mDrawerLayout.openDrawer(Gravity.LEFT);
}
When you call isDrawerOpen you need to specify which drawer (there can be two - one on the right and one on the left) you are trying to check.
So in your case it should be:
mDrawerLayout.isDrawerOpen(Gravity.LEFT)