Skip to content

Instantly share code, notes, and snippets.

@Sottti
Last active November 7, 2019 09:20
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Sottti/5d19c968fec7c55b02bb to your computer and use it in GitHub Desktop.
Save Sottti/5d19c968fec7c55b02bb to your computer and use it in GitHub Desktop.
Navigation Drawer Sizing according to Material Design
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/main_activity_rootLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<!-- The main content view -->
{...}
<!-- The navigation drawer -->
<include
layout="@layout/navigation_drawer"/>
</android.support.v4.widget.DrawerLayout>
{...}
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.content.Context;
import android.content.Intent;
import android.graphics.PorterDuff;
import android.os.Bundle;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.widget.Toolbar;
import android.view.Gravity;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.android.volley.toolbox.NetworkImageView;
{...}
/**
* This is the main activity of the application.
* Top hierarchy level.
* Holds the navigation drawer.
*
* Uses ScrimInsetsFrameLayout from Google http://goo.gl/07TJnm
* Uses Google Volley from Google http://goo.gl/b9sqAD
* Uses CircleImageView http://goo.gl/mV22sU
*
* @author https://plus.google.com/+PabloCostaTirado/posts
*/
public class MainActivity extends ActionBarActivity
{
private final static double sNAVIGATION_DRAWER_ACCOUNT_SECTION_ASPECT_RATIO = 9d/16d;
private DrawerLayout mDrawerLayout;
private FrameLayout mFrameLayout_AccountView;
private ScrimInsetsFrameLayout mScrimInsetsFrameLayout;
{...}
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
initialization();
}
/**
* Bind, create, initialise and set up the resources
*/
private void initialization()
{
{...}
// Navigation Drawer
mFrameLayout_AccountView = (FrameLayout) findViewById(R.id.navigation_drawer_account_view);
mDrawerLayout = (DrawerLayout) findViewById(R.id.main_activity_rootLayout);
mDrawerLayout.setStatusBarBackgroundColor(getResources().getColor(R.color.primaryDark));
mScrimInsetsFrameLayout = (ScrimInsetsFrameLayout) findViewById(R.id.main_activity_navigation_drawer_rootLayout);
{...}
// Navigation Drawer layout width
final DrawerLayout.LayoutParams params = (DrawerLayout.LayoutParams) mScrimInsetsFrameLayout.getLayoutParams();
int possibleMinDrawerWidth = UtilsDevice.getScreenWidth(this) -
UtilsMisc.getThemeAttributeDimensionSize(this, android.R.attr.actionBarSize);
int maxDrawerWidth = getResources().getDimensionPixelSize(R.dimen.navigation_drawer_max_width);
params.width = Math.min(possibleMinDrawerWidth, maxDrawerWidth);
mScrimInsetsFrameLayout.setLayoutParams(params);
mFrameLayout_AccountView.getLayoutParams().height = (int) (params.width
* sNAVIGATION_DRAWER_ACCOUNT_SECTION_ASPECT_RATIO);
{...}
}
}
<?xml version="1.0" encoding="utf-8"?>
<!-- Needs to have clickable to true to make the layout clickable http://goo.gl/t9fokh-->
<com.gist.navDrawer.sizing.ScrimInsetsFrameLayout
android:id="@+id/main_activity_navigation_drawer_rootLayout"
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"
android:layout_gravity="start"
android:background="@color/navigation_drawer_background"
android:clickable="true"
android:fitsSystemWindows="true"
app:insetForeground="@color/nav_drawer_inset_foreground">
<LinearLayout
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"
android:orientation="vertical">
<FrameLayout
android:id="@+id/navigation_drawer_account_view"
android:layout_width="match_parent"
android:layout_height="@dimen/navigation_drawer_account_section_default_height"
android:clickable="true"
android:foreground="?selectableItemBackground"
tools:layout_height="@dimen/navigation_drawer_account_section_default_height">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:foreground="@color/black_alpha_50">
<com.android.volley.toolbox.NetworkImageView
android:id="@+id/navigation_drawer_user_account_picture_cover"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/image_nav_drawer_account_background"
android:scaleType="centerCrop"
tools:ignore="ContentDescription" />
</FrameLayout>
<RelativeLayout
android:id="@+id/navigation_drawer_account_section"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/nav_drawer_vertical_spacing_listing"
android:paddingEnd="@dimen/nav_drawer_vertical_keyline_right"
android:paddingLeft="@dimen/nav_drawer_vertical_keyline_left"
android:paddingRight="@dimen/nav_drawer_vertical_keyline_right"
android:paddingStart="@dimen/nav_drawer_vertical_keyline_left">
<LinearLayout
android:id="@+id/navigation_drawer_account_information"
android:layout_width="wrap_content"
android:layout_height="@dimen/navigation_drawer_account_information_height"
android:layout_alignParentBottom="true"
android:gravity="center_vertical"
android:orientation="vertical">
<TextView
android:id="@+id/navigation_drawer_account_information_display_name"
style="@style/NavDrawerAccountInfoText"
tools:fontFamily="sans-serif-medium"
tools:text="@string/tools_text_account_information_username"/>
<TextView
android:id="@+id/navigation_drawer_account_information_email"
style="@style/NavDrawerAccountInfoText"
tools:fontFamily="sans-serif"
tools:text="@string/tools_text_account_information_email"/>
</LinearLayout>
<de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/navigation_drawer_user_account_picture_profile"
android:layout_width="@dimen/navigation_drawer_profile_image_size"
android:layout_height="@dimen/navigation_drawer_profile_image_size"
android:layout_above="@id/navigation_drawer_account_information"
android:layout_marginBottom="@dimen/spacing_4"
android:src="@drawable/ic_account_circle_white_48dp"
tools:src="@drawable/tools_user_profile_photo" />
</RelativeLayout>
</FrameLayout>
<!-- Place here your Nav Drawer items -->
</LinearLayout>
</com.gist.navDrawer.sizing.ScrimInsetsFrameLayout>
{...}
import android.content.Context;
import android.util.DisplayMetrics;
/**
* This utility class is for device related stuff.
*
* @author https://plus.google.com/+PabloCostaTirado/posts
*/
public class UtilsDevice
{
/**
* Returns the screen width in pixels
*
* @param context is the context to get the resources
*
* @return the screen width in pixels
*/
public static int getScreenWidth(Context context)
{
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
return metrics.widthPixels;
}
/**
* Returns the size in pixels of an attribute dimension
*
* @param context the context to get the resources from
* @param attr is the attribute dimension we want to know the size from
*
* @return the size in pixels of an attribute dimension
*/
public static int getThemeAttributeDimensionSize(Context context, int attr)
{
TypedArray a = null;
try
{
a = context.getTheme().obtainStyledAttributes(new int[] { attr });
return a.getDimensionPixelSize(0, 0);
}
finally
{
if(a != null)
{
a.recycle();
}
}
}
}
@Fuhrmann
Copy link

Wel, after so many tries, I came up with one solution. I don't know if it has some performance problem or something like this, but for now it works:

    private final static double DRAWER_COVER_ASPECT_RATIO = 9d / 16d;
    // Get the drawer layout
    DrawerLayout mDrawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    // Get the header
    final FrameLayout navHeader = (FrameLayout) mNavDrawer.getHeaderView(0);
    ViewTreeObserver vto = mNavDrawer.getViewTreeObserver();
    // When the layout has been draw
    vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            // Remove this listener
            mNavDrawer.getViewTreeObserver().removeOnGlobalLayoutListener(this);
            // Get the calculated width of the drawer
            int width = mNavDrawer.getMeasuredWidth();    
            // Set header's height using aspectio ratio
            navHeader.getLayoutParams().height = (int) (width * DRAWER_COVER_ASPECT_RATIO);
            // Update the layout on screen
            navHeader.requestLayout();
        }
    });

By the way, I'm using NavigationView from support library, which calculates for me automatically the best width.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment