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

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);

Related

Color Android splash screen using theme

In my Xamarin Forms Android app, I would like to change the color of the splash screen based on a theme that the user has selected at run time. This change should impact the next run of the app.
I have tried using the built in splash_screen.xml and using a Splash.axml file, but I cannot figure out how (if possible) to set the background color of the splash screen to a color defined in a theme.
Is this possible?
I have tried using the built in splash_screen.xml and using a Splash.axml file, but I cannot figure out how (if possible) to set the background color of the splash screen to a color defined in a theme.
You can define themes for your splashScreen and then set android:windowBackground to a specific color:
styles.xml:
<resources>
<style name="AppTheme">
<item name="android:windowBackground">#color/colorPrimary</item>
<item name="android:windowNoTitle">true</item>
</style>
<style name="AppTheme2">
<item name="android:windowBackground">#color/colorAccent</item>
<item name="android:windowNoTitle">true</item>
</style>
...
</resources>
SplashScreen.cs( don't forget to set SplashScreen activity to be mainlauncher):
[Activity(Label = "SplashActivity",MainLauncher =true)]
public class SplashActivity : Activity
{
protected override void OnCreate(Bundle savedInstanceState)
{
ISharedPreferences preferences=GetSharedPreferences("SplashThemeId", FileCreationMode.Private);
var themeName=preferences.GetString("themeName","AppTheme");
int themeId = Resource.Style.AppTheme ;
switch (themeName)
{
case "AppTheme":
themeId = Resource.Style.AppTheme;
break;
case "AppTheme2":
themeId = Resource.Style.AppTheme2;
break;
}
SetTheme(themeId);
base.OnCreate(savedInstanceState);
...
As you noticed, I use SharedPreference to store the user selected Theme in Runtime. You can also use Android Settings for the same purpose.
Here is the complete demo. It's native android project, but it's the same for forms project.
After all of the research I've done and the things I've tried in code, I am concluding that it is not possible to dynamically set the color of the initial activity. I am going with a neutral color for the splash.

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

Apply tint to PreferenceActivity widgets with AppCompat v21

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.

Run a custom Dialog layout using Theme/Style

I need to run a custom dialog layout using only theme/style options. Running custom Dialog layout by code is not an option for me. I think this should be possible by mean of attributes "android:layout", "android:dialogLayout", "*android:dialogCustomTitleDecorLayout", "*android:dialogTitleIconsDecorLayout", "*android:dialogTitleDecorLayout".<br/><br/>
My Activity onCreate load layout in a Dialog Style:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTheme(R.style.MyDialog);
setContentView(R.layout.mydialog);
this.setTitle("A title");
}
style xml:
<style name="MyDialog" parent="android:Theme.Holo.Light.Dialog">
<item name="android:windowTitleStyle">#style/MyDialog.WindowTitle</item>
<item name="android:layout">#layout/dialog_title</item>
<item name="android:dialogLayout">#layout/dialog_title</item>
<item name="*android:dialogCustomTitleDecorLayout">#layout/dialog_title</item>
<item name="*android:dialogTitleIconsDecorLayout">#layout/dialog_title</item>
<item name="*android:dialogTitleDecorLayout">#layout/dialog_title</item>
</style>
<style name="MyDialog.WindowTitle">
<item name="android:maxLines">1</item>
<item name="android:scrollHorizontally">true</item>
<item name="android:textAppearance">#style/TextAppearance_WindowTitle</item>
</style>
<style name="TextAppearance_WindowTitle">
<item name="android:textSize">32sp</item>
<item name="android:textColor">#+color/verdeTI</item>
</style>
Please, note that Text colour of the title is correctly applied (#+color/verdeTI) so I am confident the cascading styling is right but it seems none of the layout options work at all because I continue to see the standard Dialog Layout. My "dialog_title" use a completely different ImageView for divider so I can be sure when it is loaded.
The custom divider is just the main reason because I need a different layout.
Update 15/4/2014
Android theme Guide stats:
Some style properties, however, are not supported by any View element and can only be applied as a theme. These style properties apply to the entire window and not to any type of View. For example, style properties for a theme can hide the application title, hide the status bar, or change the window's background. These kind of style properties do not belong to any View object. To discover these theme-only style properties, look at the R.attr reference for attributes that begin with window. For instance, windowNoTitle and windowBackground are style properties that are effective only when the style is applied as a theme to an Activity or application. See the next section for information about applying a style as a theme.
OK attributes starting with "window" are applied only in Themes not in Styles. What's about *Layout attributes ? When they are applied ?
You can try by passing ThemeName as argument of constructor like this way.
public class TestDialog extends Dialog{
public TestDialog(Context context) {
super(context, R.style.YourTheme);
// TODO Auto-generated constructor stub
}
}
Add window feature if you require.
Make object of this class in any Activity so you can use Dialog property.
:-
More info https://stackoverflow.com/a/18224754/942224
i was using this way. so it may be help you.
You can try by creating your required layout file and opening it with an activity class just in the manifest add this code to your activity
android:theme="#android:style/Theme. Dialog"
But you will be getting title bar in your dialog with this which is your label name for your activity. To remove it add this code before setContentView
requestWindowFeature(Window. FEATURE_NO_TITLE);

How to get the parent theme programmatically

Let's say I have the following custom theme declared in themes.xml:
<style name="Theme.Custom.Light" parent="#style/Theme.Sherlock.Light">
<item name="android:actionBarTabStyle">#style/Widget.Custom.Light.ActionBar.TabView</item>
<item name="android:actionBarTabTextStyle">#style/Widget.Custom.Light.ActionBar.TabText</item>
<item name="android:actionMenuTextColor">#color/ab_item_text</item>
<item name="android:actionMenuTextAppearance">#style/TextAppearance.Custom.Light.Widget.ActionBar.Menu</item>
</style>
From the application context, we are able to get the Theme class currently applied using
Theme myTheme = appContext.getTheme();
and also, we are able to get the theme's resource id using:
int themeResId = appContext.getApplicationInfo().theme;
What I want
From my code, I would like to check programmatically which is the parent theme of the theme I'm using in order to differentiate between Sherlock, Sherlock.Light & Sherlock.Light.DarkActionBar.
In the example above, I would like to know that I am using the Light variation of the Sherlock theme.
Note: You may wonder why I need to check the parent if I declared it in the xml. Reason is that I'm in a particular situation in which I actually won't know, but this goes beyond the scope of this question.
Theme myTheme = appContext.getTheme();
You can get its parent class using
Theme myThemeParent = appContext.getTheme().getClass().getSuperclass();
and compare it with Sherlock.getclass() to verify if it is the parent. Likewise for other comparisons.

Categories

Resources