Issue
This question was initially posted on Google Moderator for the AndroidDev Office Hours Hangout that took place last week. The question was actually answered live and you can watch it here if you like. I'm posting it here cause they seemed intrigued by it and here I have a little bit more room to elaborate.
A WebView
is normally used to display web content as the author intended (as they state in the hangout). But I use a WebView
to display, not exactly content per se, but formatted text (mainly, bolds, italics, bulleted lists and text alignment). It's much easier with a WebView
(in other words, much easier with HTML/CSS) than to use a bunch of TextViews and keep it all perfectly formatted.
The problem is that I'm using this specific WebView
with a transparent background on an AlertDialog
. The WebView
text color comes from the loaded content CSS but it's important that this color contrasts with the background color of the AlertDialog
. And that's my problem.
Up until Android 2.3, the AlertDialog
background was always dark. It didn't matter if the app theme was the default dark one or the light one, the AlertDialog
was still a dark gray. This on vanilla Android. But even on skinned Android (Sense, TouchWiz, MotoBlur, etc...) the AlertDialog
has always been a dark color (for both the default/dark and light themes).
This all changed with ICS (it probably changed on Honeycomb but I didn't confirm that). The default/dark theme now has a dark AlertDialog
while the light theme actually has a light AlertDialog
.
Since I'm exclusively using the light theme on my app, I could easily solve my problem by loading the WebView
content with different CSS files. One with a dark text color for versions below ICS and anothr light text color for ICS and above. This would mostly solve my issue if it weren't for OEMs skins.
On their skin versions for ICS, they might provide dark/light themes for the AlertDialog
. Or not. They are more likely to do exactly has they been doing it, provide dark and light themes as usual but for the AlertDialog
only a dark version, no matter the app's theme.
I could force Holo
on my app and have the problem solved that way but I would prefer not to interfere with how the overall system looks on the user's devices. For instance, if they have Sense and really like it, I don't want to display a Holo
themed AlertDialog
when using my app.
Ultimately, my question is this:
So, how do I cope with this? How do I make sure the text on my WebView
is readable against the AlertDialog
background? No matter the Android version, the theme being used or if it's skinned by OEMs or not...
I don't know how feasible is this but one alternative to solve this problem would be to, somehow, extract the text color from the AlertDialog
theme in the device. But not the default theme or the Holo
theme, but the DeviceDefault
theme I believe.
Is this extraction easily done? Could it be a good solution to my problem? Do you have any other alternatives?
One last detail... If you watched the hangout and for the guys that actually answered me, one of them suggested injecting CSS. If I wasn't clear before, I don't need to do that. I just need to build the WebView
content String with the exact CSS I want, which can take the text color extracted from the theme.
Solution
I think in order to find a solution we must be able to determine what theme is used at runtime by your dialogs. I assume that you do not set a theme explicity. That means that the default dialog theme will be used. The following code is from the Dialog class and it shows how the default theme is in fact applied to a dialog if a theme was not explicitely set.
Dialog(Context context, int theme, boolean createContextWrapper) {
if (theme == 0) {
TypedValue outValue = new TypedValue();
context.getTheme().resolveAttribute(com.android.internal.R.attr.dialogTheme,
outValue, true);
theme = outValue.resourceId;
}
mContext = createContextWrapper ? new ContextThemeWrapper(context, theme) : context;
mWindowManager = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
Window w = PolicyManager.makeNewWindow(mContext);
mWindow = w;
w.setCallback(this);
w.setWindowManager(mWindowManager, null, null);
w.setGravity(Gravity.CENTER);
mUiThread = Thread.currentThread();
mListenersHandler = new ListenersHandler(this);
}
Now we need to find out what the primary text color of that theme is. We can do it like this( the variable dialog is a reference to your dialog):
TypedValue tv = new TypedValue();
dialog.getContext().getTheme().resolveAttribute(android.R.attr.textColorPrimary, tv, true);
int textColor = getResources().getColor(tv.resourceId);
Now that we have the text color it is a matter of injecting that value into your webview. I tested this code with the following devices
Samsung Galaxy Tab 10.1 running Honeycomb
- Theme.Holo.Light gave the text color pure black
- Theme.Holo gave the text color pure white
HTC Sensation running Gingerbread
- Theme.Light gave a text color of pure white (which is correct since the dialog has a dark background
- Theme.Black also gave a text color of pure white
Samsung Galaxy S2 running Gingerbread
- Theme.Black gave a textcolor of light gray (ffc8c8c8)
- Theme.Light gave the same textcolor (ffc8c8c8)
ICS Emulator
- Theme.Holo.Light gave a text color of pure black
- Theme.Holo gave a very light gray (fff3f3f3)
So this method worked fine across all tested devices.
Cheers Renard
Answered By - Renard
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.