Google recently released the android.support.design.widget.NavigationView widget as part of the com.android.support:design:22.2.0 library, which greatly simplified (and standardises) the process of creating a NavigationDrawer.
However according to the design specs, the list item should be Roboto Medium, 14sp, 87% #000000. The NavigationView exposes no textSize or textStyle to customise this.
What are my options if I'm pedantic about maintaining the correct design specifications using the Google provided NavigationView (or customising it in any other way)?
Create new style at the file app/src/main/res/values/styles.xml
<style name="NavigationDrawerStyle">
<item name="android:textSize">20sp</item><!-- text size in menu-->
<!-- item size in menu-->
<item name="android:listPreferredItemHeightSmall">40dp</item>
<item name="listPreferredItemHeightSmall">40dp</item>
<!-- item padding left in menu-->
<item name="android:listPreferredItemPaddingLeft">8dp</item>
<item name="listPreferredItemPaddingLeft">8dp</item>
<!-- item padding right in menu-->
<item name="android:listPreferredItemPaddingRight">8dp</item>
<item name="listPreferredItemPaddingRight">8dp</item>
</style>
Add it to your main_layout.xml
<android.support.design.widget.NavigationView
...
app:theme="#style/NavigationDrawerStyle"
....>
</android.support.design.widget.NavigationView>
All params of the navigation items (which you can change) are located here (path to file ...\sdk\extras\android\support\design\res\layout\design_navigation_item.xml )
design_navigation_item.xml
<android.support.design.internal.NavigationMenuItemView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="?attr/listPreferredItemHeightSmall"
android:paddingLeft="?attr/listPreferredItemPaddingLeft"
android:paddingRight="?attr/listPreferredItemPaddingRight"
android:drawablePadding="#dimen/navigation_icon_padding"
android:gravity="center_vertical|start"
android:maxLines="1"
android:fontFamily="sans-serif-thin"
android:textSize="22sp"
android:textAppearance="?attr/textAppearanceListItem" />
Also you can override *.xml file (copy file from ...\sdk\extras\android\support\design\res\layout\design_navigation_item.xml), just in your app/src/main/res/layout folder create a layout named the same design_navigation_item.xml.
All layouts which can be Overriden are located here ...\sdk\extras\android\support\design\res\layout\
design_layout_snackbar.xml
design_layout_snackbar_include.xml
design_layout_tab_icon.xml
design_layout_tab_text.xml
design_navigation_item.xml
design_navigation_item_header.xml
design_navigation_item_separator.xml
design_navigation_item_subheader.xml
design_navigation_menu.xml
[UPDATE] Each version of com.android.support:design-{version} lib has different items to override.
Check all what you need in
[UPDATE 04/14/2020]
If you are using com.google.android.material.navigation.NavigationView
then open the class, and you will see:
public NavigationView(#NonNull Context context, #Nullable AttributeSet attrs) {
this(context, attrs, R.attr.navigationViewStyle);
}
So you can use attr navigationViewStyle to set your own style for the NavigationView via theme of your app:
NB: parent theme of AppTheme should be Theme.MaterialComponents
<style name="AppTheme" parent="Theme.MaterialComponents.Light.NoActionBar.Bridge">
...
<item name="navigationViewStyle">#style/AppNavigationViewStyle</item>
...
</style>
<style name="AppNavigationViewStyle" parent="Widget.MaterialComponents.NavigationView">
<item name="itemTextAppearance">#style/AppNavigationViewItemTextAppearance</item>
</style>
<style name="AppNavigationViewItemTextAppearance" parent="#style/TextAppearance.MaterialComponents.Subtitle2">
<item name="android:textSize">18sp</item>
</style>
Just open parent theme to see all <item name attrs for override
Since Android Support Library 22.2.1, Google has changed default textSize of items in NavigationView from 16sp to 14sp, which suits Material Design guideline well. However, in some cases(for example, when you want to support Chinese language), it seems larger textSize is better. Solution is simple:
add app:theme="#style/yourStyle.Drawer" to your NavigationView in your layout.xml
in styles.xml, add android:textSize="16sp" in style yourStyle.Drawer
You can customize everything from text color to size and font in your style.xml
<style name="NavDrawerTextStyle" parent="Base.TextAppearance.AppCompat">
<item name="android:textColor">#color/colorPrimaryDark</item>
<item name="android:textSize">16sp</item>
<item name="android:textStyle">bold</item>
</style>
and then in your NavigationView:
<android.support.v4.widget.DrawerLayout 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:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<android.support.design.widget.NavigationView
...
android:itemTextAppearance="#style/NavDrawerTextStyle"
/>
you can use this attributes inside xml file
app:itemTextAppearance="?android:attr/textAppearanceMedium"
or for small text
app:itemTextAppearance="?android:attr/textAppearance"
or for large text
app:itemTextAppearance="?android:attr/textAppearanceLarge"
This worked for me:
activity_main.xml
<android.support.design.widget.NavigationView
android:id="#+id/navigation_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:theme="#style/NavigationDrawerStyle"
app:headerLayout="#layout/navdrawer_header"
app:menu="#menu/navdrawer_menu" />
styles.xml
<style name="NavigationDrawerStyle">
<item name="android:textSize">16sp</item>
</style>
Scouring through the source code I found this layout file
/platform/frameworks/support/.../design/res/layout/design_drawer_item.xml
with the following attribute
<android.support.design.internal.NavigationMenuItemView
...
android:textAppearance="?attr/textAppearanceListItem"
Which meant all we had to do was to override the textAppearanceListItem style in our project.
res/values/styles.xml
<style name="AppTheme" ... >
...
<item name="textAppearanceListItem">#style/list_item_appearance</item>
</style>
<style name="list_item_appearance">
<item name="android:textSize">14sp</item>
<item name="android:fontFamily">sans-serif-medium</item>
</style>
I'm not totally sure what else this will affect but if anyone has a better answer I'd be happy to accept that instead!
Maybe it might help. Recently I had to do this programmatically.
I used this class:
public class CustomTypefaceSpan extends TypefaceSpan {
private final Typeface newType;
private final float newSp;
public CustomTypefaceSpan(String family, Typeface type, float sp) {
super(family);
newType = type;
newSp = sp;
}
#Override
public void updateDrawState(TextPaint ds) {
applyCustomTypeFace(ds, newType, newSp);
}
#Override
public void updateMeasureState(TextPaint paint) {
applyCustomTypeFace(paint, newType, newSp);
}
private static void applyCustomTypeFace(Paint paint, Typeface tf, float sp) {
int oldStyle;
Typeface old = paint.getTypeface();
if (old == null) {
oldStyle = 0;
} else {
oldStyle = old.getStyle();
}
int fake = oldStyle & ~tf.getStyle();
if ((fake & Typeface.BOLD) != 0) {
paint.setFakeBoldText(true);
}
if ((fake & Typeface.ITALIC) != 0) {
paint.setTextSkewX(-0.25f);
}
paint.setTextSize(sp);
paint.setTypeface(tf);
}
#SuppressWarnings("unused")
public static final Parcelable.Creator<CustomTypefaceSpan> CREATOR = new Parcelable.Creator<CustomTypefaceSpan>() {
#Override
public CustomTypefaceSpan createFromParcel(Parcel in) {
return null;
}
#Override
public CustomTypefaceSpan[] newArray(int size) {
return new CustomTypefaceSpan[size];
}
};
}
Then I used like this:
// This is for color
SpannableString s = new SpannableString(item.getTitle().toString());
s.setSpan(new ForegroundColorSpan(Color.RED), 0, s.length(), 0);
// This is for typeface and size
Typeface typeFace = Functions.getTypeface(this, "Avenir");
if (typeFace != null) {
int size = 19;
float scaledSizeInPixels = size * getResources().getDisplayMetrics().scaledDensity;
CustomTypefaceSpan spanTypeFace = new CustomTypefaceSpan(item.getTitle().toString(), typeFace, scaledSizeInPixels);
s.setSpan(spanTypeFace, 0, s.length(), 0);
}
item.setTitle(s);
Hope this helps.
Goto activity_main.xml and select nav_view in design and you can change menu item text size by updating itemTextAppearance and itemTextColor like as follows
For com.google.android.material.navigation.NavigationView you should use the app namespace with your custom style:
app:itemTextAppearance="#style/NavDrawerTextStyle"
List Adapter Layout of your Navigation bar:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:orientation="horizontal"
android:background="#drawable/pressed_state">
<TextView
android:id="#+id/textView_list_item"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toRightOf="#+id/imageView_icons"
android:textStyle="bold"
android:layout_marginLeft="10dp"
android:textColor="#color/white"
android:textSize="17sp" />
<ImageView
android:id="#+id/list_adapter_image"
android:layout_width="10dp"
android:layout_height="10dp"
android:layout_centerVertical="true"
android:layout_alignParentRight="true"
android:visibility="visible"
android:layout_marginRight="50dp"
android:background="#drawable/circle_orange"/>
</RelativeLayout>
<LinearLayout
android:layout_height="1dp"
android:layout_width="match_parent"
android:background="#EC1294"></LinearLayout>
</LinearLayout>
This param in RelativeLayout set the background color --> android:background="#drawable/pressed_state"
Make this "pressed_state.xml" in drawable folder.
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="#color/light_blue" android:state_pressed="true"/>
Excuse me for my english.
Open or create values\dimens.xml
Add this code:
<dimen name="design_bottom_navigation_text_size" tools:override="true">11sp</dimen>
<dimen name="design_bottom_navigation_active_text_size" tools:override="true">12sp</dimen>
It should work
Related
Google recently released the android.support.design.widget.NavigationView widget as part of the com.android.support:design:22.2.0 library, which greatly simplified (and standardises) the process of creating a NavigationDrawer.
However according to the design specs, the list item should be Roboto Medium, 14sp, 87% #000000. The NavigationView exposes no textSize or textStyle to customise this.
What are my options if I'm pedantic about maintaining the correct design specifications using the Google provided NavigationView (or customising it in any other way)?
Create new style at the file app/src/main/res/values/styles.xml
<style name="NavigationDrawerStyle">
<item name="android:textSize">20sp</item><!-- text size in menu-->
<!-- item size in menu-->
<item name="android:listPreferredItemHeightSmall">40dp</item>
<item name="listPreferredItemHeightSmall">40dp</item>
<!-- item padding left in menu-->
<item name="android:listPreferredItemPaddingLeft">8dp</item>
<item name="listPreferredItemPaddingLeft">8dp</item>
<!-- item padding right in menu-->
<item name="android:listPreferredItemPaddingRight">8dp</item>
<item name="listPreferredItemPaddingRight">8dp</item>
</style>
Add it to your main_layout.xml
<android.support.design.widget.NavigationView
...
app:theme="#style/NavigationDrawerStyle"
....>
</android.support.design.widget.NavigationView>
All params of the navigation items (which you can change) are located here (path to file ...\sdk\extras\android\support\design\res\layout\design_navigation_item.xml )
design_navigation_item.xml
<android.support.design.internal.NavigationMenuItemView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="?attr/listPreferredItemHeightSmall"
android:paddingLeft="?attr/listPreferredItemPaddingLeft"
android:paddingRight="?attr/listPreferredItemPaddingRight"
android:drawablePadding="#dimen/navigation_icon_padding"
android:gravity="center_vertical|start"
android:maxLines="1"
android:fontFamily="sans-serif-thin"
android:textSize="22sp"
android:textAppearance="?attr/textAppearanceListItem" />
Also you can override *.xml file (copy file from ...\sdk\extras\android\support\design\res\layout\design_navigation_item.xml), just in your app/src/main/res/layout folder create a layout named the same design_navigation_item.xml.
All layouts which can be Overriden are located here ...\sdk\extras\android\support\design\res\layout\
design_layout_snackbar.xml
design_layout_snackbar_include.xml
design_layout_tab_icon.xml
design_layout_tab_text.xml
design_navigation_item.xml
design_navigation_item_header.xml
design_navigation_item_separator.xml
design_navigation_item_subheader.xml
design_navigation_menu.xml
[UPDATE] Each version of com.android.support:design-{version} lib has different items to override.
Check all what you need in
[UPDATE 04/14/2020]
If you are using com.google.android.material.navigation.NavigationView
then open the class, and you will see:
public NavigationView(#NonNull Context context, #Nullable AttributeSet attrs) {
this(context, attrs, R.attr.navigationViewStyle);
}
So you can use attr navigationViewStyle to set your own style for the NavigationView via theme of your app:
NB: parent theme of AppTheme should be Theme.MaterialComponents
<style name="AppTheme" parent="Theme.MaterialComponents.Light.NoActionBar.Bridge">
...
<item name="navigationViewStyle">#style/AppNavigationViewStyle</item>
...
</style>
<style name="AppNavigationViewStyle" parent="Widget.MaterialComponents.NavigationView">
<item name="itemTextAppearance">#style/AppNavigationViewItemTextAppearance</item>
</style>
<style name="AppNavigationViewItemTextAppearance" parent="#style/TextAppearance.MaterialComponents.Subtitle2">
<item name="android:textSize">18sp</item>
</style>
Just open parent theme to see all <item name attrs for override
Since Android Support Library 22.2.1, Google has changed default textSize of items in NavigationView from 16sp to 14sp, which suits Material Design guideline well. However, in some cases(for example, when you want to support Chinese language), it seems larger textSize is better. Solution is simple:
add app:theme="#style/yourStyle.Drawer" to your NavigationView in your layout.xml
in styles.xml, add android:textSize="16sp" in style yourStyle.Drawer
You can customize everything from text color to size and font in your style.xml
<style name="NavDrawerTextStyle" parent="Base.TextAppearance.AppCompat">
<item name="android:textColor">#color/colorPrimaryDark</item>
<item name="android:textSize">16sp</item>
<item name="android:textStyle">bold</item>
</style>
and then in your NavigationView:
<android.support.v4.widget.DrawerLayout 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:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<android.support.design.widget.NavigationView
...
android:itemTextAppearance="#style/NavDrawerTextStyle"
/>
you can use this attributes inside xml file
app:itemTextAppearance="?android:attr/textAppearanceMedium"
or for small text
app:itemTextAppearance="?android:attr/textAppearance"
or for large text
app:itemTextAppearance="?android:attr/textAppearanceLarge"
This worked for me:
activity_main.xml
<android.support.design.widget.NavigationView
android:id="#+id/navigation_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:theme="#style/NavigationDrawerStyle"
app:headerLayout="#layout/navdrawer_header"
app:menu="#menu/navdrawer_menu" />
styles.xml
<style name="NavigationDrawerStyle">
<item name="android:textSize">16sp</item>
</style>
Scouring through the source code I found this layout file
/platform/frameworks/support/.../design/res/layout/design_drawer_item.xml
with the following attribute
<android.support.design.internal.NavigationMenuItemView
...
android:textAppearance="?attr/textAppearanceListItem"
Which meant all we had to do was to override the textAppearanceListItem style in our project.
res/values/styles.xml
<style name="AppTheme" ... >
...
<item name="textAppearanceListItem">#style/list_item_appearance</item>
</style>
<style name="list_item_appearance">
<item name="android:textSize">14sp</item>
<item name="android:fontFamily">sans-serif-medium</item>
</style>
I'm not totally sure what else this will affect but if anyone has a better answer I'd be happy to accept that instead!
Maybe it might help. Recently I had to do this programmatically.
I used this class:
public class CustomTypefaceSpan extends TypefaceSpan {
private final Typeface newType;
private final float newSp;
public CustomTypefaceSpan(String family, Typeface type, float sp) {
super(family);
newType = type;
newSp = sp;
}
#Override
public void updateDrawState(TextPaint ds) {
applyCustomTypeFace(ds, newType, newSp);
}
#Override
public void updateMeasureState(TextPaint paint) {
applyCustomTypeFace(paint, newType, newSp);
}
private static void applyCustomTypeFace(Paint paint, Typeface tf, float sp) {
int oldStyle;
Typeface old = paint.getTypeface();
if (old == null) {
oldStyle = 0;
} else {
oldStyle = old.getStyle();
}
int fake = oldStyle & ~tf.getStyle();
if ((fake & Typeface.BOLD) != 0) {
paint.setFakeBoldText(true);
}
if ((fake & Typeface.ITALIC) != 0) {
paint.setTextSkewX(-0.25f);
}
paint.setTextSize(sp);
paint.setTypeface(tf);
}
#SuppressWarnings("unused")
public static final Parcelable.Creator<CustomTypefaceSpan> CREATOR = new Parcelable.Creator<CustomTypefaceSpan>() {
#Override
public CustomTypefaceSpan createFromParcel(Parcel in) {
return null;
}
#Override
public CustomTypefaceSpan[] newArray(int size) {
return new CustomTypefaceSpan[size];
}
};
}
Then I used like this:
// This is for color
SpannableString s = new SpannableString(item.getTitle().toString());
s.setSpan(new ForegroundColorSpan(Color.RED), 0, s.length(), 0);
// This is for typeface and size
Typeface typeFace = Functions.getTypeface(this, "Avenir");
if (typeFace != null) {
int size = 19;
float scaledSizeInPixels = size * getResources().getDisplayMetrics().scaledDensity;
CustomTypefaceSpan spanTypeFace = new CustomTypefaceSpan(item.getTitle().toString(), typeFace, scaledSizeInPixels);
s.setSpan(spanTypeFace, 0, s.length(), 0);
}
item.setTitle(s);
Hope this helps.
Goto activity_main.xml and select nav_view in design and you can change menu item text size by updating itemTextAppearance and itemTextColor like as follows
For com.google.android.material.navigation.NavigationView you should use the app namespace with your custom style:
app:itemTextAppearance="#style/NavDrawerTextStyle"
List Adapter Layout of your Navigation bar:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:orientation="horizontal"
android:background="#drawable/pressed_state">
<TextView
android:id="#+id/textView_list_item"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toRightOf="#+id/imageView_icons"
android:textStyle="bold"
android:layout_marginLeft="10dp"
android:textColor="#color/white"
android:textSize="17sp" />
<ImageView
android:id="#+id/list_adapter_image"
android:layout_width="10dp"
android:layout_height="10dp"
android:layout_centerVertical="true"
android:layout_alignParentRight="true"
android:visibility="visible"
android:layout_marginRight="50dp"
android:background="#drawable/circle_orange"/>
</RelativeLayout>
<LinearLayout
android:layout_height="1dp"
android:layout_width="match_parent"
android:background="#EC1294"></LinearLayout>
</LinearLayout>
This param in RelativeLayout set the background color --> android:background="#drawable/pressed_state"
Make this "pressed_state.xml" in drawable folder.
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="#color/light_blue" android:state_pressed="true"/>
Excuse me for my english.
Open or create values\dimens.xml
Add this code:
<dimen name="design_bottom_navigation_text_size" tools:override="true">11sp</dimen>
<dimen name="design_bottom_navigation_active_text_size" tools:override="true">12sp</dimen>
It should work
Is there a way to change the theme of a TextInputLayout programmatically in Android.
If I have the following TextInputLayout for ex.:
<android.support.design.widget.TextInputLayout
android:id="#+id/label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:paddingTop="16dp"
android:theme="#style/TextInputLayoutTheme"
app:errorTextAppearance="#style/Error">
<android.support.v7.widget.AppCompatEditText
android:id="#+id/edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="8dp"
android:paddingTop="8dp"/>
</android.support.design.widget.TextInputLayout>
Could I somehow change this line android:theme="#style/TextInputLayoutTheme" to another theme programmatically?
There is no way to change theme of any view or any layout at runtime. Because of themes and styles are applied during creation of view, recursively. (Themes also applies child views of layouts)
But, you can change that theme before creation of view using XML layout or programmatically.
Programmatically:
Method 1 - Create TextInputLayout programmatically with wrapping Context with android.view.ContextThemeWrapper and use.
TextInputLayout layout = new TextInputLayout(new ContextThemeWrapper(getContext(), R.style. TextInputLayoutTheme));
Method 2 - Extend TextInputLayout and use your own layout. Pass ContextThemeWrapper as context.
public class MyTextInputLayout extends TextInputLayout {
public MyTextInputLayout(Context context) {
super(new ContextThemeWrapper(context, R.style.AppTheme));
}
public MyTextInputLayout(Context context, AttributeSet attrs) {
super(new ContextThemeWrapper(context, R.style.AppTheme), attrs);
}
public MyTextInputLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(new ContextThemeWrapper(context, R.style.AppTheme), attrs, defStyleAttr);
}
}
Now, you can use MyTextInputLayout in your XML layout
With XML Layout:
1) In attrs.xml file, create new attribute named textInputLayoutTheme
<attr name="textInputLayoutTheme" format="reference"/>
2) In your AppTheme in styles.xml file set your #style/TextInputLayoutTheme as textInputLayoutTheme.
<resources>
<style name="AppTheme" parent="PARENT_THEME">
<item name="textInputLayoutTheme">#style/TextInputLayoutTheme</item>
</style>
<style name="AppTheme.Secondary">
<item name="textInputLayoutTheme">#style/TextInputLayoutTheme_Secondary</item>
</style>
</resources>
3) In your layout.xml file, set ?attr/textInputLayoutTheme as a TextInputLayout theme
<android.support.design.widget.TextInputLayout
android:id="#+id/label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:paddingTop="16dp"
android:theme="#?attr/textInputLayoutTheme"
app:errorTextAppearance="#style/Error">
Now, when you change your application theme from AppTheme to AppTheme.Secondary TextInputLayoutTheme_Secondary will be used as a theme of your TextInputLayout instead of TextInputLayoutTheme.
Unfortunately the accepted answer is not working for me.
My solution was to wrap TextInputLayout in a custom layout.
view_input_layout_wrapper.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:theme="#style/AppThemeMaterial"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.textfield.TextInputLayout
android:id="#+id/til"
style="#style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.textfield.TextInputEditText
android:id="#+id/edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</com.google.android.material.textfield.TextInputLayout>
</FrameLayout>
TextInputLayoutWrapper
class TextInputLayoutWrapper(context: Context) : FrameLayout(context) {
var inputLayout: TextInputLayout
private set
init {
inflate(context, R.layout.view_input_layout_wrapper, this)
inputLayout = findViewById(R.id.til)
}
}
Implementation in the view (fragment/activity):
private fun addNewField(fieldName: String) {
val textInputLayoutWrapper = TextInputLayoutWrapper(
requireContext()
).apply {
inputLayout.hint = fieldName
}
fieldsContainerViewGroup.addView(textInputLayoutWrapper)
}
NOTE: My app theme is not material theme, so I must add theme="#style/AppThemeMaterial" in the root ViewGroup of the TextInputLayout.
<style name="AppThemeMaterial" parent="Theme.MaterialComponents.Light">
<item name="colorPrimary">#color/colorPrimary</item>
<item name="colorPrimaryDark">#color/colorPrimaryDark</item>
<item name="colorAccent">#color/colorAccent</item>
<item name="android:windowBackground">#android:color/black</item>
</style>
I'm using the Calligraphy lib for Android to change the fonts in my app.
The problem is with the Toolbar. I don't know how to change the font.
This is my Toolbar :
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:titleTextAppearance="#style/Toolbar.TitleText"
android:background="#drawable/background_repeat"
app:popupTheme="#style/AppTheme.PopupOverlay" />
This is the TextAppearance in my style.xml :
<style name="Toolbar.TitleText" parent="TextAppearance.Widget.AppCompat.Toolbar.Title">
<item name="fontPath">fonts/Raleway-ExtraBoldItalic.ttf</item>
<item name="android:textSize">50sp</item>
</style>
This is not working. I can change the size of the text (in this example, 50sp is working). But impossible to change the font.
The problem is that Toolbar creates TextViews for title and subtitle programmatically inside itself.
It means that it doesn't use wrapped LayoutInflater by Calligraphy.
Instead it uses system Typefaces depending on fontFamily and fontStyle from textAppearence attribute.
But Calligraphy listens for GlobalLayout changes and tries to load style from theme.
So what I've done:
Add activity theme and customize ActionBarStyle:
<style name="ActivityTheme" parent="AppTheme.Base">
<item name="android:actionBarStyle">#style/ActionBarStyle</item>
</style>
<style name="ActionBarStyle" parent="Widget.AppCompat.Light.ActionBar.Solid">
<item name="android:titleTextStyle">#style/ToolbarTitleTextAppearance</item>
</style>
<style name="ToolbarTitleTextAppearance" parent="TextAppearance.AppCompat.Widget.ActionBar.Title">
<item name="android:textSize">20sp</item>
<item name="fontPath">fonts/Roboto-Medium.ttf</item>
</style>
If you don't want or cannot override toolbar theme, you can subclass Toolbar and use your custom toolbar instead of the system toolbar:
public class ToolbarPlus extends Toolbar {
public ToolbarPlus(Context context) {
super(context);
}
public ToolbarPlus(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ToolbarPlus(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
public void setTitle(CharSequence title) {
if (title == null) {
title = "";
}
Typeface font = TypefaceUtils.load(getResources().getAssets(), "fonts/Roboto-BoldItalic.ttf");
super.setTitle(CalligraphyUtils.applyTypefaceSpan(title, font));
}
}
Replace "fonts/Roboto-BoldItalic.ttf" with your font.
You can also use this method for subtitle by overriding public void setSubtitle(CharSequence subtitle).
There is two way you can do this
1) By using style in style.xml file AnoDest told you
2) By using xml, in this way you will get more control over view, you need to create seprate xml file called appbar.xml and include it in your view
appbar.xml file
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
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"
android:background="#drawable/gradient_theme"
android:elevation="#dimen/smallPadding"
android:fitsSystemWindows="true">
<com.indussoft.lms.customUI.TextViewRobotoBold
android:id="#+id/tvTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Activity Name"
android:textStyle="bold"
android:textSize="#dimen/okTextSize"
android:layout_gravity="center"
android:gravity="center"
android:visibility="visible"
android:textColor="#color/white" />
<TextView
android:layout_width="wrap_content"
android:text="#string/accept"
fontPath="fonts/Roboto-Bold.ttf"
android:layout_height="wrap_content" />
</android.support.v7.widget.Toolbar>
And include it in your activity view such as
<include
layout="#layout/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
Nothing worked for me so this is the function that I wrote in my base activity to workaround the issue:
private void setToolBarFont() {
final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
for (int i = 0; i < toolbar.getChildCount(); i++) {
final View child = toolbar.getChildAt(i);
if (child instanceof TextView) {
final TextView textView = (TextView) child;
CalligraphyUtils.applyFontToTextView(textView, TypefaceUtils.load(getAssets(), "fonts/my_font.ttf"));
}
}
}
p.s. this is an open issue on Calligraphy's GitHub page currently. Here's the link to the issue:
https://github.com/chrisjenx/Calligraphy/issues/295
According to How to style PopupMenu? you cannot set a popupmenu style directly, which seems contrary to https://developer.android.com/reference/android/widget/PopupWindow.html
It states you can specify a style in the PopupMenu constructor. According to http://blog.http417.com/2014/06/styling-popupmenu.html it looks like the attributes I need to specify are "android:popupBackground" and "android:dropDownWidth". However, the following just removes the default style and doesn't apply my desired color or width:
styles.xml:
<style name="popup">
<item name="android:popupBackground">#color/material_blue_grey_800</item>
<item name="android:dropDownWidth">350dp</item>
</style>
ActivityA.java
public class ActivityA extends AppCompatActivity implements
PopupMenu.OnMenuItemClickListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_a);
findViewById(R.id.popupBtn).setOnClickListener(new
View.OnClickListener() {
#Override
public void onClick(View button) {
PopupMenu popupMenu = new PopupMenu(ActivityA.this,
button, Gravity.RIGHT, 0, R.style.popup);
}
}
#Override
public boolean onMenuItemClick(MenuItem item) {
return false;
}
}
activity_a.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
tools:context=".activities.ActivityA">
<Button
android:id="#+id/popupBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:text="Press to open menu"/>
</RelativeLayout>
You cannot apply a style programmatically but you can do it with a theme: https://developer.android.com/guide/topics/ui/themes.html#ApplyAStyle a similar answer can be found here: https://stackoverflow.com/a/2016344/936269
Add this to your AppTheme ..
<item name="android:popupMenuStyle">#style/popup</item>
<item name="popupMenuStyle">#style/popup</item>
Good luck!
You can declare the styles in your theme like below:
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Other styles -->
<!-- PopUpMenu styles -->
<item name="popupMenuStyle">#style/Widget.App.PopupMenu</item>
</style>
<!-- Widget PopUpMenu Style-->
<style name="Widget.App.PopupMenu" parent="Widget.AppCompat.Light.PopupMenu">
<!-- Whatever Styles Put Here-->
</style>
I've seen in the new material design Side Nav spec that you can display the drawer over the action bar and behind the status bar. How can I implement this?
New functionality in the framework and support libs allow exactly this. There are three 'pieces of the puzzle':
Using Toolbar so that you can embed your action bar into your view hierarchy.
Making DrawerLayout fitsSystemWindows so that it is layed out behind the system bars.
Disabling Theme.Material's normal status bar coloring so that DrawerLayout can draw there instead.
I'll assume that you will use the new appcompat.
First, your layout should look like this:
<!-- The important thing to note here is the added fitSystemWindows -->
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/my_drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<!-- Your normal content view -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!-- We use a Toolbar so that our drawer can be displayed
in front of the action bar -->
<android.support.v7.widget.Toolbar
android:id="#+id/my_awesome_toolbar"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:minHeight="?attr/actionBarSize"
android:background="?attr/colorPrimary" />
<!-- The rest of your content view -->
</LinearLayout>
<!-- Your drawer view. This can be any view, LinearLayout
is just an example. As we have set fitSystemWindows=true
this will be displayed under the status bar. -->
<LinearLayout
android:layout_width="304dp"
android:layout_height="match_parent"
android:layout_gravity="left|start"
android:fitsSystemWindows="true">
<!-- Your drawer content -->
</LinearLayout>
</android.support.v4.widget.DrawerLayout>
Then in your Activity/Fragment:
public void onCreate(Bundled savedInstanceState) {
super.onCreate(savedInstanceState);
// Your normal setup. Blah blah ...
// As we're using a Toolbar, we should retrieve it and set it
// to be our ActionBar
Toolbar toolbar = (...) findViewById(R.id.my_awesome_toolbar);
setSupportActionBar(toolbar);
// Now retrieve the DrawerLayout so that we can set the status bar color.
// This only takes effect on Lollipop, or when using translucentStatusBar
// on KitKat.
DrawerLayout drawerLayout = (...) findViewById(R.id.my_drawer_layout);
drawerLayout.setStatusBarBackgroundColor(yourChosenColor);
}
Then you need to make sure that the DrawerLayout is visible behind the status bar. You do that by changing your values-v21 theme:
values-v21/themes.xml
<style name="Theme.MyApp" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:statusBarColor">#android:color/transparent</item>
<item name="android:windowTranslucentStatus">true</item>
</style>
Note:
If a <fragment android:name="fragments.NavigationDrawerFragment"> is used instead of
<LinearLayout
android:layout_width="304dp"
android:layout_height="match_parent"
android:layout_gravity="left|start"
android:fitsSystemWindows="true">
<!-- Your drawer content -->
</LinearLayout>
the actual layout, the desired effect will be achieved if you call fitsSystemWindows(boolean) on a view that you return from onCreateView method.
#Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container,
Bundle savedInstanceState) {
View mDrawerListView = inflater.inflate(
R.layout.fragment_navigation_drawer, container, false);
mDrawerListView.setFitsSystemWindows(true);
return mDrawerListView;
}
EDIT: The new Design Support Library supports this and the previous method is no longer required.
This can now be achieved using the new Android Design Support Library.
You can see the Cheesesquare sample app by Chris Banes which demos all the new features.
Previous method:
Since there is no complete solution posted, here is the way I achieved the desired result.
First include a ScrimInsetsFrameLayout in your project.
/*
* Copyright 2014 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* A layout that draws something in the insets passed to
* {#link #fitSystemWindows(Rect)}, i.e. the area above UI chrome
* (status and navigation bars, overlay action bars).
*/
public class ScrimInsetsFrameLayout extends FrameLayout {
private Drawable mInsetForeground;
private Rect mInsets;
private Rect mTempRect = new Rect();
private OnInsetsCallback mOnInsetsCallback;
public ScrimInsetsFrameLayout(Context context) {
super(context);
init(context, null, 0);
}
public ScrimInsetsFrameLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs, 0);
}
public ScrimInsetsFrameLayout(
Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context, attrs, defStyle);
}
private void init(Context context, AttributeSet attrs, int defStyle) {
final TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.ScrimInsetsView, defStyle, 0);
if (a == null) {
return;
}
mInsetForeground = a.getDrawable(
R.styleable.ScrimInsetsView_insetForeground);
a.recycle();
setWillNotDraw(true);
}
#Override
protected boolean fitSystemWindows(Rect insets) {
mInsets = new Rect(insets);
setWillNotDraw(mInsetForeground == null);
ViewCompat.postInvalidateOnAnimation(this);
if (mOnInsetsCallback != null) {
mOnInsetsCallback.onInsetsChanged(insets);
}
return true; // consume insets
}
#Override
public void draw(Canvas canvas) {
super.draw(canvas);
int width = getWidth();
int height = getHeight();
if (mInsets != null && mInsetForeground != null) {
int sc = canvas.save();
canvas.translate(getScrollX(), getScrollY());
// Top
mTempRect.set(0, 0, width, mInsets.top);
mInsetForeground.setBounds(mTempRect);
mInsetForeground.draw(canvas);
// Bottom
mTempRect.set(0, height - mInsets.bottom, width, height);
mInsetForeground.setBounds(mTempRect);
mInsetForeground.draw(canvas);
// Left
mTempRect.set(
0,
mInsets.top,
mInsets.left,
height - mInsets.bottom);
mInsetForeground.setBounds(mTempRect);
mInsetForeground.draw(canvas);
// Right
mTempRect.set(
width - mInsets.right,
mInsets.top, width,
height - mInsets.bottom);
mInsetForeground.setBounds(mTempRect);
mInsetForeground.draw(canvas);
canvas.restoreToCount(sc);
}
}
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (mInsetForeground != null) {
mInsetForeground.setCallback(this);
}
}
#Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (mInsetForeground != null) {
mInsetForeground.setCallback(null);
}
}
/**
* Allows the calling container to specify a callback for custom
* processing when insets change (i.e. when {#link #fitSystemWindows(Rect)}
* is called. This is useful for setting padding on UI elements
* based on UI chrome insets (e.g. a Google Map or a ListView).
* When using with ListView or GridView, remember to set
* clipToPadding to false.
*/
public void setOnInsetsCallback(OnInsetsCallback onInsetsCallback) {
mOnInsetsCallback = onInsetsCallback;
}
public static interface OnInsetsCallback {
public void onInsetsChanged(Rect insets);
}
}
Then create a styleable so that the insetForeground can be set.
values/attrs.xml
<declare-styleable name="ScrimInsetsView">
<attr name="insetForeground" format="reference|color" />
</declare-styleable>
Update your activity's xml file and make sure android:fitsSystemWindows is set to true on both the DrawerLayout as well as the ScrimInsetsFrameLayout.
layout/activity_main.xml
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/drawerLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".MainActivity">
<!-- The main content view -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!-- Your main content -->
</LinearLayout>
<!-- The navigation drawer -->
<com.example.app.util.ScrimInsetsFrameLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/scrimInsetsFrameLayout"
android:layout_width="320dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#color/white"
android:elevation="10dp"
android:fitsSystemWindows="true"
app:insetForeground="#4000">
<!-- Your drawer content -->
</com.example.app.util.ScrimInsetsFrameLayout>
</android.support.v4.widget.DrawerLayout>
Inside the onCreate method of your activity set the status bar background color on the drawer layout.
MainActivity.java
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// ...
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawerLayout);
mDrawerLayout.setStatusBarBackgroundColor(
getResources().getColor(R.color.primary_dark));
}
Finally update your app's theme so that the DrawerLayout is behind the status bar.
values-v21/styles.xml
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:statusBarColor">#android:color/transparent</item>
</style>
Result:
With the release of the latest Android Support Library (rev 22.2.0) we've got a Design Support Library and as part of this a new view called NavigationView. So instead of doing everything on our own with the ScrimInsetsFrameLayout and all the other stuff we simply use this view and everything is done for us.
Example
Step 1
Add the Design Support Library to your build.gradle file
dependencies {
// Other dependencies like appcompat
compile 'com.android.support:design:22.2.0'
}
Step 2
Add the NavigationView to your DrawerLayout:
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"> <!-- this is important -->
<!-- Your contents -->
<android.support.design.widget.NavigationView
android:id="#+id/navigation"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:menu="#menu/navigation_items" /> <!-- The items to display -->
</android.support.v4.widget.DrawerLayout>
Step 3
Create a new menu-resource in /res/menu and add the items and icons you wanna display:
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:checkableBehavior="single">
<item
android:id="#+id/nav_home"
android:icon="#drawable/ic_action_home"
android:title="Home" />
<item
android:id="#+id/nav_example_item_1"
android:icon="#drawable/ic_action_dashboard"
android:title="Example Item #1" />
</group>
<item android:title="Sub items">
<menu>
<item
android:id="#+id/nav_example_sub_item_1"
android:title="Example Sub Item #1" />
</menu>
</item>
</menu>
Step 4
Init the NavigationView and handle click events:
public class MainActivity extends AppCompatActivity {
NavigationView mNavigationView;
DrawerLayout mDrawerLayout;
// Other stuff
private void init() {
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mNavigationView = (NavigationView) findViewById(R.id.navigation_view);
mNavigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
mDrawerLayout.closeDrawers();
menuItem.setChecked(true);
switch (menuItem.getItemId()) {
case R.id.nav_home:
// TODO - Do something
break;
// TODO - Handle other items
}
return true;
}
});
}
}
Step 5
Be sure to set android:windowDrawsSystemBarBackgrounds and android:statusBarColor in values-v21 otherwise your Drawer won`t be displayed "under" the StatusBar
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Other attributes like colorPrimary, colorAccent etc. -->
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:statusBarColor">#android:color/transparent</item>
</style>
Optional Step
Add a Header to the NavigationView. For this simply create a new layout and add app:headerLayout="#layout/my_header_layout" to the NavigationView.
Result
Notes
The highlighted color uses the color defined via the colorPrimary attribute
The List Items use the color defined via the textColorPrimary attribute
The Icons use the color defined via the textColorSecondary attribute
You can also check the example app by Chris Banes which highlights the NavigationView along with the other new views that are part of the Design Support Library (like the FloatingActionButton, TextInputLayout, Snackbar, TabLayout etc.)
Make it work, in values-v21 styles or theme xml needs to use this attribute:
<item name="android:windowTranslucentStatus">true</item>
That make the magic!
The above all approaches are correct and may be working . I have created a working demo following the above guide and tested on 2.x to 5.x
You can clone from Github
The important thing to play around is in Main Activity
toolbar = (Toolbar) findViewById(R.id.toolbar);
res = this.getResources();
this.setSupportActionBar(toolbar);
ActionBar actionBar = getSupportActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setHomeButtonEnabled(true);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
ScrimInsetsFrameLayout scrimInsetsFrameLayout = (ScrimInsetsFrameLayout)
findViewById(R.id.linearLayout);
scrimInsetsFrameLayout.setOnInsetsCallback(this);
}
and the call back
#Override
public void onInsetsChanged(Rect insets) {
Toolbar toolbar = this.toolbar;
ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams)
toolbar.getLayoutParams();
lp.topMargin = insets.top;
int top = insets.top;
insets.top += toolbar.getHeight();
toolbar.setLayoutParams(lp);
insets.top = top; // revert
}
Absolutely the Theme for V21 does the magic
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- API 21 theme customizations can go here. -->
<item name="colorPrimary">#color/colorPrimary</item>
<item name="colorPrimaryDark">#color/colorPrimaryDark</item>
<item name="colorAccent">#color/accent_material_light</item>
<item name="windowActionModeOverlay">true</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:statusBarColor">#android:color/transparent</item>
<item name="android:windowTranslucentStatus">true</item>
</style>
and the ScrimInsetsFrameLayout
Now this come more easy with new Design Support library
compile 'com.android.support:design:22.2.0'
clone from #Chris Banes
https://github.com/chrisbanes/cheesesquare
I am Using Design Support Library. And just by using custom theme I achived transparent Status Bar when Opened Navigation Drawer.
<style name="NavigationStyle" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">#color/primaryColor</item>
<item name="colorPrimaryDark">#color/primaryColorDark</item>
<!-- To Make Navigation Drawer Fill Status Bar and become Transparent Too -->
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:statusBarColor">#android:color/transparent</item>
</style>
Finally add theme in Manifest File
<activity
........
........
android:theme="#style/NavigationStyle">
</activity>
Do not forget to use the property, android:fitsSystemWindows="true" in "DrawerLayout"
All answers mentioned here are too old and lengthy.The best and short solution that work with latest Navigationview is
#Override
public void onDrawerSlide(View drawerView, float slideOffset) {
super.onDrawerSlide(drawerView, slideOffset);
try {
//int currentapiVersion = android.os.Build.VERSION.SDK_INT;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP){
// Do something for lollipop and above versions
Window window = getWindow();
// clear FLAG_TRANSLUCENT_STATUS flag:
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
// add FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS flag to the window
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
// finally change the color to any color with transparency
window.setStatusBarColor(getResources().getColor(R.color.colorPrimaryDarktrans));}
} catch (Exception e) {
Crashlytics.logException(e);
}
}
this is going to change your status bar color to transparent when you open the drawer
Now when you close the drawer you need to change status bar color again to dark.So you can do it in this way.
public void onDrawerClosed(View drawerView) {
super.onDrawerClosed(drawerView);
try {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP){
// Do something for lollipop and above versions
Window window = getWindow();
// clear FLAG_TRANSLUCENT_STATUS flag:
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
// add FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS flag to the window
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
// finally change the color again to dark
window.setStatusBarColor(getResources().getColor(R.color.colorPrimaryDark));}
} catch (Exception e) {
Crashlytics.logException(e);
}
}
and then in main layout add a single line i.e
android:fitsSystemWindows="true"
and your drawer layout will look like
<android.support.v4.widget.DrawerLayout
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:id="#+id/drawer_layout"
android:fitsSystemWindows="true"
android:layout_width="match_parent"
android:layout_height="match_parent">
and your navigation view will look like
<android.support.design.widget.NavigationView
android:id="#+id/navigation_view"
android:layout_height="match_parent"
android:layout_width="wrap_content"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="#layout/navigation_header"
app:menu="#menu/drawer"
/>
I have tested it and its fully working.Hope it helps someone.This may not be the best approach but it works smoothly and is simple to implement.
Mark it up if it helps.Happy coding :)
This is the most simple, and it worked for me:
In the values-21:
<resources>
<style name="AppTheme" parent="AppTheme.Base">
...
<item name="android:windowTranslucentStatus">true</item>
</style>
<dimen name="topMargin">25dp</dimen>
</resources>
In the values:
<resources>
<dimen name="topMargin">0dp</dimen>
</resources>
And set to your toolbar
android:layout_marginTop="#dimen/topMargin"
Instead of using the ScrimInsetsFrameLayout... Isn't it easier to just add a view with a fixed height of 24dp and a background of primaryColor?
I understand that this involves adding a dummy view in the hierarchy, but it seems cleaner to me.
I already tried it and it's working well.
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_base_drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!-- THIS IS THE VIEW I'M TALKING ABOUT... -->
<View
android:layout_width="match_parent"
android:layout_height="24dp"
android:background="?attr/colorPrimary" />
<android.support.v7.widget.Toolbar
android:id="#+id/activity_base_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:elevation="2dp"
android:theme="#style/ThemeOverlay.AppCompat.Dark" />
<FrameLayout
android:id="#+id/activity_base_content_frame_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
<fragment
android:id="#+id/activity_base_drawer_fragment"
android:name="com.myapp.drawer.ui.DrawerFragment"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:elevation="4dp"
tools:layout="#layout/fragment_drawer" />
</android.support.v4.widget.DrawerLayout>
Try with this:
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/drawer_layout"
android:fitsSystemWindows="true">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--Main layout and ads-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<FrameLayout
android:id="#+id/ll_main_hero"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
</FrameLayout>
<FrameLayout
android:id="#+id/ll_ads"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<View
android:layout_width="320dp"
android:layout_height="50dp"
android:layout_gravity="center"
android:background="#ff00ff" />
</FrameLayout>
</LinearLayout>
<!--Toolbar-->
<android.support.v7.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/toolbar"
android:elevation="4dp" />
</FrameLayout>
<!--left-->
<ListView
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:choiceMode="singleChoice"
android:divider="#null"
android:background="#mipmap/layer_image"
android:id="#+id/left_drawer"></ListView>
<!--right-->
<FrameLayout
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="right"
android:background="#mipmap/layer_image">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#mipmap/ken2"
android:scaleType="centerCrop" />
</FrameLayout>
style :
<style name="ts_theme_overlay" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorPrimary">#color/red_A700</item>
<item name="colorPrimaryDark">#color/red1</item>
<item name="android:windowBackground">#color/blue_A400</item>
</style>
Main Activity extends ActionBarActivity
toolBar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolBar);
Now you can onCreateOptionsMenu like as normal ActionBar with ToolBar.
This is my Layout
TOP: Left Drawer - Right Drawer
MID: ToolBar (ActionBar)
BOTTOM: ListFragment
Hope you understand !have fun !