I have an Android astronomy app where I need to tint the UI reddish for use at night. Although I have a scheme that works well for many (most??) UI elements, I'm having trouble with the CompoundButtons: CheckBox and RadioButton.
The basic idea is to retrieve the Drawable for the UI element and if it has one to set a color filter on it. My problem is finding the appropriate Drawable for the compound buttons. I would think that getCompoundDrawables() would be what I'd need, but the returned array for the 4 drawables always contains nulls for the 4 elements.
Here is the recursive code I call on the top level view to try to colorize the UI elements.
public static void setNightVisionBkg( View view )
{
if ( view instanceof ViewGroup )
{
Drawable drawable = view.getBackground();
if ( drawable != null )
drawable.setColorFilter( 0xFFAA0000, PorterDuff.Mode.MULTIPLY );
ViewGroup group = (ViewGroup) view;
int numChildren = group.getChildCount();
for ( int i = 0; i < numChildren; i++ )
{
View v = group.getChildAt( i );
Drawable d = v.getBackground();
if ( d != null )
d.setColorFilter( 0xFFAA0000, PorterDuff.Mode.MULTIPLY );
if ( v instanceof ViewGroup )
{
setNightVisionBkg( (ViewGroup) v );
}
else if (v instanceof CompoundButton)
{
CompoundButton compBtn = (CompoundButton)v;
Drawable drawables[] = compBtn.getCompoundDrawables();
for (int j = 0; j < drawables.length; j++)
if (drawables[j] != null)
{
drawables[j].setColorFilter( 0xFFAA0000, PorterDuff.Mode.MULTIPLY );
}
}
}
}
}
Note that it is the latter part where it is getting the Drawables for the CompoundButton that fails to work (all drawables are null).
Any thoughts on how to do this? I know I could set my own custom drawables, but I'd prefer to use the standard ones and just set a colorFilter if possible.
I solved my problem in a slightly different way. Ended up subclassing CheckBox (and RadioButton). In the subclass I override:
protected boolean verifyDrawable( Drawable drawable )
and in this method I set the colorFilter on the drawable. Works great.
You don't progress "normal" non-ViewGroup Views. Furthermore your testing
for ViewGroup in a for loop which can ONLY be ran if the view is a ViewGroup.
Related
As I am developing for API level 7 and upwards setAlpha(float) is unavailable to me. As such I have implemented a method that traverses all child elements of a given ViewGroup and tries to find a way to set the alpha so that the element is almost transparent. Unfortunately I cannot come up with a way to make the ListView and its items transparent. How do I proceed?
My method:
public void enableDisableViewGroup(ViewGroup viewGroup, boolean enabled) {
int childCount = viewGroup.getChildCount();
for (int i = 0; i < childCount; i++) {
View view = viewGroup.getChildAt(i);
view.setEnabled(enabled);
if (!enabled) {
if (view instanceof TextView) {
int curColor = ((TextView) view).getCurrentTextColor();
int myColor = Color.argb(ALPHA_NUM, Color.red(curColor),
Color.green(curColor),
Color.blue(curColor));
((TextView) view).setTextColor(myColor);
} else if (view instanceof ImageView) {
((ImageView) view).setAlpha(ALPHA_NUM);
} else if (view instanceof ListView) {
// How do I set the text color of the subitems in this listview?
} else {
try {
Paint currentBackgroundPaint =
((PaintDrawable) view.getBackground()).getPaint();
int curColor = currentBackgroundPaint.getColor();
int myColor = Color.argb(ALPHA_NUM, Color.red(curColor),
Color.green(curColor), Color.blue(curColor));
view.setBackgroundColor(myColor);
} catch (NullPointerException e) {
Log.d("viewNotFound", "View " + view.getId() + " not found..");
e.getStackTrace();
}
}
if (view instanceof ViewGroup) {
enableDisableViewGroup((ViewGroup) view, enabled);
}
}
}
}
Is it an option to set this directly in the XML for your ListView row?
For example, if your layout is a LinearLayout
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#android:color/transparent">
<!-- stuff -->
</LinearLayout>
I'm not sure of your setup, but you may be able to set it programatically like this if you really want your ListView to be transparent.
ListView listView = (ListView) view;
listView.setBackgroundColor(android.R.color.transparent);
where default color android.R.color.transparent equals:
<!-- Fully transparent, equivalent to 0x00000000 -->
<color name="transparent">#00000000</color>
In this case, you'll need to set your ListView rows to be transparent in the XML anyway.
If you want to control the transparency of the Views inside your ListView rows, your best bet is to create a custom ArrayAdapter and handle this there.
I have a bunch of buttons on my MapView already transparent so I would like to make the built in zoom control at the bottom transparent also. The getZoomControl() on MapView is deprecated. Anyone have an idea of how to get a hold of the Buttons in the control without the getZoomControl?
Edit:
So I figured it out. It turns out that the ZoomButtonsController has a container that is just a ViewGroup. I can parse through that containers children to find the object that is an instanceof a ZoomControl, which is a down the line instance of a ViewGroup. I can parse through the children of the ZoomControl to get the ZoomButtons that it contains. getBackground() of the ZoomButton and setAlpha().
Here is my code:
android.widget.ZoomButtonsController zbc = mapView.getZoomButtonsController();
ViewGroup container = zbc.getContainer();
for (int i = 0; i < container.getChildCount(); i++) {
View child = container.getChildAt(i);
if (child instanceof ZoomControls) {
ViewGroup zoomC = (ViewGroup)child;
for (int j = 0; j < zoomC.getChildCount(); j++) {
View btn = zoomC.getChildAt(j);
if ( btn instanceof ZoomButton ) {
((ZoomButton)btn).getBackground().setAlpha(120);
}
}
break;
}
}
To my understanding it is deprecated in android.view.View but it resides in android.widget.ZoomButtonsController. Not sure if that helps. Let me know.
Here is some documentation.
remove the built in zoom buttons and use your own buttons and set their actions to perform zoom actions. you can make the buttons look the way you want.
Try using setBuiltInZoomControls(boolean) as suggested in the doc.
I am creating a widget with a few textviews and a few image views.
And when i want to apply a font to all the text views, i need to get one by one with the ids
and set the font or color accordingly.
But how do i get all the text view components from the layout so that
i can set the color to them all by iterating through the components ?
Try this
for( int i = 0; i < myLayout.getChildCount(); i++ ){
if( myLayout.getChildAt( i ) instanceof TextView ){
(TextView) myLayout.getChildAt( i ).setTextColor(#FF0000);
}
}
with myLayout is your ViewGroup
How can I change the transparency (alpha) of a view on pre-SDK-11 on Android?
Before you suggest using a background colour with some transparency, please note that this method does not include all elements in the view such as the text of a button or the child views of a view group.
The ViewHelper of NineOldAndroids is what I use, it is a static helper class and a real gem! Many here recommend NineOldAndroids but I have seen no mention of the ViewHelper. It is really easy to use.
import com.nineoldandroids.view.ViewHelper;
...
ViewHelper.setAlpha(myView, .2f);
You can also use it to set other properties like x, y etc, very handy when setting up for animations or building your UI. Many thanks to Jake Wharton for sharing his work with the community!
EDIT - example below refers for Android pre-SDK11, but I just found out about an amazingly great library called Nine Old Androids, The amazing thing it does is enabling all animation capabilities of Android 3.0 for all API versions!!!
Previous answer
I actually encountered this kind of problem when wanted to set alpha dynamically on a complex layout.
I created an override of onSetAlpha() and added another recursive function that checks every kind of view for background image, drawables and text colors.
#Override
public boolean onSetAlpha(int alpha)
{
return onSetAlpha(alpha, theLayoutYouWantToSetAlphaTo);
}
public boolean onSetAlpha(int alpha, View view)
{
if (view instanceof ViewGroup)
{
for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++)
{
onSetAlpha(alpha, ((ViewGroup) view).getChildAt(i));
if (((ViewGroup) view).getBackground() != null) ((ViewGroup) view).getBackground().setAlpha(alpha);
}
}
else if (view instanceof ImageView)
{
if (((ImageView) view).getDrawable() != null) ((ImageView) view).getDrawable().setAlpha(alpha);
if (((ImageView) view).getBackground() != null) ((ImageView) view).getBackground().setAlpha(alpha);
}
else if (view instanceof TextView)
{
((TextView) view).setTextColor(((TextView) view).getTextColors().withAlpha(alpha));
if (((TextView) view).getBackground() != null) ((TextView) view).getBackground().setAlpha(alpha);
}
else if (view instanceof EditText)
{
((EditText) view).setTextColor(((EditText) view).getTextColors().withAlpha(alpha));
if (((EditText) view).getBackground() != null) ((EditText) view).getBackground().setAlpha(alpha);
}
return true;
}
You can add other kinds of views as you need.
You can extend the views draw() method and use the canvas.saveAlphaLayer()
public void draw(Canvas canvas) {
canvas.saveLayerAlpha(null, alphaValue, ALL_SAVE_FLAG);
super.draw(canvas);
canvas.restore();
}
You can set Alpha to all colors of the view.(such as the text of a button or the child views of a view group). Make them into colors xml and use in all View.
You can read colors from the view recursively and add alpha to them and set them back.
You can create the view as a main view of a new Activity. Then do as in How do I create a transparent Activity on Android?
Does anyone have a quick and easy method for removing dynamically added buttons from a Linear Layout in Android? They seem to be kept in the saved instancestate and I don't want them when I return to the activity.
You may clear ALL views in a linear layout by using the following code:
LinearLayout myLayout = (LinearLayout)findViewById(R.id.your_linear_layout);
myLayout.removeAllViews();
However, if you are looking to remove only the views that were dynamically added (and you have views in there that are not) this will not work.
If you need to do it this way you can do something like this
LinearLayout l = (LinearLayout)findViewById(R.id.linearLayout);
List<View> removeViews = new ArrayList<View>();
int count = l.getChildCount();
for (int i = 0; i < count; i++) {
View v = l.getChildAt(i);
if (v != null && v.getTag() != null
&& v.getTag().toString().equals("dynamicView")) {
removeViews.add(v);
}
}
for (View v : removeViews) {
l.removeView(v);
}
Please notice the v.getTag() != null && v.getTag().toString().equals("dynamicView") portion. You don't have to do it this way, however, this would be an easy way to differentiate between a view you added and a view that was statically created.
Edit in order for this to work when you create the view you need to call view.setTag("dynamicView"); of course