Apply tint to PreferenceActivity widgets with AppCompat v21 - android

I'm using CheckboxPreference in a PreferenceActivity and an AppCompat theme from the v21 support library. As you already know, with this latest library widgets like checkboxes, editTexts, radio buttons etc are tinted with the secondary color defined in the theme. In the preference screen, text is in the right color as specifified by my theme, but checkboxes and edittext are not. It seems that when the CheckboxPreference instance creates the widget, it doesn't apply my theme to it.
Radio buttons in a normal layout, tinted:
Checkbox from the CheckboxPreference, not tinted:
I'm using as the parent theme Theme.AppCompat.Light.NoActionBar. This happens to every subclass of Preference with a widget, like EditTextPreference to say one, where the EditText has a black bottom line, instead of a tinted line. How can I apply the tint to the widgets shown by the Preference subclasses?
UPDATE: tinting is not applied because PreferenceActivity extends the framework Activity. In the working case, I'm using an ActionBarActivity from the support library. Now the question is: how come?

Edit: As of AppCompat 22.1, any activity can be themed using AppCompatDelegate. The name of the tinted view classes also changed from v7.internal.widget.TintXYZ to v7.widget.AppCompatXYZ. The answer below is for AppCompat 22.0 and older.
I've also came across this problem and solved it by simply copying the code related to widget tinting from ActionBarActivity. One downside of this solution is that it relies on internal classes that might change or become unavailable in the future.
import android.support.v7.internal.widget.TintCheckBox;
import android.support.v7.internal.widget.TintCheckedTextView;
import android.support.v7.internal.widget.TintEditText;
import android.support.v7.internal.widget.TintRadioButton;
import android.support.v7.internal.widget.TintSpinner;
public class MyActivity extends PreferenceActivity {
#Override
public View onCreateView(String name, Context context, AttributeSet attrs) {
// Allow super to try and create a view first
final View result = super.onCreateView(name, context, attrs);
if (result != null) {
return result;
}
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
// If we're running pre-L, we need to 'inject' our tint aware Views in place of the
// standard framework versions
switch (name) {
case "EditText":
return new TintEditText(this, attrs);
case "Spinner":
return new TintSpinner(this, attrs);
case "CheckBox":
return new TintCheckBox(this, attrs);
case "RadioButton":
return new TintRadioButton(this, attrs);
case "CheckedTextView":
return new TintCheckedTextView(this, attrs);
}
}
return null;
}
}
This works because onCreateView gets called by the LayoutInflater service for every view that is being inflated from a layout resource, which allows the activity to override which classes get instantiated. Make sure that the activity theme is set to Theme.AppCompat. (or descendants) in the manifest.
See ActionBarActivity.java and ActionBarActivityDelegateBase.java for the original code.

I know this questions is kinda old but I wanted to leave a solution to overcome this issue you've experienced.
First of all I'd like to say that the PreferenceActivity is a relic of pre-honeycomb times so don't expect Google to tint your Widgets in this really really old Activity subset.
Instead of the PreferenceActivity you should use PreferenceFragments which will be wrapped in an Activity (preferably an ActionbarActivity if you want your Widgets to be tinted).
Following a pretty basic code example how your Settings Activity should look like.
Example
public class MySettings extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.settings_activity);
getFragmentManager().beginTransaction()
.replace(R.id.container, new MyPreferenceFragment()).commit();
}
public static class MyPreferenceFragment extends PreferenceFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences_file);
}
}
}
Note: In this example I've used a FrameLayout as my container for the PreferenceFragments
Result:
So as you can see your Widgets will be tinted properly according to the colorAccent you've set.
More about PreferenceFragments on developer.android.com (click).

So far, my own (sad) workaround was to create from scratch my own checkbox drawables, using the colors which the checkbox should have been tinted with in the first place.
In styles.xml:
<?xml version="1.0" encoding="utf-8"?>
<style name="AppThemeBase" parent="Theme.AppCompat.Light.NoActionBar">
...
<!-- edit the checkbox appearance -->
<item name="android:listChoiceIndicatorMultiple">#drawable/my_checkbox</item>
...
</style>
drawable/my_checkbox.xml:
<?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/checkbox_on" />
<item android:drawable="#drawable/checkbox_off" />
</selector>
checkbox_on" andcheckbox_off` are the PNG drawables for the selected and unselected states, obviously one for each screen density.
If you mind dimension consistency, the baseline (MDPI) dimension of the drawables should be 32px full asset and 18px optical square.

The solution given by Tamás Szincsák works great but it should be updated, if using appcompat-v7:22.1.1, as follows:
imports should be changed to
import android.support.v7.widget.AppCompatCheckBox;
import android.support.v7.widget.AppCompatCheckedTextView;
import android.support.v7.widget.AppCompatEditText;
import android.support.v7.widget.AppCompatRadioButton;
import android.support.v7.widget.AppCompatSpinner;
And respectively the switch should be
switch (name) {
case "EditText":
return new AppCompatEditText(this, attrs);
case "Spinner":
return new AppCompatSpinner(this, attrs);
case "CheckBox":
return new AppCompatCheckBox(this, attrs);
case "RadioButton":
return new AppCompatRadioButton(this, attrs);
case "CheckedTextView":
return new AppCompatCheckedTextView(this, attrs);
}

If you are using AppCompat, then use the app compat items in your style.xml file.
For example, use:
<style name="AppTheme" parent="Theme.AppCompat.Light">
<item name="colorPrimary">#color/primary</item>
<item name="colorPrimaryDark">#color/primary_dark</item>
<item name="colorAccent">#color/accent</item>
</style>
NOT (notice "android:"):
<style name="AppTheme" parent="Theme.AppCompat.Light">
<item name="android:colorPrimary">#color/primary</item>
<item name="android:colorPrimaryDark">#color/primary_dark</item>
<item name="android:colorAccent">#color/accent</item>
</style>
This fixed the issue for me.

Related

Android: Set style programmatically to custom button

I have an custom view which extends Button. And I just want to set the belove style to this view.
<style name="MultipleButtonStyle" parent="android:Widget.Material.Light.Spinner.Underlined">
<item name="android:textColor">#android:color/black</item>
<item name="android:textAppearance">?android:attr/textAppearanceMedium</item>
</style>
To be able set style programmatically, I have tried some way. But They didn't work for me.
The First way, is using the style in the constructor of the custom button like this :
public class SpinnerButton extends AppCompatButton{
public SpinnerButton (Context context) {
super(context, null, R.style.MultipleButtonStyle);
}
}
Second way is use setTextAppearance method. It didn't work me as well.
if (Build.VERSION.SDK_INT < 23) {
super.setTextAppearance(getContext(), R.style.MultipleButtonStyle );
} else {
super.setTextAppearance(R.style.MultipleButtonStyle);
}
your constructor looks fine, are you overriding also other ones (e.g. this with AttributeSet, which is called when inflating from XML)? check THIS question about Views constructors and some styling
second way is improper, because parent of your style is a style for whole Spinner.Underlined, not only for TextAppearance. in this case you should extend #android:style/TextAppearance.Medium (or other). if you choose this way then remember about deprecated setTextAppearance method in API23 and you may use some helper without checking OS version:
TextViewCompat.setTextAppearance(textView, android.R.style.TextAppearance_Medium);

Changing EditText bottom line color android [duplicate]

I am using appcompat v7 to get the look consistent on Android 5 and less. It works rather well. However I cannot figure out how to change the bottom line color and the accent color for EditTexts. Is it possible?
I have tried to define a custom android:editTextStyle (cf. below) but I only succeeded to change the full background color or text color but not the bottom line nor the accent color. Is there a specific property value to use? do I have to use a custom drawable image through the android:background property? is it not possible to specify a color in hexa?
<style name="Theme.App.Base" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="android:editTextStyle">#style/Widget.App.EditText</item>
</style>
<style name="Widget.App.EditText" parent="Widget.AppCompat.EditText">
???
</style>
According to android API 21 sources, EditTexts with material design seem to use colorControlActivated and colorControlNormal. Therefore, I have tried to override these properties in the previous style definition but it has no effect. Probably appcompat does not use it. Unfortunately, I cannot find the sources for the last version of appcompat with material design.
Finally, I have found a solution. It simply consists of overriding the value for colorControlActivated, colorControlHighlight and colorControlNormal in your app theme definition and not your edittext style. Then, think to use this theme for whatever activity you desire. Below is an example:
<style name="Theme.App.Base" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="colorControlNormal">#c5c5c5</item>
<item name="colorControlActivated">#color/accent</item>
<item name="colorControlHighlight">#color/accent</item>
</style>
I felt like this needed an answer in case somebody wanted to change just a single edittext. I do it like this:
editText.getBackground().mutate().setColorFilter(ContextCompat.getColor(context, R.color.your_color), PorterDuff.Mode.SRC_ATOP);
While Laurents solution is correct, it comes with some drawbacks as described in the comments since not only the bottom line of the EditText gets tinted but the Back Button of the Toolbar, CheckBoxes etc. as well.
Luckily v22.1 of appcompat-v7 introduced some new possibilities. Now it's possible to assign a specific theme only to one view. Straight from the Changelog:
Deprecated use of app:theme for styling Toolbar. You can now use android:theme for toolbars on all API level 7 and higher devices and android:theme support for all widgets on API level 11 and higher devices.
So instead of setting the desired color in a global theme, we create a new one and assign it only to the EditText.
Example:
<style name="MyEditTextTheme">
<!-- Used for the bottom line when not selected / focused -->
<item name="colorControlNormal">#9e9e9e</item>
<!-- colorControlActivated & colorControlHighlight use the colorAccent color by default -->
</style>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/MyEditTextTheme"/>
This can be changed in XML by using:
For Reference API >= 21 compatibility use:
android:backgroundTint="#color/blue"
For backward API < 21 compatibility use:
app:backgroundTint="#color/blue"
Here is the solution for API < 21 and above
Drawable drawable = yourEditText.getBackground(); // get current EditText drawable
drawable.setColorFilter(Color.GREEN, PorterDuff.Mode.SRC_ATOP); // change the drawable color
if(Build.VERSION.SDK_INT > 16) {
yourEditText.setBackground(drawable); // set the new drawable to EditText
}else{
yourEditText.setBackgroundDrawable(drawable); // use setBackgroundDrawable because setBackground required API 16
}
Hope it help
The accepted answer is a bit more per style basis thing, but the most efficient thing to do is to add the colorAccent attribute in your AppTheme style like this:
<style name="AppTheme.Base" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorAccent">#color/colorAccent</item>
<item name="android:editTextStyle">#style/EditTextStyle</item>
</style>
<style name="EditTextStyle" parent="Widget.AppCompat.EditText"/>
The colorAccent attribute is used for widget tinting throughout the app and thus should be used for consistency
If you are using appcompat-v7:22.1.0+ you can use the DrawableCompat to tint your widgets
public static void tintWidget(View view, int color) {
Drawable wrappedDrawable = DrawableCompat.wrap(view.getBackground());
DrawableCompat.setTint(wrappedDrawable.mutate(), getResources().getColor(color));
view.setBackgroundDrawable(wrappedDrawable);
}
<!-- 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>
<item name="colorControlNormal">#color/colorAccent</item>
<item name="colorControlActivated">#color/colorAccent</item>
<item name="colorControlHighlight">#color/colorAccent</item>
</style>
Use:
<EditText
app:backgroundTint="#color/blue"/>
This will support pre-Lollipop devices not only +21
One quick solution for your problem is to look in yourappspackage/build/intermediates/exploded-aar/com.android.support/appcompat-v7/res/drawable/ for abc_edit_text_material.xml and copy that xml file in your drawable folder. Then you can change the colour of the 9 patch files from inside this selector, in order to match your preferences.
It's very easy just add android:backgroundTint attribute in your EditText.
android:backgroundTint="#color/blue"
android:backgroundTint="#ffffff"
android:backgroundTint="#color/red"
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:backgroundTint="#ffffff"/>
Here is a part of source code of TextInputLayout in support design library(UPDATED for version 23.2.0), which changes EditText's bottom line color in a simpler way:
private void updateEditTextBackground() {
ensureBackgroundDrawableStateWorkaround();
final Drawable editTextBackground = mEditText.getBackground();
if (editTextBackground == null) {
return;
}
if (mErrorShown && mErrorView != null) {
// Set a color filter of the error color
editTextBackground.setColorFilter(
AppCompatDrawableManager.getPorterDuffColorFilter(
mErrorView.getCurrentTextColor(), PorterDuff.Mode.SRC_IN));
}
...
}
It seems that all of above code become useless right now in 23.2.0 if you want to change the color programatically.
And if you want to support all platforms, here is my method:
/**
* Set backgroundTint to {#link View} across all targeting platform level.
* #param view the {#link View} to tint.
* #param color color used to tint.
*/
public static void tintView(View view, int color) {
final Drawable d = view.getBackground();
final Drawable nd = d.getConstantState().newDrawable();
nd.setColorFilter(AppCompatDrawableManager.getPorterDuffColorFilter(
color, PorterDuff.Mode.SRC_IN));
view.setBackground(nd);
}
I too was stuck on this problem for too long.
I required a solution that worked for versions both above and below v21.
I finally discovered a very simple perhaps not ideal but effective solution: Simply set the background colour to transparent in the EditText properties.
<EditText
android:background="#android:color/transparent"/>
I hope this saves someone some time.
For me I modified both the AppTheme and a value colors.xml Both the colorControlNormal and the colorAccent helped me change the EditText border color. As well as the cursor, and the "|" when inside an EditText.
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorControlNormal">#color/yellow</item>
<item name="colorAccent">#color/yellow</item>
</style>
Here is the colors.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="yellow">#B7EC2A</color>
</resources>
I took out the android:textCursorDrawable attribute to #null that I placed inside the editText style. When I tried using this, the colors would not change.
You can set background of edittext to a rectangle with minus padding on left, right and top to achieve this. Here is the xml example:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:top="-1dp"
android:left="-1dp"
android:right="-1dp"
android:bottom="1dp"
>
<shape android:shape="rectangle">
<stroke android:width="1dp" android:color="#6A9A3A"/>
</shape>
</item>
</layer-list>
Replace the shape with a selector if you want to provide different width and color for focused edittext.
I worked out a working solution to this problem after 2 days of struggle, below solution is perfect for them who want to change few edit text only, change/toggle color through java code, and want to overcome the problems of different behavior on OS versions due to use setColorFilter() method.
import android.content.Context;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.AppCompatDrawableManager;
import android.support.v7.widget.AppCompatEditText;
import android.util.AttributeSet;
import com.newco.cooltv.R;
public class RqubeErrorEditText extends AppCompatEditText {
private int errorUnderlineColor;
private boolean isErrorStateEnabled;
private boolean mHasReconstructedEditTextBackground;
public RqubeErrorEditText(Context context) {
super(context);
initColors();
}
public RqubeErrorEditText(Context context, AttributeSet attrs) {
super(context, attrs);
initColors();
}
public RqubeErrorEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initColors();
}
private void initColors() {
errorUnderlineColor = R.color.et_error_color_rule;
}
public void setErrorColor() {
ensureBackgroundDrawableStateWorkaround();
getBackground().setColorFilter(AppCompatDrawableManager.getPorterDuffColorFilter(
ContextCompat.getColor(getContext(), errorUnderlineColor), PorterDuff.Mode.SRC_IN));
}
private void ensureBackgroundDrawableStateWorkaround() {
final Drawable bg = getBackground();
if (bg == null) {
return;
}
if (!mHasReconstructedEditTextBackground) {
// This is gross. There is an issue in the platform which affects container Drawables
// where the first drawable retrieved from resources will propogate any changes
// (like color filter) to all instances from the cache. We'll try to workaround it...
final Drawable newBg = bg.getConstantState().newDrawable();
//if (bg instanceof DrawableContainer) {
// // If we have a Drawable container, we can try and set it's constant state via
// // reflection from the new Drawable
// mHasReconstructedEditTextBackground =
// DrawableUtils.setContainerConstantState(
// (DrawableContainer) bg, newBg.getConstantState());
//}
if (!mHasReconstructedEditTextBackground) {
// If we reach here then we just need to set a brand new instance of the Drawable
// as the background. This has the unfortunate side-effect of wiping out any
// user set padding, but I'd hope that use of custom padding on an EditText
// is limited.
setBackgroundDrawable(newBg);
mHasReconstructedEditTextBackground = true;
}
}
}
public boolean isErrorStateEnabled() {
return isErrorStateEnabled;
}
public void setErrorState(boolean isErrorStateEnabled) {
this.isErrorStateEnabled = isErrorStateEnabled;
if (isErrorStateEnabled) {
setErrorColor();
invalidate();
} else {
getBackground().mutate().clearColorFilter();
invalidate();
}
}
}
Uses in xml
<com.rqube.ui.widget.RqubeErrorEditText
android:id="#+id/f_signup_et_referral_code"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_toEndOf="#+id/referral_iv"
android:layout_toRightOf="#+id/referral_iv"
android:ems="10"
android:hint="#string/lbl_referral_code"
android:imeOptions="actionNext"
android:inputType="textEmailAddress"
android:textSize="#dimen/text_size_sp_16"
android:theme="#style/EditTextStyle"/>
Add lines in style
<style name="EditTextStyle" parent="android:Widget.EditText">
<item name="android:textColor">#color/txt_color_change</item>
<item name="android:textColorHint">#color/et_default_color_text</item>
<item name="colorControlNormal">#color/et_default_color_rule</item>
<item name="colorControlActivated">#color/et_engagged_color_rule</item>
</style>
java code to toggle color
myRqubeEditText.setErrorState(true);
myRqubeEditText.setErrorState(false);
In Activit.XML add the code
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textPersonName"
android:ems="10"
android:id="#+id/editText"
android:hint="Informe o usuário"
android:backgroundTint="#android:color/transparent"/>
Where BackgroundTint=color for your desired colour
I use this method to change the color of the line with PorterDuff, with no other drawable.
public void changeBottomColorSearchView(int color) {
int searchPlateId = mSearchView.getContext().getResources().getIdentifier("android:id/search_plate", null, null);
View searchPlate = mSearchView.findViewById(searchPlateId);
searchPlate.getBackground().setColorFilter(color, PorterDuff.Mode.SRC_IN);
}
If you want change bottom line without using app colors, use these lines in your theme:
<item name="android:editTextStyle">#android:style/Widget.EditText</item>
<item name="editTextStyle">#android:style/Widget.EditText</item>
I don't know another solution.
I was absolutely baffled by this problem. I had tried everything in this thread, and in others, but no matter what I did I could not change the color of the underline to anything other than the default blue.
I finally figured out what was going on. I was (incorrectly) using android.widget.EditText when making a new instance (but the rest of my components were from the appcompat library). I should have used android.support.v7.widget.AppCompatEditText. I replaced new EditText(this) with new AppCompatEditText(this)
and the problem was instantly solved. It turns out, if you are actually using AppCompatEditText, it will just respect the accentColor from your theme (as mentioned in several comments above) and no additional configuration is necessary.
This is the easiest and most efficient/reusable/works on all APIs
Create a custom EditText class like so:
public class EditText extends android.widget.EditText {
public EditText(Context context) {
super(context);
init();
}
public EditText(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public EditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
getBackground().mutate().setColorFilter(ContextCompat.getColor(getContext(), R.color.colorAccent), PorterDuff.Mode.SRC_ATOP);
}
}
Then use it like this:
<company.com.app.EditText
android:layout_width="200dp"
android:layout_height="wrap_content"/>
To change the EditText background dynamically, you can use ColorStateList.
int[][] states = new int[][] {
new int[] { android.R.attr.state_enabled}, // enabled
new int[] {-android.R.attr.state_enabled}, // disabled
new int[] {-android.R.attr.state_checked}, // unchecked
new int[] { android.R.attr.state_pressed} // pressed
};
int[] colors = new int[] {
Color.BLACK,
Color.RED,
Color.GREEN,
Color.BLUE
};
ColorStateList colorStateList = new ColorStateList(states, colors);
Credits: This SO answer about ColorStateList is awesome.
You can use just backgroundTint for change bottom line color of edit text
android:backgroundTint="#000000"
example :
<EditText
android:id="#+id/title1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:backgroundTint="#000000" />
Add app:backgroundTint for below api level 21. Otherwise use android:backgroundTint.
For below api level 21.
<EditText
android:id="#+id/edt_name"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:textColor="#0012ff"
app:backgroundTint="#0012ff"/>
For higher than api level 21.
<EditText
android:id="#+id/edt_name"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:textColor="#0012ff"
android:backgroundTint="#0012ff"/>
Please modify this method according to your need. This worked for me!
private boolean validateMobilenumber() {
if (mobilenumber.getText().toString().trim().isEmpty() || mobilenumber.getText().toString().length() < 10) {
input_layout_mobilenumber.setErrorEnabled(true);
input_layout_mobilenumber.setError(getString(R.string.err_msg_mobilenumber));
// requestFocus(mobilenumber);
return false;
} else {
input_layout_mobilenumber.setError(null);
input_layout_mobilenumber.setErrorEnabled(false);
mobilenumber.setBackground(mobilenumber.getBackground().getConstantState().newDrawable());
}
}

Theme style for custom view

My app has several themes from which the user can chose (red, blue, green etc.) Every theme has a corresponding button style (RedTheme => RedButton).
Now I have created a custom view which slightly extends "Button" and unfortunately this button does not get any style, except I use the "style" attribute in a layout.xml.
I don’t use any additional attributes, I just want that my Button style is applied.
I want to do something similar than:
<item name="android:imageButtonStyle">#style/ImageButtonmyTimeRed</item>
I have already read many other posts like this one:
How to: Define theme (style) item for custom widget
but I’m not 100% sure if this solution fits for me since I don’t need any additional attributes.
I'm using the three parameter super constructor and pass the button style resource id. This works for all my custom themes. Thanks #pskink for pointing me into right direction.
public ClockButton(Context context, AttributeSet attrs) {
super(context, attrs, R.attr.buttonStyle);
...
}
My theme looks like this:
<style name="LilaTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="buttonStyle">#style/ButtonmyTimeLila</item>
</style>

Why is Cast MediaRouteButton always white even on Holo.Light Action-Bar?

I'm moving from a custom MediaRouteButton to one inside the action-bar but it doesn't display properly. The button when custom was white which is what I wanted. However, the button is still white (and barely visible) on the action-bar even though the action-bar is of "Holo.Light" style. The button should be dark.
The button is created as an XML menu item:
<item
android:id="#+id/menu_item_media_route"
android:title="#string/menu_item_media_route"
android:actionViewClass="android.support.v7.app.MediaRouteButton"
android:actionProviderClass="android.support.v7.app.MediaRouteActionProvider"
android:showAsAction="always" />
My app is of style "#style/AppTheme":
<style name="AppTheme" parent="android:Theme.Holo.Light">
</style>
My activity of of theme "#style/FullscreenActionbarTheme":
<style name="FullscreenActionbarTheme" parent="android:Theme.Holo.Light">
<item name="android:windowFullscreen">true</item>
<item name="android:windowActionBarOverlay">true</item>
<item name="android:windowContentOverlay">#null</item>
<item name="android:windowBackground">#null</item>
<item name="android:actionBarStyle">#style/FullscreenActionbar</item>
</style>
<style name="FullscreenActionbar" parent="#android:style/Widget.Holo.Light.ActionBar.Solid">
</style>
I have no custom "ic_media_route_(on|off).png" drawables -- I used to but removed them.
I've tried changing various styles and though the action-bar will turn dark, the cast button is always white. (As it should be on a dark action bar but not a light one.)
The button is fully functional, just the wrong color. The "chooser" dialog that appears when I press the button is styled "Holo.Light".
So why is my cast button colored white on a "Holo.Light" theme as though it was a "Holo" (dark) theme?
Taken from: Link
Caution: When implementing an activity that provides a media router
interface you must extend either ActionBarActivity or FragmentActivity
from the Android Support Library, even if your android:minSdkVersion
is API 11 or higher.
ActionBarActivity has been superseded by AppCompatActivity, so you should use that instead.
Support-V7 MediaRouteButton depends on this. Look at the super call:
public MediaRouteButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(MediaRouterThemeHelper.createThemedContext(context), attrs, defStyleAttr);
....
....
}
MediaRouterThemeHelper.createThemedContext(Context):
public static Context createThemedContext(Context context) {
boolean isLightTheme = isLightTheme(context);
return new ContextThemeWrapper(context, isLightTheme ?
R.style.Theme_MediaRouter_Light : R.style.Theme_MediaRouter);
}
isLightTheme is set by resolving R.attr.isLightTheme <<== This is a support library attribute. It will not be present when your parent theme is provided by the framework, as is the case with android:Theme.Holo.Light.
private static boolean isLightTheme(Context context) {
TypedValue value = new TypedValue();
return context.getTheme().resolveAttribute(R.attr.isLightTheme, value, true)
&& value.data != 0;
}
So, isLightTheme is false & you get the dark-theme version of MediaRouteButton ==> ... always white.
Note that the Caution statement implies that your parent theme must be an AppCompat theme - AppCompatActivity (or ActionBarActivity) can't work with android:Theme.*.
Edit:
A lot of discussion took place here: Link
One can go through the chat-log to read on the approaches tried. In the end, it seems that the media-router support library needs some work to be production-ready. Read more here: MediaRouteActionProvider connection dialog theme.
If all else fails you can change the color programmatically in onCreate():
ImageButton button = ((ImageButton) toolbar.getChildAt( ... )); // The view index of the button
button.setColorFilter(Color.BLACK, PorterDuff.Mode.MULTIPLY);

Prevent my android:theme from modifying dialogs?

My theme gives my app black text and yellow background, this works but I noticed it was also affecting AlertDialogs and making them look buggy.
I want to ensure my app theme only modifies Activities and Fragment's parent layout, but not dialogs or toasts. How can I restore them so they use the phone's default styling?
This is what I'm trying:
<style name="MyTheme" parent="android:style/Theme.Holo.NoActionBar.Fullscreen">
<!-- Colors -->
<item name="android:textColor">#000000</item>
<item name="android:background">#fffdf12a</item>
<!-- Restore Dialogs to default style -->
<item name="android:alertDialogStyle"></item>
</style>
According to my knowledge you can't do that for Dialogs created by System, like the ones in the Preferences but you can change of Dialogs which you create from sratch
Here's what I found from another answer :
protected AlertDialog(Context context) {
this(context, com.android.internal.R.style.Theme_Dialog_Alert);
}
public Builder(Context context) {
this(context, com.android.internal.R.style.Theme_Dialog_Alert);
}
You can see the values are Hardcoded & hence can't be changed

Categories

Resources