Change a button to round programmatically - android

Having a round button in xml, I want to change its color when clicking on it. I do it with this code, but it changes to square shape again, not to the original round shape:
button1.setBackgroundColor(Color.BLUE);
Does anyone know how I can change the button's shape as well?

GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius( 8 );
// add some color
// You can add your random color generator here
// and set color
if (i % 2 == 0) {
shape.setColor(Color.RED);
} else {
shape.setColor(Color.BLUE);
}
// now find your view and add background to it
findViewById( R.id.my_view ).setBackground(shape);

Related

How to change color of a sprite randomly

I wrote the following code:
int color = Color.argb8888(255, rand.nextInt(256), rand.nextInt(256), rand.nextInt(256));
stage.getBatch().setColor(color);
With this code I want to change the color of a sprite randomly. Unfortunately, the color of all sprites on the stage get changed but I want to declare which sprite I want to tint. How can I improve my code?
To change tint of a single sprite, use below code
Sprite mysprite;
Texture mytexture;
mytexture = new Texture("texture.png");
mysprite = new Sprite(mytexture);
mysprite.setColor(Color.WHITE.cpy().lerp(Color.BLACK, .5f));
this code changes white tint of sprite to black tint
Color color = new Color(rand.nextFloat(), rand.nextFloat(), rand.nextFloat(), 1f);
'rand.nextFloat()' is gives you a float between 0 and 1, so you can create random color like this.
I prefer to use in this way :
final Image image=new Image(new Texture("badlogic.jpg"));
final Color colors[]=new Color[]{Color.YELLOW,Color.RED,Color.CYAN};
image.addAction(Actions.forever(Actions.sequence(Actions.delay(.2f),Actions.run(new Runnable() {
#Override
public void run() {
image.setColor(colors[MathUtils.random(colors.length-1)]);
}
}))));
stage.addActor(image);
In my experience, you could just set your color attribute that used as vertex attributes in shader back to normal color masking like this:
stage.getBatch().setColor(your_random_color);
stage.getBatch().draw(your_texture);
stage.getBatch().setColor(1.0f,1.0f,1.0f,1.0f);
Please be noticed that I tried this way for drawing TextureRegion, but I think this would not be different with drawing Sprite.

how to layer two buttons with graphics/color that are set programmatically

I have to layer two Buttons. The first (top) button is created like this using a .png for the icon.
// create circular button and colorize
View button1 = v.findViewById(bId);
GradientDrawable backgroundGradient = (GradientDrawable)imgIcon.getBackground();
backgroundGradient.setColor(getResources().getColor(R.color.holo_gray_light));
// set icon
button1.setImageDrawable(getResources().getDrawable(R.drawable.ic_phone_ib));
For the 2nd button (bottom):
Button button2 = (Button) v.findViewById(R.id.textButton);
button2.setBackgroundResource(R.drawable.gray_rect);
what I have tried:
1 set the drawable left on the bottom button to the drawable of top button. result: icon only is displayed not the background colored circle.
2 create a RoundRectangle using ShapeDrawable then create 2 layers and use LayerDrawable to set the background of the button:
int r= 20;
float[] outerR=new float[]{r,r,r,r,r,r,r,r};
RoundRectShape rr=new RoundRectShape(outerR,null,null);
ShapeDrawable drawable=new ShapeDrawable(rr);
drawable.getPaint().setColor(getResources().getColor(R.color.gray_189));
// get bitmap from button1
BitmapDrawable bm1 = (BitmapDrawable)button1.getDrawable();
// layer them
Drawable drawableArray[]= new Drawable[]{drawable, bm1};
LayerDrawable layerDraw = new LayerDrawable(drawableArray);
layerDraw.setLayerInset(1, 15, 15, 0, 0);//set offset of 2 layer
textButton.setBackground(layerDraw);
result: same as for (1).
Here is the desired result:
button1 is blue with icon, button2 is gray rounded rectangle with text.
figured it out using RelativeLayout in the xml for the list item. I used 2 table rows, one for each button and oriented them such that the button layers accordingly and I was able to set the icon and background color programmatically.

Changing property when clicked - Android

I have 15 ImageView where I assign a 'shape' as background. What I want to achieved is when I click these ImageViews, the shape's stoke property will change from 0dp to 4dp. But when I clicked the ImageView again, it will turn back to 0dp. I also want to limit the number of ImageView that can be clicked. For example, If I have clicked 8 ImageView already (that changes their stroke property from 0dp to 4dp), it won't allow me to change others ImageView stroke property anymore, unless I clicked one ImageView (that will removed it's 2dp stroke and will reset it to 0dp).
This is the code I have so far. Which allows me to click the ImageViews and change their stroke property to 4dp. I am googling/stackoverflow for solutions but can't find one. Hope you can help me.
private int[] colors = {R.color.filter_dark_blue, R.color.filter_rouge, R.color.filter_blue, R.color.filter_burgundy,
R.color.filter_turquoise, R.color.filter_navy, R.color.filter_green, R.color.filter_black,
R.color.filter_yellow, R.color.filter_charcoal, R.color.filter_orange, R.color.filter_grey,
R.color.filter_warm_red, R.color.filter_white, R.color.filter_pink};
private ImageView[] color = new ImageView[colors.length];
for (int i = 0 ; i < color.length ; i++) {
color[i] = (ImageView) findViewById(ivCirclesId[i]);
final GradientDrawable ivCircleOnClick = (GradientDrawable) color[i].getBackground();
color[i].setOnClickListener(new OnClickListener() {
public void onClick(View v) {
ivCircleOnClick.setStroke(4, Color.WHITE);
}
});
}
here is snippet,
some quick ideas ...
1- use the setTag(Object) and getTag() to set 0/1 value, as clicked flag
color[i] = (ImageView) findViewById(ivCirclesId[i]);
final GradientDrawable ivCircleOnClick = (GradientDrawable) color[i].getBackground();
//add this
color[i].setTag("0");//not clicked when created.
2- use global variable as counter for total clicked images, to control the limit 8 issue, if its set to 4 then increment the counter ++counter, if reset to 0, decrement the counter --counter, and change setTag()
public void onClick(View v) {
if(v.getTag().toString().equals("1")){
--clicked;
v.setTag("0");
ivCircleOnClick.setStroke(0, Color.WHITE);
}else{
if(clicked >= 8){
//max limit reached, nothing to do... add toast if you want ...
return;
}
++clicked;
v.setTag("1");
ivCircleOnClick.setStroke(4, Color.WHITE);
}
}

Ninepatch Drawable with ColorFilter

I'm create some calendar view and what I want to do is to create a background for a LineairLayout that is clickabe.
Therefore I create a StateListDrawable with two images:
The image for the background
The image when the item has been pressed
So far that works with this piece of code:
NinePatchDrawable background = (NinePatchDrawable) context.getResources().getDrawable(R.drawable.calendar_item);
Drawable backgroundFocus = context.getResources().getDrawable(R.drawable.calendar_focus);
int stateFocused = android.R.attr.state_focused;
int statePressed = android.R.attr.state_pressed;
StateListDrawable sld = new StateListDrawable();
sld.addState(new int[]{ stateFocused, statePressed}, backgroundFocus);
sld.addState(new int[]{-stateFocused, statePressed}, backgroundFocus);
sld.addState(new int[]{-stateFocused}, background);
return sld;
But I would like to do something extra. I'dd like the user to be able to pass in a color that he wants to use to display the background. So the background var must be variable, but it must be based on the nine-patch drawable.
So I thought I could just do something like this:
background.setColorFilter(Color.RED, PorterDuff.Mode.DST_IN);
Where Color.RED must be replaced by the color of choice of the user.
But that doesn't seem to be working. The nine-patch is created perfectly but without the color fiilter being applied.
I also tried other PoterDuff.Mode 's:
SRC
SRC_ATOP
DST_IN
...
If you have any clue what I'm doing wrong or what I could do else to solve my issue please let me know! :-)
Kr,
Dirk
I don't think you can assign ColorFilters for each Drawable in a StateListDrawable. Reason: The ColorFilter will be removed/replaced when the StateListDrawable changes state. To see this in action, change the order of the statements such that:
background.setColorFilter(Color.RED, PorterDuff.Mode.DST_IN);
comes after the creation of the StateListDrawable. You'll see that the ColorFilter IS applied. But, as soon as the state changes(click, then release), the ColorFilter isn't there any more.
StateListDrawables allow you to set a ColorFilter: StateListDrawable#setColorFilter(ColorFilter). This is how the supplied (or null) ColorFilter is used:
StateListDrawable#onStateChange(int[]):
#Override
protected boolean onStateChange(int[] stateSet) {
....
if (selectDrawable(idx)) { // DrawableContainer#selectDrawable(int)
return true;
}
....
}
DrawableContainer#selectDrawable(int):
public boolean selectDrawable(int idx) {
....
if (idx >= 0 && idx < mDrawableContainerState.mNumChildren) {
Drawable d = mDrawableContainerState.mDrawables[idx];
mCurrDrawable = d;
mCurIndex = idx;
if (d != null) {
....
// So, at this stage, any ColorFilter you might have supplied
// to `d` will be replaced by the ColorFilter you
// supplied to the StateListDrawable, or `null`
// if you didn't supply any.
d.setColorFilter(mColorFilter);
....
}
} else {
....
}
}
Workaround:
If at all a possible, use an ImageView (match_parent for dimensions) for visual communication. Set the StateListDrawable that you've created as the ImageView's background. Create another StateListDrawable for the overlay:
StateListDrawable sldOverlay = new StateListDrawable();
// Match Colors with states (and ultimately, Drawables)
sldOverlay.addState(new int[] { statePressed },
new ColorDrawable(Color.TRANSPARENT));
sldOverlay.addState(new int[] { -statePressed },
new ColorDrawable(Color.parseColor("#50000000")));
// Drawable that you already have
iv1.setBackground(sld);
// Drawable that you just created
iv1.setImageDrawable(sldOverlay);
Another possibility: use a FrameLayout in place of LinearLayout. LinearLayouts do not have a foreground property.
// StateListDrawable
frameLayout.setBackground(sld);
// For tint
frameLayout.setForeground(sldOverlay);
It does involve overdraw, making it a sub-optimal solution/workaround. Perhaps you can look at extending StateListDrawable and DrawableContainer. And since you are not using a ColorFilter for the StateListDrawable, you can remove d.setColorFilter(mColorFilter); from overridden DrawableContainer#selectDrawable(int).

Honeycomb background drawing issues

I'm seeing drawing issues on Honeycomb that I can't figure out. For some reason when I add buttons to a view in code the background of the view disapears (becomes black).
This works fine on my Galaxy tab running 2.3. It fails in the emulator or on my Motorolla Xoom running 3.2.
Details:
In onCreate() I'm setting either a background color or a background image on the relativeLayout defined in main.xml. My relativeLayout is defined as fill_parent.
I have an OnTouchListener for my activity, in which I add two green buttons (one left aligned, one right aligned), to the relativeLayout.
When I add those two buttons the background of the relativeLayout disappears (shows all black). I can't explain why.
Clues:
If I set the color of one of the green buttons to instead be Color.TRANSPARENT, everything works and my background doesn't disappear. This seems like a big clue, but I can't figure out what it means.
When using color background, if I set the targetSdkVersion to "11" instead of "7" (I'm targetting 2.1/7) it works and my color background doesn't disappear. But images are still broken.
When using color background, I can call setDrawingCacheBackgroundColor( Color.RED ) which results in a red background instead of black. I could use this as a solution, setting the cache color to my background color, but this doesn't work when using images.
This really feels like a bug in android because I can't see that I'm doing anything wrong in my code. I'd appreciate any help or advice.
Here's my simple main.xml layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/MyLayout">
</RelativeLayout>
Here's my activity code:
public class ViewTesterActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate( savedInstanceState );
// set the relative layout as our view
setContentView( R.layout.main );
// get the relative layout
android.widget.RelativeLayout layout = (android.widget.RelativeLayout) findViewById( R.id.MyLayout );
// set an on touch listener
layout.setOnTouchListener( (android.view.View.OnTouchListener) mOnTouchListener );
// set a background image
// PROBLEM: this background image disappears when adding the buttons in our touch handler
// GOOFY FIX: If I change the color of one of the buttons we add to be Color.TRANSPARENT, this
// background image doesn't disappear.
layout.setBackgroundResource( R.drawable.icon );
layout.setDrawingCacheEnabled( false );
// alternatively, set background color
// PROBLEM: the color disappears (becomes black) when adding the button in our touch handler
// GOOFY FIX: If I change the color of one of the buttons we add to be Color.TRANSPARENT, the color
// doesn't disappear
// GOOFY FIX 2: If I set android:targetSdkVersion to "11" in our manifest, the color doesn't disappear
// CLUE?: Without any fixes above and using color as the background, if I set the drawing cache color
// to Color.RED it'll show up instead of black. This would be a great solution to my problem but it
// doesn't work for background images.
// layout.setDrawingCacheBackgroundColor( Color.RED );
// layout.setDrawingCacheEnabled( true );
}
// on touch listener, add two buttons to the view
private android.view.View.OnTouchListener mOnTouchListener = new android.view.View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
if ( v != null )
v.onTouchEvent( event );
if ( event.getAction() == MotionEvent.ACTION_UP ) {
android.widget.RelativeLayout layout = (android.widget.RelativeLayout) findViewById( R.id.MyLayout );
// add a green button, left aligned
Button btn = new Button( ViewTesterActivity.this );
btn.setBackgroundColor( Color.GREEN );
// GOOFY FIX: setting this instead of green solves the issue, no disappearing background
// btn.setBackgroundColor( Color.TRANSPARENT );
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams( 100, 100 );
params.addRule( RelativeLayout.ALIGN_PARENT_LEFT );
layout.addView( btn, params );
// add a green button, right aligned
btn = new Button( ViewTesterActivity.this );
btn.setBackgroundColor( Color.GREEN );
params = new RelativeLayout.LayoutParams( 100, 100 );
params.addRule( RelativeLayout.ALIGN_PARENT_RIGHT );
layout.addView( btn, params );
}
return true;
}
};
}
I faced a somehow similar problem, and I got it working by using handlers. You need to send a message to a handler implemented in your activity and invalidate your view. There is no need for setDrawingCacheEnabled( false ). Here is what I did for my problem:
protected static final int REFRESH = 0;
private Handler _hRedraw;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
_hRedraw=new Handler(){
#Override
public void handleMessage(Message msg)
{
switch (msg.what) {
case REFRESH:
redrawEverything();
break;
}
}
};
}
private void redrawEverything()
{
android.widget.RelativeLayout layout = (android.widget.RelativeLayout) findViewById( R.id.MyLayout );
layout.invalidate();
layout.refreshDrawableState();
}
Now in your OnTouchListener just send a message to your handler using:
_hRedraw.sendEmptyMessage(REFRESH);

Categories

Resources