How can i remove the drop shadow of action bar from java code ?.
If i remove from the style it is working fine.
<style name="MyTheme" parent="Theme.Sherlock">
....
<item name="windowContentOverlay">#null</item>
<item name="android:windowContentOverlay">#null</item>
....
</style>
But i need to remove and add it dynamically from java code.
There is no way to set value for windowContentOverlay attribute programmatically. But you can define two different themes, one for Activities with a visible ActionBar shadow and one for others:
<!-- Your main theme with ActionBar shadow. -->
<style name="MyTheme" parent="Theme.Sherlock">
....
</style>
<!-- Theme without ActionBar shadow (inherits main theme) -->
<style name="MyNoActionBarShadowTheme" parent="MyTheme">
<item name="windowContentOverlay">#null</item>
<item name="android:windowContentOverlay">#null</item>
</style>
Now you can set them to activities in AndroidManifest.xml:
<!-- Activity with ActionBar shadow -->
<activity
android:name=".ShadowActivity"
android:theme="#style/MyTheme"/>
<!-- Activity without ActionBar shadow -->
<activity
android:name=".NoShadowActivity"
android:theme="#style/MyNoActionBarShadowTheme"/>
Or you can set the right theme programmatically in onCreate() method:
#Override
protected void onCreate(Bundle savedInstanceState) {
setTheme(R.style.MyNoActionBarShadowTheme);
super.onCreate(savedInstanceState);
//...
}
If you won't make more theme, then try this. This works nicely for me!
public void disableActionbarShadow() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
View v = getActivity().findViewById(android.R.id.content);
if (v instanceof FrameLayout) {
((FrameLayout) v).setForeground(null);
}
}else {
// kitkat.
// v is ActionBarOverlayLayout. unfortunately this is internal class.
// if u want to check v is desired class, try this
// if(v.getClass().getSimpleName.equals("ActionBarOverlayLayout"))
// (we cant use instanceof caz ActionBarOverlayLayout is internal package)
View v = ((ViewGroup)getActivity().getWindow().getDecorView()).getChildAt(0);
v.setWillNotDraw(true);
}
}
From Kitkat(maybe), ActionBarOverlayLayout is included in activity's view tree.
This shows actionbar shadow (I think XD)
refs: http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.4_r1/com/android/internal/widget/ActionBarOverlayLayout.java#79
Becaraful I don't know whats happen if using support library version.
I know this question is old, but this problem was new for me, so it might help somebody else as well.
Try:
getSupportActionBar().setElevation(0);
Or, if you are not using a custom action bar:
getActionBar().setElevation(0);
I think this is the easiest way to do it programmatically.
Define a new style like this. Notice that there's no parent defined:
<style name="ConOver" > <<== no parent
<item name="android:windowContentOverlay">#null</item>
</style>
Add this above your code:
// Add this line before setContentView() call
// Lets you add new attribute values into the current theme
getTheme().applyStyle(R.style.ConOver, true);
// Rest stays the same
Declare 2 styles ne has a shadow and the other one doesn't. THen in your manifest define each activity's theme with respective one.
e.g
<Activity
android:theme="#style/ThemeShadow" ...>
...
<Activity
android:theme="#style/ThemeNoShadow" ...>
I found this article:
Change Theme of Layout Runtime by Button Click in Android
It allows you to change the theme of an activity, but it does call finish() and restart the activity. So, I am not sure it will work for what you want.
import android.app.Activity;
import android.content.Intent;
public class Utils
{
private static int sTheme;
public final static int THEME_DEFAULT = 0;
public final static int THEME_WHITE = 1;
public final static int THEME_BLUE = 2;
/**
* Set the theme of the Activity, and restart it by creating a new Activity of the same type.
*/
public static void changeToTheme(Activity activity, int theme)
{
sTheme = theme;
activity.finish();
activity.startActivity(new Intent(activity, activity.getClass()));
}
/** Set the theme of the activity, according to the configuration. */
public static void onActivityCreateSetTheme(Activity activity)
{
switch (sTheme)
{
default:
case THEME_DEFAULT:
activity.setTheme(R.style.FirstTheme);
break;
case THEME_WHITE:
activity.setTheme(R.style.SecondTheme);
break;
case THEME_BLUE:
activity.setTheme(R.style.Thirdheme);
break;
}
}
}
If supportActionBar.elevation=0f did not work for you,
You can remove the shadow by setting appBar.targetElevation=0f but this method is deprecated.
The new method is using StateListAnimator.
You have to set the stateListAnimator to AppBarLayout without elevation that can be achieved by the steps below
Create animator resource appbar_animator.xml
<item
android:state_enabled="true"
app:state_collapsed="false"
app:state_collapsible="true">
<objectAnimator
android:duration="150"
android:propertyName="elevation"
android:valueTo="0dp"
android:valueType="floatType" />
</item>
<item android:state_enabled="true">
<objectAnimator
android:duration="150"
android:propertyName="elevation"
android:valueTo="0dp"
android:valueType="floatType" />
</item>
<item>
<objectAnimator
android:duration="0"
android:propertyName="elevation"
android:valueTo="0"
android:valueType="floatType" />
</item>
android.valueTo="0dp" defines the elevation.
Inflate and set the StateListAnimator to appBar
val stateAnimator=AnimatorInflater.loadStateListAnimator(this,R.animator.appbar_animator);
appBar.stateListAnimator=stateAnimator
StateListAnimator was added in api 21 Lollipop
Related
I am developing Day/Night feature in my app so I read those documents and start developing it.
It's working fine with default value in Day or Night
with deligate method AppCompatDelegate.setDefaultNightMode(*).
For customize night theme color I create values-night folder and inside I create colors.xml file like below.
res -> values -> colors.xml
res -> values-night -> colors.xml
After I place that color but not applying in Night theme! Its very strange why value-night colors is not applying always its showing default night color?
I have researched some but can't find the solution.
Note: Recreate activity is resolved my issue but I don't want to recreate
Here is my build.gradle file
Advance Thanks.
Try below dark mode code which I am use.
Step - 1
First of create night folder into your resource file like below image(i.e. values-night)
Step - 2
Create styles,strings and colors xml file for night mode same as below image and add your night mode color,string and style which you want to show in your app when night mode was apply.
For better user experience add window Animation in your style.
values --> style.xml
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">#color/colorPrimary</item>
<item name="colorPrimaryDark">#color/colorPrimaryDark</item>
<item name="colorAccent">#color/colorAccent</item>
</style>
<style name="NoActionBarAppTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">#color/white</item>
<item name="colorPrimaryDark">#color/white</item>
<item name="colorAccent">#color/main_click_txt</item>
<item name="android:windowLightStatusBar" tools:targetApi="m">true</item>
</style>
<!-- Add this theme where you change mode -->
<style name="NoActionBarWithChangeTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">#color/white</item>
<item name="colorPrimaryDark">#color/white</item>
<item name="colorAccent">#color/main_click_txt</item>
<item name="android:windowAnimationStyle">#style/WindowAnimationTransition</item>
<item name="android:windowLightStatusBar" tools:targetApi="m">true</item>
</style>
<!-- This will set the fade in animation on your change theme activity by default -->
<style name="WindowAnimationTransition">
<item name="android:windowEnterAnimation">#anim/fade_in</item>
<item name="android:windowExitAnimation">#anim/fade_out</item>
</style>
</resources>
values-night --> style.xml
<!-- Base application theme. values-night.xml -->
<style name="NoActionBarAppTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">#color/white</item>
<item name="colorPrimaryDark">#color/white</item>
<item name="colorAccent">#color/main_click_txt</item>
<item name="android:windowLightStatusBar" tools:targetApi="m">true</item>
</style>
<!-- Add this theme where you change mode -->
<style name="NoActionBarWithChangeTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">#color/white</item>
<item name="colorPrimaryDark">#color/white</item>
<item name="colorAccent">#color/main_click_txt</item>
<item name="android:windowAnimationStyle">#style/WindowAnimationTransition</item>
<item name="android:windowLightStatusBar" tools:targetApi="m">true</item>
</style>
<!-- This will set the fade in animation on your change activity by default -->
<style name="WindowAnimationTransition">
<item name="android:windowEnterAnimation">#anim/fade_in</item>
<item name="android:windowExitAnimation">#anim/fade_out</item>
</style>
fade_in.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="#android:anim/linear_interpolator">
<alpha
android:duration="2000"
android:fromAlpha="0.0"
android:toAlpha="1.0">
</alpha>
</set>
fade_out.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="#android:anim/linear_interpolator">
<alpha
android:duration="2000"
android:fromAlpha="1.0"
android:toAlpha="0.0" >
</alpha>
</set>
Step - 3
Add this below code in your splash screen if you want to set night mode as per device mode first time when application installed.
#Override
protected void onCreate(Bundle savedInstanceState) {
if (!CommonUtils.isToogleEnabled(SplashActivity.this)) {
if (CommonUtils.isDarkMode(SplashActivity.this)) {
CommonUtils.setIsNightModeEnabled(SplashActivity.this, true);
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
} else {
CommonUtils.setIsNightModeEnabled(SplashActivity.this, false);
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
}
} else {
if (CommonUtils.isNightModeEnabled(SplashActivity.this)) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
} else {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
}
}
super.onCreate(savedInstanceState);
...
//your code
}
Step - 4
Add this below code in your all activity
#Override
protected void onCreate(Bundle savedInstanceState) {
if (CommonUtils.isNightModeEnabled(MainActivity.this)) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
} else {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
}
super.onCreate(savedInstanceState);
...
//your code
}
Step - 5
Change mode using below code
private WeakReference<Activity> mActivity;
binding.imgNightMode.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mActivity = new WeakReference<Activity>(MainActivity.this);
CommonUtils.setIsToogleEnabled(MainActivity.this, true);
if (CommonUtils.isNightModeEnabled(MainActivity.this)) {
CommonUtils.setIsNightModeEnabled(MainActivity.this, false);
mActivity.get().recreate();
} else {
CommonUtils.setIsNightModeEnabled(MainActivity.this, true);
mActivity.get().recreate();
}
}
});
Below methods are CommonUtils.
private static final String NIGHT_MODE = "NIGHT_MODE";
private static final String TOOGLE = "TOOGLE";
public static boolean isNightModeEnabled(Context context) {
SharedPreferences mPrefs = context.getSharedPreferences("MY_PREF", MODE_PRIVATE);
return mPrefs.getBoolean(NIGHT_MODE, false);
}
public static void setIsNightModeEnabled(Context context, boolean isNightModeEnabled) {
SharedPreferences mPrefs = context.getSharedPreferences("MY_PREF", MODE_PRIVATE);
SharedPreferences.Editor editor = mPrefs.edit();
editor.putBoolean(NIGHT_MODE, isNightModeEnabled);
editor.apply();
}
public static void setIsToogleEnabled(Context context, boolean isToogleEnabled) {
SharedPreferences mPrefs = context.getSharedPreferences("MY_PREF", MODE_PRIVATE);
SharedPreferences.Editor editor = mPrefs.edit();
editor.putBoolean(TOOGLE, isToogleEnabled);
editor.apply();
}
public static boolean isToogleEnabled(Context context) {
SharedPreferences mPrefs = context.getSharedPreferences("MY_PREF", MODE_PRIVATE);
return mPrefs.getBoolean(TOOGLE, false);
}
public static boolean isDarkMode(Activity activity) {
return (activity.getResources().getConfiguration()
.uiMode & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES;
}
I hope this can help you!
Thank You.
Change appcompat dependency from 1.1.0 to 1.0.0, There is some issue to update resource in 1.1.0. This trick worked for me.
implementation 'androidx.appcompat:appcompat:1.1.0'//Remove
implementation 'androidx.appcompat:appcompat:1.0.0' // Add
Hope this will help you!!
I've done a few researches on this topic and I couldn't find a complete solution so, step by step and with some trial and error, I finally find out how can we achieve these results: having a transparent or coloured Actionbar and Statusbar. See my answer bellow.
I'm developing an app that needs to look similar in all devices with >= API14 when it comes to actionbar and statusbar customization. I've finally found a solution and since it took a bit of my time I'll share it to save some of yours.
We start by using an appcompat-21 dependency.
Transparent Actionbar:
values/styles.xml:
<style name="AppTheme" parent="Theme.AppCompat.Light">
...
</style>
<style name="AppTheme.ActionBar.Transparent" parent="AppTheme">
<item name="android:windowContentOverlay">#null</item>
<item name="windowActionBarOverlay">true</item>
<item name="colorPrimary">#android:color/transparent</item>
</style>
<style name="AppTheme.ActionBar" parent="AppTheme">
<item name="windowActionBarOverlay">false</item>
<item name="colorPrimary">#color/default_yellow</item>
</style>
**values-v21/styles.xml**:
<style name="AppTheme" parent="Theme.AppCompat.Light">
...
</style>
<style name="AppTheme.ActionBar.Transparent" parent="AppTheme">
<item name="colorPrimary">#android:color/transparent</item>
</style>
<style name="AppTheme.ActionBar" parent="AppTheme">
<item name="colorPrimaryDark">#color/bg_colorPrimaryDark</item>
<item name="colorPrimary">#color/default_yellow</item>
</style>
Now you can use these themes in your AndroidManifest.xml to specify which activities will have a transparent or colored ActionBar:
<activity
android:name=".MyTransparentActionbarActivity"
android:theme="#style/AppTheme.ActionBar.Transparent"/>
<activity
android:name=".MyColoredActionbarActivity"
android:theme="#style/AppTheme.ActionBar"/>
Note: in API>=21 to get the Actionbar transparent you need to get the Statusbar transparent too, otherwise will not respect your colour styles and will stay light-grey.
Transparent Statusbar (only works with API>=19):
This one it's pretty simple just use the following code:
protected void setStatusBarTranslucent(boolean makeTranslucent) {
if (makeTranslucent) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
} else {
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
}
But you'll notice a funky result:
This happens because when the Statusbar is transparent the layout will use its height. To prevent this we just need to:
SOLUTION ONE:
Add this line android:fitsSystemWindows="true" in your layout view container of whatever you want to be placed bellow the Actionbar:
...
<LinearLayout
android:fitsSystemWindows="true"
android:layout_width="match_parent"
android:layout_height="match_parent">
...
</LinearLayout>
...
SOLUTION TWO:
Add a few lines to our previous method:
protected void setStatusBarTranslucent(boolean makeTranslucent) {
View v = findViewById(R.id.bellow_actionbar);
if (v != null) {
int paddingTop = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT ? MyScreenUtils.getStatusBarHeight(this) : 0;
TypedValue tv = new TypedValue();
getTheme().resolveAttribute(android.support.v7.appcompat.R.attr.actionBarSize, tv, true);
paddingTop += TypedValue.complexToDimensionPixelSize(tv.data, getResources().getDisplayMetrics());
v.setPadding(0, makeTranslucent ? paddingTop : 0, 0, 0);
}
if (makeTranslucent) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
} else {
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
}
Where R.id.bellow_actionbar will be the layout container view id of whatever we want to be placed bellow the Actionbar:
...
<LinearLayout
android:id="#+id/bellow_actionbar"
android:layout_width="match_parent"
android:layout_height="match_parent">
...
</LinearLayout>
...
So this is it, it think I'm not forgetting something.
In this example I didn't use a Toolbar but I think it'll have the same result. This is how I customize my Actionbar:
#Override
protected void onCreate(Bundle savedInstanceState) {
View vg = getActionBarView();
getWindow().requestFeature(vg != null ? Window.FEATURE_ACTION_BAR : Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
setContentView(getContentView());
if (vg != null) {
getSupportActionBar().setCustomView(vg, new ActionBar.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
getSupportActionBar().setDisplayShowCustomEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(false);
getSupportActionBar().setDisplayShowTitleEnabled(false);
getSupportActionBar().setDisplayUseLogoEnabled(false);
}
setStatusBarTranslucent(true);
}
Note: this is an abstract class that extends ActionBarActivity.
It supports after KITKAT. Just add following code inside onCreate method of your Activity. No need any modifications to Manifest file.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
Window w = getWindow(); // in Activity's onCreate() for instance
w.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
}
Just add these lines of code to your activity/fragment java file:
getWindow().setFlags(
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
);
I have a DialogFragment which I want to show in fullscreen. I do however still want a StatusBar present, and the hardware buttons at the bottom. I also want to set a background color of the StatusBar (for Lollipop).
My problem is that if I set the following flags in the DialogFragment:
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
Both the StatusBar and Hardware keyboard becomes translucent, and the DialogFragment stretches behind these.
Here is the code, which has been greatly reduced to become readable:
public class CardDetailsDialog extends DialogFragment {
Setup parameters...
public static CardDetailsDialog newInstance(final long cardId, final long projectId){
CardDetailsDialog frag = new CardDetailsDialog();
frag.setStyle(DialogFragment.STYLE_NORMAL, R.style.CardDetailsDialogStyle);
return frag;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if(getDialog() != null) {
getDialog().getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
getDialog().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
getDialog().getWindow().getAttributes().windowAnimations = R.style.DialogSlideAnimation;
getDialog().getWindow().setLayout(LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT);
getDialog().getWindow().setStatusBarColor(Color.RED);
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View view = inflater.inflate(R.layout.card_details, container, false);
Handle everything that happens inside the view...
return view;
}
}
Here is the referred theme:
<style name="CardDetailsDialogStyle" parent="#style/Theme.AppCompat.Light.Dialog" >
<item name="android:windowBackground">#null</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowFrame">#null</item>
<item name="android:windowIsFloating">true</item>
<item name="android:windowContentOverlay">#null</item>
<item name="android:windowAnimationStyle">#android:style/Animation.Dialog</item>
<item name="android:windowSoftInputMode">stateUnspecified|adjustPan</item>
</style>
And the style of the fragment:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/pp.whiteBackgroundColor" >
<android.support.v7.widget.Toolbar xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/card_details_toolbar"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_alignParentTop="true"
app:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="#style/PopupMenutheme">
</android.support.v7.widget.Toolbar>
<ScrollView
android:id="#+id/details_scrollview"
android:layout_height="wrap_content"
android:layout_width="match_parent">
All subview elements here...
</ScrollView>
</RelativeLayout>
This is the result:
As you can see, the ToolBar extends over the StatusBar and hardware buttons. I don't know if I am approaching this correctly. Am I missing something?
EDIT
This is what the same view look likes when I remove
getDialog().getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
For anyone who's still having this problem, do the following. This just solves half of the problem that is posted i.e. black status bar.
Add following theme to res/value-v21/style
<style name="DialogTheme" parent="#style/Base.Theme.AppCompat.Light.Dialog">
<item name="android:windowTranslucentStatus">true</item>
</style>
And then apply Style on DialogFragment in onCreate
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStyle(DialogFragment.STYLE_NO_TITLE, R.style.DialogTheme);
}
Edit
if you've problem with your dialog theme then use this style e.g. colorAccent or colorControlHighlight etc
<style name="DialogTheme" parent="#style/ThemeOverlay.AppCompat.Dialog">
<item name="android:windowTranslucentStatus">true</item>
</style>
In my case SYSTEM_UI_FLAG_LAYOUT_STABLE solved problem with overlapping
int width = ViewGroup.LayoutParams.MATCH_PARENT;
int height = ViewGroup.LayoutParams.MATCH_PARENT;
dialog.getWindow().setLayout(width,height);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
dialog.getWindow().setStatusBarColor(getResources().getColor(R.color.darkGrayTransp));
dialog.getWindow().getDecorView().setSystemUiVisibility(SYSTEM_UI_FLAG_LAYOUT_STABLE);//solves issue with statusbar
dialog.getWindow().setGravity(Gravity.CENTER_HORIZONTAL| Gravity.TOP);
}
Try use the same Style from your App. I tested with simple dialog without fragment and works fine.
Like that:
new Dialog(context, R.style.CardDetailsDialogStyle);
You have to set fitsystemwindows = true. Other way is to add a Space with 0dp and change its height to 25dp when the dialog is going to show.
To change the space size, use layout params, check this post: How to create a RelativeLayout programmatically with two buttons one on top of the other?
<style name="DialogTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowFullscreen">true</item>
<item name="android:windowIsFloating">false</item>
</style>
Just apply android:fitsSystemWindows="true" to your root ViewGroup:
`<FrameLayout
android:fitsSystemWindows="true">
<View .../>
I used Android Studio to implement the Navigation Drawer and I can't get the blue colour that is used to show which section we're currently in to change.
I've tried numerous things, I'm currently using a listSelector which looks like:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_activated="true" android:drawable="#color/selected" />
<item android:state_pressed="true" android:drawable="#color/highlight" />
</selector>
I've also tried state_checked. state_pressed works in this situation but the currently selected item is still blue.
EDIT:
I've been examining this more and when the adapter is created the context that is passed is getActionBar().getThemedContext() so I'm thinking if I can find the right attribute to assign to my actionbar style I can change it from there. I've tried a few different attributes with no luck. Does anyone know the exact attribute?
I've also realised if I put
<item name="android:activatedBackgroundIndicator">#drawable/nav_listview_selector</item>
in the main part of my theme and change getActionBar().getThemedContext() for getActivity.getBaseContext then I can change the color but I don't think this is the correct way. I think the themed context should be used. So if anyone knows where the activatedBackgroundIndicator could be put so that it would be used in getActionBar.getThemedContext()
EDIT2:
So the text view used for the listview is one within the SDK it looks like this:
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#android:id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceListItemSmall"
android:gravity="center_vertical"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:background="?android:attr/activatedBackgroundIndicator"
android:minHeight="?android:attr/listPreferredItemHeightSmall"
/>
So I tried modifying the "?android:attr/activatedBackgroundIndicator" at the theme level but it has no effect for checked/selected/activated but it does for pressed. Does anyone know why this is? And how I can change it?
To solve this problem:
1- You don't need android:listSelector under your ListView.
2- Open (or Create) styles.xml under (res/values).
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="android:activatedBackgroundIndicator">#drawable/drawer_list_selector</item>
</style>
3- Under res/drawable folder create drawer_list_selector.xml file
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="#drawable/light_gray_color" />
<item android:state_activated="true" android:drawable="#drawable/red_color" />
<item android:drawable="#android:color/transparent" />
</selector>
4- Under res/drawable create red_color.xml / light_gray_color.xml (or any other name) and add your desired Hex color:
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#C8FF0000"/>
</shape>
5- Open your project AndroidManifest.xml and add android:theme tag (if not exist)
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
Reference / Credit: Changing Navigation Drawer Selected Item Color from default blue
To change the "Navigation Drawer item background colour for selected item" you could do it with the attribut:
colorControlHighlight
In your "styles.xml" it could look like this:
<style name="YourStyleNameFor.NavigationDrawer" parent="ThemeOverlay.AppCompat.Light">
<item name="colorControlHighlight">#color/your_highlight_color</item>
</style>
Don't forget to apply your Style in the tag:
android.support.design.widget.NavigationView
For example in your activity_main.xml it could look like this:
<android.support.design.widget.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="#layout/navigationdrawer_header"
<!-- the following line referes to your style -->
app:theme="#style/YourThemeNameFor.NavigationDrawer"
<!-- the following two lines are maybe also interesting for you -->
app:itemIconTint="#color/gray3"
app:itemTextColor="#color/gray3"
app:menu="#menu/navigationdrawer_main" />
This is working for me:
First define a drawable item_bg.xml as:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:drawable="#drawable/nav_menu_bg" />
</selector>
Then use this drawable in navigation_main_layout.xml as:
<android.support.design.widget.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:itemBackground="#drawable/item_bg"
android:fitsSystemWindows="true"
app:headerLayout="#layout/nav_header_navigation"
app:menu="#menu/navigation_main_layout_drawer" />
here is how i have done and it is working, the brief concept is maintain the position of selected item in adapter and call notifyDataSetChanged on calling notifyDatasetChanged the getView method is called again and in get view check the position on the selected position change the background view. Here is the code :
Adapter of NavigationDrawer List View
public class MenuAdapter extends BaseAdapter {
private static final int TYPE_HEADER = 0;
private static final int TYPE_ITEM = 1;
private Context mContext;
private String name;
private int profile;
private int mIcons[];
private int selectedPosition = 0;
private String mNavTitles[];
private LayoutInflater mInflater;
public MenuAdapter(String titles[], int icon[], String Name, int profile) {
mNavTitles = titles;
mIcons = icon;
name = Name;
this.profile = profile;
}
public MenuAdapter(String Titles[], int Icons[], Context mContext) {
mNavTitles = Titles;
mIcons = Icons;
this.mContext = mContext;
mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return mNavTitles.length;
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
convertView = mInflater.inflate(R.layout.item_row, parent, false);
TextView textView = (TextView) convertView.findViewById(R.id.rowText);
ImageView imageView = (ImageView) convertView.findViewById(R.id.rowIcon);
final LinearLayout layout = (LinearLayout) convertView.findViewById(R.id.outerLayout);
imageView.setImageResource(mIcons[position]);
textView.setText(mNavTitles[position]);
if (position == selectedPosition)
layout.setBackgroundColor(mContext.getResources().getColor(R.color.app_bg));
else
layout.setBackgroundColor(mContext.getResources().getColor(R.color.normal_bg));
return convertView;
}
public void setSelectedPosition(int position) {
this.selectedPosition = position;
}
}
in your activity do this
private class DrawerItemClickListener implements ListView.OnItemClickListener {
#Override
public void onItemClick(AdapterView parent, View view, int position, long id) {
mMenuAdapter.setSelectedPosition(position - 1);
mMenuAdapter.notifyDataSetChanged();
}
}
if anyone still face any difficulty, feel free to ask.
I have implement drawer menu with custom adapter class. May be it will help someone Drawer List
<ListView
android:id="#+id/listview_drawer"
android:layout_width="260dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#color/menu_item_color"
android:choiceMode="singleChoice"
android:divider="#android:color/transparent"
android:dividerHeight="0dp"
android:fadingEdge="none"
/>
drawer_list_item.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/menu_selector"
>
<ImageView
android:id="#+id/imgIcon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:src="#drawable/ic_menu_home" />
<TextView
android:id="#+id/lblName"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_centerVertical="true"
android:gravity="center_vertical"
android:layout_toRightOf="#+id/imgIcon"
android:minHeight="48dp"
android:textColor="#color/menu_txt_color" />
menu_selector.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android" android:exitFadeDuration="#android:integer/config_mediumAnimTime">
<!-- selected -->
<item android:drawable="#color/menu_item_active_color" android:state_focused="true" android:state_pressed="false"/>
<item android:drawable="#color/menu_item_active_color" android:state_pressed="true"/>
<item android:drawable="#color/menu_item_active_color" android:state_activated="true"/>
<item android:drawable="#color/menu_item_active_color" android:state_checked="true"/>
<item android:drawable="#color/menu_item_active_color" android:state_selected="true"/>
<item android:drawable="#color/menu_item_color" android:state_activated="false"/>
Add this on item click listner of listview
yourlistview.setItemChecked(position, true);
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#color/list_item_back_pressed" android:state_pressed="true" />
<item android:state_activated="true"><color android:color="#color/primary_blue"/></item>
<item android:drawable="#color/list_item_back_normal"/>
</selector>
In addition to providing a custom selector drawable for the listSelector, you should also set the background resource of the list item to a similar selector drawable that has different drawables for the different states.
I usually use my custom adapter that has an int selection field, and a setSelection(int) function. And in the getView function I set the background of the view according to position == selection.
Still not sure why it is that it doesn't work. But the way I found around it is to use my own simple_list_item_activated layout to be passed to the ArrayAdapter which was basically the same except for setting the text colour to white. I then replaced getActionBar().getThemedContext() with getActivity().getBaseContext() and it now has an effect.
This may not be the correct way and may have repercussions in the future, but for now I have it working the way I want it to.
I know its too late but I have solved this issue in my app.
Pls dont think it is silly, just simply change the position of "state_pressed" to top.
<item android:drawable="#drawable/list_item_bg_pressed" android:state_pressed="true"/>
<item android:drawable="#drawable/list_item_bg_normal" android:state_activated="false"/>
<item android:drawable="#drawable/list_item_bg_selected" android:state_activated="true"/>
In Future if anyone comes here using, Navigation Drawer Activity (provided by Studio in Activity Prompt window)
The answer is -
Use this before OnCreate() in MainActivity
int[][] state = new int[][] {
new int[] {android.R.attr.state_checked}, // checked
new int[] {-android.R.attr.state_checked}
};
int[] color = new int[] {
Color.rgb(255,46,84),
(Color.BLACK)
};
ColorStateList csl = new ColorStateList(state, color);
int[][] state2 = new int[][] {
new int[] {android.R.attr.state_checked}, // checked
new int[] {-android.R.attr.state_checked}
};
int[] color2 = new int[] {
Color.rgb(255,46,84),
(Color.GRAY)
};
ColorStateList csl2 = new ColorStateList(state2, color2);
and use this in onNavigationItemSelected() in MainActivity (you dont need to Write this function if you use Navigation Drawer activity, it will be added in MainActivity).
NavigationView nav = (NavigationView) findViewById(R.id.nav_view);
nav.setItemTextColor(csl);
nav.setItemIconTintList(csl2);
nav.setItemBackgroundResource(R.color.white);
Tip - add this code before If else Condition in onNavigationItemSelected()
This worked for me :
implemented menu drawer not by populating the navigation view with list, but with menu items.
created a drawable like this :
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#color/drawer_menu_selector_color" android:state_checked="true"></item>
<item android:drawable="#color/drawer_menu_selector_color" android:state_activated="true"></item>
and in onCreate method , set the id of the menu item which corresponds to selected activity as checked.
and implement the drawable selector file to your navigation drawer like this
app:itemBackground="#drawable/drawer_menu_selector"
fyi : need to define your 'app' namespace.
I searched for solution on this issue, tried everything, and only this solution worked for me.
You can find it on this link https://tuchangwei.github.io/2016/07/18/The-solution-that-the-menu-item-of-Navigation-View-can-t-change-its-background-When-it-is-selected-checked/
All the credit to https://tuchangwei.github.io/
I am creating an app that has 4 main sections. I would like to have a very simple way of doing the navigation which would mean if the phone supports an action bar, then I would like it to display a tabbed action bar. Otherwise the regular menu button showing the menu is fine.
The problem is though that the action bar seams un-manageable or un-created when trying it out on phones with an sdk version that actually supports action bars.
I am using a menu/menu.xml file to create the menu and items that I want to display. I am then using onCreateOptionsMenu() with MenuInflater to populate the menu for each Activity. This works just fine on all phones but on phones that use the action bar, I get a title-type bar with the app icon on the far left, the current Activity title next to it, and then on the far right is the icon for the first menu item followed by the 3 squares (which when you click on them, show the rest of the menu items). This situation stays the same regardless of the Activity that I am in.
What I want is a tabbed action bar to show up instead with the icon and text (if there is room for the text) and have whatever current Activity the user is viewing to be "selected" in the tabbed-action bar. The same way shown here:
http://developer.android.com/images/ui/actionbar.png (I can't make it an image due to being a new user)
Here is the code I am using:
manifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mypackage"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission
android:name="android.permission.INTERNET" />
<uses-permission
android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission
android:name="android.permission.READ_PHONE_STATE" />
<uses-sdk
android:minSdkVersion="10"
android:targetSdkVersion="15" />
<application
android:icon="#drawable/icon"
android:label="#string/app_name"
android:theme="#android:style/Theme.Holo">
<uses-library android:name="com.google.android.maps" />
<activity
android:name=".ActivityLoad"
android:label="label">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
....more activities....
</application>
</manifest>
menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/menuMap"
android:title="#string/A_MAP_TITLE"
android:icon="#drawable/nav_map"
android:showAsAction="ifRoom|withText">
</item>
<item
android:id="#+id/menuList"
android:title="#string/A_LIST_TITLE"
android:icon="#drawable/nav_list"
android:showAsAction="ifRoom|withText">
</item>
<item
android:id="#+id/menuMore"
android:title="#string/A_MORE_TITLE"
android:icon="#drawable/nav_more"
android:showAsAction="ifRoom|withText">
</item>
<item
android:id="#+id/menuReport"
android:title="#string/A_REPORT_TITLE"
android:icon="#drawable/nav_report"
android:showAsAction="ifRoom|withText">
</item>
</menu>
MyActivity.java
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.options, menu);
return super.onCreateOptionsMenu(menu);
}
I have tried setting the action bar navigation mode using this code in my activities onCreate() method but all that happens is a blank action bar is shown below the "bad" action bar that I get by default:
ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
All the tutorials seam to just say "use a style" or something but I have no idea where to put a style xml file or how to set this to my menu or what I should actually be doing here. If anyone could help it would be greatly appreciated!
First make sure your MyActivity.java is implementing ActionBar.TabListener
which means you will need to override 3 functions.
I don't know how you did your fragments but this is how I did it in MyActivity.java:
public class MyActivity extends FragmentActivity implements ActionBar.TabListener {
private static final String STATE_SELECTED_NAVIGATION_ITEM = "selected_navigation_item";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Set up the action bar.
final ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// For each of the section, add a tab to the action bar.
actionBar.addTab(actionBar.newTab().setText(R.string.title_status).setTabListener(this));
actionBar.addTab(actionBar.newTab().setText(R.string.title_configuration).setTabListener(this));
}
#Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
if (savedInstanceState.containsKey(STATE_SELECTED_NAVIGATION_ITEM)) {
getActionBar().setSelectedNavigationItem(
savedInstanceState.getInt(STATE_SELECTED_NAVIGATION_ITEM));
}
}
#Override
public void onSaveInstanceState(Bundle outState) {
outState.putInt(STATE_SELECTED_NAVIGATION_ITEM,
getActionBar().getSelectedNavigationIndex());
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
//getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
#Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
#Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
// When the given tab is selected, show the tab contents in the container
Fragment fragment = new DummySectionFragment();
Bundle args = new Bundle();
args.putInt(DummySectionFragment.ARG_SECTION_NUMBER, tab.getPosition() + 1);
fragment.setArguments(args);
getSupportFragmentManager().beginTransaction()
.replace(R.id.container, fragment)
.commit();
}
#Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
/**
* A dummy fragment representing a section of the app, but that simply displays dummy text.
*/
public static class DummySectionFragment extends Fragment {
public DummySectionFragment() {
}
public static final String ARG_SECTION_NUMBER = "section_number";
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
TextView textView = new TextView(getActivity());
textView.setGravity(Gravity.CENTER);
Bundle args = getArguments();
textView.setText(Integer.toString(args.getInt(ARG_SECTION_NUMBER)));
return textView;
}
}
}
In order to customize the actionbar you need to use a custom style that has Theme.Holo as a parent. This way it inherits everything from the Holo theme but then you can overwride what you want. Inside manifest.xml use:
<application
android:theme="#style/AppTheme">
instead of:
<application
android:theme="#android:style/Theme.Holo">
Then inside values/styles.xml put your custom style:
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="AppTheme" parent="android:Theme.Holo.Light">
<item name="android:actionBarStyle">#style/MyActionBar</item>
<item name="android:actionBarTabStyle">#style/MyActionBarTabStyle</item>
<item name="android:actionBarTabBarStyle">#style/MyActionBarTabBar</item>
</style>
This is where it gets a little tricky. within the same file(values/styles.xml) you need to define each style you referenced above.
<style name="MyActionBar" parent="#android:style/Widget.Holo.Light.ActionBar">
<item name="android:background">#drawable/menu_bar</item> <!-- remove if you don't have custom background for action bar -->
<item name="android:displayOptions"></item> <!-- get rid of logo on left and title, if you want logo on left put useLogo here -->
<item name="android:customNavigationLayout">#layout/custom_action_bar</item> <!-- This is where you define how you want things to layout in your actionbar. I use a relative layout -->
</style>
<!-- Style for tab bar -->
<style name="MyActionBarTabBar" parent="#android:style/Widget.Holo.Light.ActionBar.TabBar">
<item name="android:showDividers">none</item>
<item name="android:paddingLeft">20dp</item>
</style>
<!-- Style for action bar tabs -->
<style name="MyActionBarTabStyle" parent="#android:style/Widget.Holo.Light.ActionBar.TabView">
<item name="android:background">#drawable/menu_tab</item> <!-- I use a background for my tabs also -->
</style>
If you don't care about custom background for each tab remove the last style from above.
If you have a custom background for each tab (you will need a selected state .9.png image and a not selected state .9.png image), you will need drawable/menu_tab.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"
android:constantSize="false"
android:dither="true"
android:variablePadding="false" >
<item android:state_selected="true" >
<inset android:insetTop="23dp"
android:insetBottom="26dp" >
<bitmap android:src="#drawable/menu_selected" ></bitmap>
</inset>
</item>
<item android:state_selected="false" >
<inset android:insetTop="20dp"
android:insetBottom="26dp" >
<bitmap android:src="#drawable/menu_not_selected" ></bitmap>
</inset>
</item>
</selector>
Now create layout/custom_action_bar.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:contentDescription="#string/LogoText"
android:paddingRight="20dp"
android:paddingTop="20dp"
android:src="#drawable/ic_launcher" />
</RelativeLayout>
The custom_action_bar can be however you want to layout the rest of the action bar elements. I just put the logo on the right but in your case you can use the overflow menu button or whatever you want. I use a custom background for the action bar and for each tab. If you do so you will need to create .9.png files to make sure they are compatible with different screens.
The finished result looks like: