I am trying To show a dialog from a PreferenceActivity, which is set to Theme.Light. The dialog shows with dark text on a dark background:
I assume it uses dark text because it is inheriting the text color from the parent activity, or something similar. I would like the dialog to either use white text on the dark background, or use a white background with dark text, as the PreferenceActivity does when set to Theme.Light.
This seems to be a known problem, the workarounds I have found involve creating and using a custom style that extends Theme.Dialog and using it to instantiate the dialog. Something like:
<style name="CustomDialog" parent="#android:style/Theme.Dialog">
<item name="android:textColor">?android:attr/textColorPrimaryInverseDisableOnly</item>
</style>
Dialog dialog = new Dialog(context, R.style.CustomDialog);
I tried this, but it made no difference. I also tried a number of different values for textColor, none of which modified the Dialog's text color. As a sanity check, I added:
<item name="android:background">#FFFF0000</item>
to the style, which resulted in a dialog with a red background (so I am sure that I am instantiating the dialog properly).
The closest I have come to a solution is just setting the dialog's background color to white, which gives the below dialog. But this is not a good solution, because some version or some device might not use the same behavior I am seeing when inverting text color:
So, is there a good way to set text color on a dialog displayed from a Theme.Light activity?
I assume that you use AlertDialog.Builder and set the list using one of the setSingleChoiceItems methods which doesn't use your own ListAdapter. Instead it creates its own instead with the wrong style. To fix this, you should call setSingleChoiceItems(ListAdapter adapter, int checkedItem, DialogInterface.OnClickListener listener) and provide such an adapter which would use a layout with the needed style.
Now, why this happens. The actual adapter creation happens in the file com.android.internal.app.AlertController, where the following line selects the layout for single choice lists:
int layout = mIsSingleChoice
? R.layout.select_dialog_singlechoice : R.layout.select_dialog_item;
Here is the aforementioned layout:
<CheckedTextView 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:minHeight="?android:attr/listPreferredItemHeight"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="#android:color/primary_text_light_disable_only"
android:gravity="center_vertical"
android:paddingLeft="12dip"
android:paddingRight="7dip"
android:checkMark="#android:drawable/btn_radio"
android:ellipsize="marquee"
/>
As you can see, the line which sets the text color contains not a reference to a theme, but a hardwired color. That's why when this thing gets inflated during the list creation, it will always use the same color, regardless of what style you want it to use. So the right action to overcome this problem is to use your own layout and your own ListAdapter.
Related
I was trying to apply a style to an EditText to change it's colorAccent, I tried to set its style and android:textAppearance, but it completely ignored my new settings. The only way I got it to work was by setting its android:theme.
Am I doing something wrong or is this expected behavior? Why?
My style:
<style name="bright_color_cursor" parent="AppTheme">
<item name="colorAccent">#color/primaryBrightColor</item>
<item name="android:textColorHighlight">#color/primaryBrightColor</item>
</style>
My EditText:
<EditText
android:id="#+id/edit_text"
android:theme="#style/bright_color_cursor"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp"
android:background="#android:color/transparent"
android:ems="10"
android:hint="#string/hello"
android:inputType="textCapWords"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="#+id/name_edit_text"
app:layout_constraintTop_toBottomOf="#+id/divider" />
Changing android:theme to any of this settings won't work:
style="#style/bright_color_cursor"
or
android:textAppearance="#style/bright_color_cursor"
Yep, this behavior is to be expected with an EditText. We need to style it by using the android:theme property.
When using #style, the EditText doesn't use the values that we set (and thus the style seems to be ignored). This is, because the EditText creates some children views that are not being styled. See my detailed explanation below.
Detailed explanation and the cause
1) First, the meanings of the options tried and what these do:
style: (Note: not prefixed with android:): This sets the styles only for the component itself and does not change the styles of it's underlying children views/layouts.
android:theme: This basically applies to style to itself and applies the style to it's children views/layouts.
android:textAppearance: This one behaves just like #style for styling.
2) The EditText functionality
As we can imagine: an EditText is not just a simple view. It has a background drawable and handles interaction and such. It simply needs some additional views (and logic) for this functionality to work.
For the functionality of the EditText, it adds some subviews as children to be able to do what we expect from it.
3) Back to theming
The subviews that the EditText adds to do it's functionality, are styled just like the other views are being styled. Which means that the child views only inherit the style when we use the android:theme property. Because this property causes it to style the children views too.
And, if we use #style on the edittext, the children will not get this style.
4) Why this happens (only) for EditText?
Well, not really only... The base view of an EditText is a TextView, but a TextView doesn't provide the functionality that an EditText needs. So the EditText adds additional functionality itself.
A Button for example has the TextView as base too. But this class has enough views with the text and background it gets from the base class, and thus a Button doesn't need to add additional views for it's functionality. So for this, using #style works as it creates no children views to style.
Having said this, a small remark:
In fact, in the source the TextView actually contains the editting logic, but in case of a Button it simply doesn't execute that part of code. (A button doesn't need the Editting functionality, thus it's not being executed)
I have a popup which is shown when I receive a GCM notification. The popup is implemented as a LinearLayout which is setContentView'd in the popup activity. The layout render in Android Studio looks like this:
However, on the device and on the DebugMonitor View Hierarchy dump it does not show, although it is there:
The TextView has the default text "Where?" replaced in the extended Activity class:
String lightName = getIntent().getStringExtra(LIGHT_NAME_KEY);
final TextView lightNameLabel = (TextView) findViewById(R.id.lightNameLabel);
lightNameLabel.setText(lightName);
I am at a loss here. I grep'ed through the project files and there are no other uses of the TextView's id other than in the snippet above. Could you please give me some pointers where to investigate why the TextView doesn't show?
[edit] I am including the .xml snippet for the respective TextView:
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:id="#+id/lightNameLabel"
android:layout_gravity="center_horizontal"
android:layout_marginTop="1dp"
android:text="Where?"
android:visibility="visible" />
[edit 2] A link to the whole layout .xml file: http://pastebin.com/2uqkzBSa
It was helpful that you showed a screenshot, as the problem is likely that you're displaying the layout in a dialog. If you select the Holo dialog theme in Android Studio's graphical editor pane, you'll observe that the default text color is white. Since you've provided a light background, the light text is simply illegible against it.
There are different solutions:
Provide a different theme when displaying the dialog as to ensure that the primary colors are dark; or
Define your own theme and provide it when displaying the dialog; or
Modify the layout to specify a text color.
I have a custom DialogPreference Dialog that has its layout set out in a relativelayout that contains the following:
Checkbox
Textview
Text Field
This is fine in Android 4.0+, because the theme we are using is Theme.Light so the background color of the dialog is white and the default text is black for the Checkbox label and textview. However, in 2.3.3, the background color is dark grey so it becomes hard to see the text... the theme is still Theme.Light however.
I thought that making a custom dialog would be necessary for this because the checkbox enable/disables the text field. At the moment, I'm making the background color of the relativelayout for this Dialog white... but I don't really like this solution as there maybe cases where some other phones on 2.3.3 may not have white as the default dialog background...
Is there a cleaner way to fix this problem?
I notice this person has the same problem: Custom Support Dialog Fragment text is the wrong color
Another with the problem :Android: Issue with showing dialog from Theme.Light activity
EDIT: Attached screenshot. This is what it looks like on LG Optimus 2X running 2.3.3. On my co-worker's samsung galaxy which runs 2.3.3 also, the background is even darker so you can hardly see the text.
You could make custom dialog theme in style files , such as:
less than API 11:
<style name="MyDialogTheme" parent="android:Theme.Light" >
API 11 and forward:
<style name="MyDialogTheme" parent="android:Theme.Holo.Dialog" >
then use "MyDialogTheme" in your Fragment dialog:
... ...
ContextThemeWrapper context = new ContextThemeWrapper(getActivity(), R.style.MyDialogTheme);
AlertDialog.Builder builder = new AlertDialog.Builder(context);
... ...
hope this help.
I am trying to add a custom style to an Android NumberPicker. What I am trying to do is have the text displayed by the picker as white since by default (or according to the default theme on the device) I have it in black. The problem is that my app background is a dark color so I want the text to be white or something clear.
so I have something like this in my style.xml file :
<style name="myPicker">
<item name="android:textColor">#FFFFFF</item>
</style>
the textcolor attribute doesn't even exist on the NumberPicker widget but I just tried to add it so that my text color changes. It does not work of course. The only thing that can be customized on this widget seems to be the background
Now the question : how can we change the text color of the picker ?
if somebody has the same issue or has solved it then please let us know.
I have found an "ugly" way to do it. Just get a reference to the child views of the number picker widget. There are three (3) child views : the upper arrow, the textview (containing the text or value to be displayed) and the lower arrow.
Let's say we have a Number picker called np
np.setValue(10);
np.setMinValue(5);
np.setMaxValue(50);
// retrieve the textview reference
TextView npTextView = (TextView) np.giftAmount.getChildAt(1); // since indexing begins at 0
npTextView.setTextColor(getResources().getColor(
R.color.my_custom_color)
I know that's bad but it works ...
I try to make a ExpandableListView where the group headers are drawn inverse. There is no problem with changing the text color, size etc. via XML. I even found out how to use the system defaults like
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
style="#android:style/TextAppearance.Medium.Inverse"
/>
But for the background color?! I don't understand why these styles don't include background color information?!
Of course I could use a direct color, but I look for good default background attributes or styles. Like "style/Background.For.TextAppearance.Medium.Inverse" ;-)
What would be a good solution? So that for the dark themed devices I get white/gray, and for the white themed I get black?
Or should I simply use R.color.background_light?
Greetings, Joerg
PS: First question here ;-) Thanx to all the people answering here the last months and years: You great people made it much more easier for me to find a re-entrance in programming after 12 years break ;-)
As you observe, the styles with "TextAppearance" in their name only affect the foreground text attributes of the view. They are appropriate for the android:textAppearance attribute. The styles with "Widget" in their names define all the UI properties and will work in a style attribute, but Android doesn't define a "Widget.TextView.Inverse" style.
When I wanted to display an console-like log as an inverse text view, I used the following XML:
<TextView
android:textAppearance="#style/TextAppearance.AppCompat.Small.Inverse"
android:background="?android:colorForeground"
... />
It uses the theme's foreground color as the background for the view. With a dark theme it displays dark text on white, and in a light theme it displays light text on black.