Change color of button programmatically - android

First of, I have read the multiple topics about this subject here on SO. Methods like PorterDuff colorfilter and changing setBackgroundResource. They all work but with strange hiccups that happen at complete random.
I have a button with following style (unpressed state = white, pressed = gray):
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<layer-list>
<item>
<shape>
<solid android:color="#ffafafaf" />
<corners android:radius="30dip"/>
</shape>
</item>
</layer-list>
</item>
<item>
<layer-list>
<!-- SHADOW LAYER -->
<item>
<shape>
<solid android:color="#66000000" />
<corners android:radius="30dp"/>
</shape>
</item>
<!-- CONTENT LAYER -->
<item android:left="1dp" android:top="1dp" android:bottom="2dp" android:right="2dp">
<shape>
<solid android:color="#ffffff" />
<corners android:radius="30dp"/>
</shape>
</item>
</layer-list>
</item>
</selector
>
So to make this button green instead of white when clicked I have tried two different approaches. First one
button.getBackground().setColorFilter(Color.GREEN, PorterDuff.Mode.SRC_ATOP);
Than to make it go back to normal (white) I do:
Drawable d = button.getBackground();
button.invalidateDrawable(d);
d.clearColorFilter();
This make the button go back to normal (white), but when I press it isn't gray (as it was before setColorFilter) but green. Somehow the colorfilter got transferred to the buttons pressed state.
Second approach. I created an additional drawable button style identical to my normal one except for item color being green (instead of white)
So with this approach I can change the button color like this:
b6.setBackgroundResource(R.drawable.green_button);
And I change it back to normal:
b6.setBackgroundResource(R.drawable.normal_button);
This works as expected except for a strange behavior that happens 1/10 when I try to reset the button back to normal. The button becomes gray and it seems like it didn't read the setBackgroundResource. This happens all random and nothing in the logcat revile anything.
Please somebody help me figure out what is causing this or proposing your method for doing this. I would rather not use an imagebutton with a textfield overlapping the button with relative layout, than change color by changing imagebutton rsc. But please there has to be another way?

Invalidate your button to force a refresh.
b6.invalidate();
That way your button should be redrawn every time.

Related

Change shape of Button while mantaining its material design ripple effect

I want to create Button with custom shape , which would react on press like in theme "Base.Widget.AppCompat.Button.Colored".
However bacause of I have to customize its shape (rounded corners I have to override its android:background - this is so far the only way I know (no... no I will not use dirty hacks with FrameLayout).
Currently it can be done only by providing our custom <shape> in xml file as background drawable.
The most promising code, which enable selectableItemBackground - so imporant for me, is:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape>
<solid android:color="#color/colorAccent"/>
<corners android:topLeftRadius="#dimen/button_shape_radius"
android:topRightRadius="#dimen/button_shape_radius"/>
</shape>
</item>
<item android:drawable="?attr/selectableItemBackground">
<shape>
<solid/>
<corners android:topLeftRadius="#dimen/button_shape_radius"
android:topRightRadius="#dimen/button_shape_radius"/>
</shape>
</item>
</layer-list>
Unfortunatelly I cannot shape second item with <item android:drawable="?attr/selectableItemBackground"> therefore in the end pressed item's shape is rectangle.
I would appreaciate if someone will give me soulution for this problem.
I use API_MIN = 16, so cannot use ripple effect. I also dont want to use FrameLayout or tther external Library that forces me to wrapp Button with something.
To have a ripple below 21 you can use this library Ripple Effect you use your shape without the ripple tag and surround the view with RippleView for more details you can check the Usage section
21+ you can try this i didn't test it but it should work, put this in the folder drawable-v21
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?attr/colorControlHighlight">
<item>
<shape>
<solid android:color="#color/colorAccent"/>
<corners android:topLeftRadius="#dimen/button_shape_radius"
android:topRightRadius="#dimen/button_shape_radius"/>
</shape>
</item>
<item android:drawable="?attr/selectableItemBackground">
<shape>
<solid/>
<corners android:topLeftRadius="#dimen/button_shape_radius"
android:topRightRadius="#dimen/button_shape_radius"/>
</shape>
</item>
</ripple>
UPDATE
I changed the source code of Ripple Effect to a button
You can get the code here
USAGE
Just like any ordinary button XML
<path.to.the.RippleButton
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/button_rounded_top_blue"
android:id="#+id/mybutton"/>
Java
RippleButton button = (RippleButton) findViewById(R.id.mybutton);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(MainScreen.this, "You did it", Toast.LENGTH_SHORT).show();
}
});
If you need other view you just need to make some tweaks to the source code it's easy (in my opinion)

Material Design suggestions for edit button for each item

I wanted to add an edit button to each button in a list of items. Android action buttons should only be used once per view so those don't make sense. Is there any other way of doing it by following material guidelines? This button should be something that flies off and flies on depending on whether the overall edit button is pressed or not.
You should use flat buttons because buttons pop from backgrounds, easily grab attention, and guide the user’s eye. Here is a nice post about this
UPDATED:
To design a flat button effect you have to do the following
define your button and set background to a drawable which contains definitions for status pressed and status default
for status pressed write a drawable resource with solid color
for status default write a drawable with a item pointing to status pressed drawable as a background. And draw a lighter shape as another item with a android:bottom="2dp"
flat_button.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="#drawable/rect_pressed"/>
<item android:drawable="#drawable/rect_normal"/>
</selector>
rect_normal.xml
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/rect_pressed" />
<item android:bottom="#dimen/layer_padding">
<shape android:shape="rectangle">
<corners android:radius="#dimen/corner_radius" />
<solid android:color="#color/blue_normal" />
</shape>
</item>
</layer-list>
rect_pressed.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="#dimen/corner_radius" />
<solid android:color="#color/blue_pressed" />
</shape>
if you need to read the full tutorial go here.
You should probably use flat or raised button (depending on how important your edit function is).

android button customized color and round corner

I am making a drawing app where the users can choose a custom color. After choosing the color, the customBtn would change its color to the chosen color by the following code:
customBtn.setBackgroundColor(Color.argb(alphaSeekBar.getProgress(), redSeekBar.getProgress(),
greenSeekBar.getProgress(), blueSeekBar.getProgress()));
However, this makes the button to be squared-corner.
I would like it to be round-corner and when pressed, it become grey in color.
There is selector.xml already exist and shown as follows, but how could I incorporate all the things together such that
it will show custom color when not pressed, round-cornered, and
when pressed it become grey (and maintain round-cornered)?
Selector:
<item android:state_pressed="true" >
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<stroke android:width="2dp" android:color="#color/black" />
<solid android:color="#color/grey"/>
<padding android:left="5dp" android:top="2dp"
android:right="5dp" android:bottom="2dp" />
<corners android:radius="5dp" />
</shape>
</item>
<item>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<stroke android:width="2dp" android:color="#color/black" />
<solid android:color="#color/???-- how to amend---??"/>
<padding android:left="5dp" android:top="2dp"
android:right="5dp" android:bottom="2dp" />
<corners android:radius="5dp" />
</shape>
</item>
EDIT: to set round-corner programmatically, as customerized color is not static, user can change the customerized color upon request
customColorCode = Color.argb(alphaSeekBar.getProgress(), redSeekBar.getProgress(),
greenSeekBar.getProgress(), blueSeekBar.getProgress());
RoundRectShape rs = new RoundRectShape(new float[] { 10, 10, 10, 10, 10, 10, 10, 10}, null, null);
ShapeDrawable sd = new ShapeDrawable(rs);
customBtn.setBackgroundDrawable(sd);
customBtn.setBackgroundColor(customColorCode);
Programmatically problem:
The button before choosing customerized color is showing round corner perfectly, set after choosing the customerized color it is then back to squared-color, possibly it is because the setBackgroundColor line is put at the last code. Yet i have tried move it up and yet still being squared color. How can this be modified?
Thanks!
Since you aren't supporting the full range states like a normal button (focused, disabled, pressed, active, etc, etc), and the only difference between your default state and your pressed state is a solid color. Maybe a [PorterColorFilter][1] would work. I think you can set the pressed state as is, and have the default state simply be white. Then you apply the color filter to the button with the set custom color. You might need to try a few filter modes, but I think DST_ATOP will replace the white, but not the black border. And you will probably want to use a gesture detector to remove the color filter when a down MotionEvent is triggered on the button (also known as your pressed state being triggered).
The short answer is that Android Buttons don't work well for what you want to do. They tend to require static drawables that define their appearance in the different states they can be in.
One option is to restrict the color choices and create a drawable for each color, and set the drawable based on the user's choice. I don't know what context your button occurs in, but it's recommended to follow the touch feedback example for a normal button to provide consistency for the user.
Note: setBackgroundColor is misleading, it's just setting the Button drawable to a color drawable, which is replacing your rounded rectangle drawable. That's why it's becoming a rectangle when you do that.

android - seekbar progress does not get painted all the way

does anybody know why I am getting this (see photo)?
Here is how I set it:
this._seekBar.setProgressDrawable(_context.getResources().getDrawable(R.drawable.common_controls_player_progressbar_bg_expanded));
this._seekBar.setThumb(_context.getResources().getDrawable(R.drawable.ringtone_scrub));
this._seekBar.setThumbOffset(0);
this._seekBar.setMax(1000);
this._seekBar.setMinimumHeight(6);
Seekbar itself:
<SeekBar android:id="#+id/seekbar_ctrl" android:layout_width="wrap_content" android:layout_height="wrap_content" android:maxHeight="6dp"/>
Expanded view xml
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#android:id/background">
<shape>
<solid android:color="#color/player_progressbar_gray"/>
</shape>
</item>
<item android:id="#android:id/secondaryProgress">
<clip>
<shape>
<solid android:color="#color/player_progressbar_gray"/>
</shape>
</clip>
</item>
<item android:id="#android:id/progress">
<clip>
<shape>
<solid android:color="#color/player_progressbar_green"/>
</shape>
</clip>
</item>
</layer-list>
It does happen in both expanded and collapsed view. What am I missing?
Thank you in advance
this was due to the launch of two controls that I was toggling. 1. expanded mode 2. collapsed. State of the progress was lost between toggles since I was only setting one control at a time. So what I did to fix this was: I placed 2 progress bar controls on the control holder and was setting them both at the same time. One remained hidden the other one was shown. During toggle event I switched the visability. That solved the issue. The second issue we had with same control was the progress on tap would flicker back and forth before being set. It turned out to be the issue with the OS of the phone and related to the player itself. We got a new OS build release and that fixed the issue.

How to make two parallel and adjacent lines in Android xml?

I'm trying to make a custom list divider. It has one horizontal line that's a subtle gradient, and a second horizontal white line immediately below it as a sort of "drop shadow".
I'm trying to use <layer-list> to accomplish what I want, but it's not working out the way I expect.
Here's the code:
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape>
<gradient
android:startColor="#ccd0d3"
android:centerColor="#b6babd"
android:endColor="#ccd0d3"
android:height="1px"
android:angle="0" />
</shape>
</item>
<item android:top="2px">
<shape
android:color="#android:color/white"
android:height="1px" />
</item>
</layer-list>
If I use android:divider to assign this to a ListView and set the android:dividerHeight="2", I get a grey gradient that's two pixels high. The white line is nowhere to be seen.
If I set the white line's android:top="1px", I see a one pixel grey gradient and a one pixel black line below it.
Any ideas what I'm doing wrong?
You should set dividerHeight to 3 or avoid setting it altogether.

Categories

Resources