I've learned how to tint an image when it's pressed by adding an OnTouchListener in which I call setColorFilter on the image.
I've learned how to use nine-patch images as the background for Buttons and ImageButtons.
The problem is, nine-path images don't stretch if they're the src for an ImageButton, and the tint has no effect on the background image.
How can I tint a nine-patch ImageButton when it's pressed? Any suggestions?
I know it's an old question but it seems that it's the only one on this topic.
You can tint nine patch images by creating an xml resource file containing a nine patch node and a tint node. Example :
<?xml version="1.0" encoding="utf-8"?>
<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
android:src="#drawable/nine_patch_image"
android:tint="#android:color/black"/>
You may then reference this file in your background attributes :
<LinearLayout
android:id="#+id/some_id"
android:background="#drawable/xml_filename">
Hope this will help someone
So I'm 3 years late but I found a way to do this.
(I'm using Xamarin so excuse any C# formatting I miss)
#Override
protected void onDraw(Canvas canvas)
{
NinePatchDrawable bg = (NinePatchDrawable)getResources().getDrawable(R.Drawable.whatev);
bg.setBounds(0, 0, getWidth(), getHeight());
bg.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY));
bg.draw(canvas);
base.onDraw(canvas);
}
Another option, is using backgroundTint (available on API21 and above):
<TextView
android:id="#+id/chat_bubble_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/left_bubble"
android:backgroundTint="#color/main_color"
android:gravity="center_vertical"
android:minWidth="200dp"
android:textColor="#android:color/white"
android:visibility="visible"
tools:text="message" />
I found one way you can kinda sorta of do this. Using a purely gray-scale, semi-transparent 9-patch image as your button background, wrap the button in a view group which has your tint color as its background like this:
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#F00"
android:orientation="vertical" >
<Button
android:id="#+id/my_butt"
android:background="#drawable/my_semi_transparent_gray_9_patch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="I'm a tinted 9-patch button!" />
</LinearLayout>
The main problem is that if your image has transparent edges, the tint color will show through where you don't want it, but if your image edges used a fully opaque color that matched the background of whatever container you put this thing in, it might work well enough. You also might need to write your own selector that changes those background colors for each state you care about. I'm not recommending this approach but maybe it will help someone. I agree that it's a shame that tinting isn't built into the 9-patch design because it feels stupid to maintain a bunch of identical images that differ only in tint, especially when you multiply that by a number of different drawable sizes. Even better would be for Android to natively support SVG. I've modified the open-source "svg-android" library so that with the right art I only need a single image that can be stretched and tinted as needed.
I think you'd have better results by making a separate asset for each button state. For instance, you can make a drawable xml file like this:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/btn_pressed"
android:state_pressed="true" />
<item android:drawable="#drawable/btn_focused"
android:state_pressed="false"
android:state_focused="true" />
<item android:drawable="#drawable/btn_default"
android:state_focused="false"
android:state_pressed="false" />
</selector>
Then create a style for your buttons like this:
<style name="PushButton">
<item name="android:background">#drawable/btn</item>
</style>
Then you should be able to style your image buttons and set the src to whatever image you want.
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/icon"
style="#style/PushButton" />
Related
I am relatively new to android styling techniques and I am trying to wrap my head around reusable components. My app has many buttons scattered throughout its' view hierarchy and they are all almost exactly the same (variable font color and button color). Is it possible to define one button drawable that can then have different styles applied to it such that, a button has one drawable definition that is applied as a background to a Button xml attribute like so <Button> android:background="#drawable/basic_btn"</Button> and then customize lets say the button color through styling, something like
<Button
style="#style/Button.Green"
android:background="#drawable/basic_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
then if I want a blue button using the same drawable I can set something like:
<Button
style="#style/Button.Blue"
android:background="#drawable/basic_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
is this possible? I currently do not get the result I want when trying this.
Edit with answer:
Looking back on my post, I don't believe I described my initial issue well enough and I appreciate everyone who has responded in between. My initial problem was attempting to apply different <styles> to a drawable to achieve different background colors, was not in fact changing the background color. My solution that I went with goes like this.
Define the drawable shape:
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#ffffff"/>
<corners android:radius="3dp" />
Next, assign the drawable as a background
<Button style="#style/Button.basic
android:background="#drawable/btn_basic"
/>
Now for the heart of the trick:
<Button style="#style/Button.basic
android:background="#drawable/btn_basic"
android:backgroundTint="#color/seafoam"
/>
backgroundTint by default seems to add the color tint on top of the drawable. This allowed me to define one shape but apply any color to it when used in an xml file. backgroundTint
Use TextView Like This:-
<TextView
android:id="#+id/reviewsTitleTxt"
style="#style/txt_style_16sp_white_color_ffffff"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAllCaps="true"
android:gravity="center"
android:text="#string/reviews_txt"
android:layout_gravity="center_vertical"/>
Where Style file is:-
Define style in style file
<style name="txt_style_16sp_white_color_ffffff">
<item name="android:textSize">#dimen/txt_size_16sp</item>
<item name="android:textColor">#color/white_color_ffffff</item>
</style>
Since we were commenting and you weren't able to solve this via the posted answer I'm going to try to help you out.
First, you should define all the common attributes on a #style/ .xml
Secondly, define a #drawable/ as your background for each button:
Background drawable:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="#dimen/button_round_radius"/>
<solid android:color="#color/background_color"/>
</shape>
The bad thing about this is you'll have to create a new drawable with somewhat the same properties just to change the color.
Also look into the already created themes/style that might help you on the reference of this answer.
Now on your button's XML declaration:
<Button
style="#style/YourCommonAttributesStyling"
android:background="#drawable/a_drawable_shape_like_the_above"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
Reference: Android Material Design Button Styles
I have this button:
<Button
android:id="#+id/btn_action"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:theme="#style/AppTheme.Button.Toolbar"/>
And this style:
<style name="AppTheme.Button.Toolbar" parent="Widget.AppCompat.Button.Borderless">
<item name="colorButtonNormal">#color/main</item>
<item name="android:textColor">#color/secondary</item>
</style>
Even though the style inherits from Widget.AppCompat.Button.Borderless, the button still has a border.
Changing Button to android.support.v7.widget.AppCompatButton did not help.
How to remove the border then?
Edit:
Setting background of the button is not an option - by doing so the animation of ripple effect is lost.
Edit 2:
Things become even more interesting.
Tried to change android:theme to style as #cadet suggested.
When button is defined this way:
<Button
android:id="#+id/btn_action"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:theme="#style/ToolbarButton"/>
That's what I get:
The colors apply, but there is distinct border.
If I just change theme to style:
<Button
android:id="#+id/btn_action"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
style="#style/ToolbarButton"/>
I get this:
There is no border, and the style is applied only partially (text is colored, button is not)
Edit 3:
Friends, I'm looking for a way to get borderless, styled button with ripple effects using styling approach. Hacking each and every button separately in layout files might work, but that's not the point.
Try this, hope out of this one may help you
<Button
android:id="#+id/btn_photo_lib"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="startPhotoLibAction"
android:src="#drawable/library_blau_2"
style="?android:attr/borderlessButtonStyle"/>
or
android:background="#null"
set background #null. or set own created background
android:background="#null"
You can use a different View instead of Button
<LinearLayout
android:id="#+id/btn_action_alternative"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:clickable="true" />
I found a better solution, you'll wanna create a custom drawable and depending on the min version your app supports, you'll need to create two, one for Android versions pre-21(Lollipop) and another for post 21(Lollipop). The two files will need to be named identically so Android can find them and match them appropriatly based on the API level. But in the file drawable file for API 21 and above your file should look like such:
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?android:colorControlHighlight">
<item android:drawable="#drawable/button_normal"/>
</ripple>
This Drawable file is wrapping another Drawable that is your preferred background image or color with a ripple whose color is defined using "?android:colorControlHighlight", which is simple a reference to a default color from what ever theme the current activity is using.
If you need to support pre-21(Lollipop), your drawable file would simply be a selector, with the preferred drawable. Your preferred drawable should be the same background color, or even a transparent color to make sure you can see your parent layouts background color. Similar to this:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/button_normal"/>
</selector>
You can combine this with a style in order to apply the borderless style to all buttons it to all buttons in a layout... I recommend you use a transparent drawable so you can use this style with all buttons regardless if their parent has a different color background. This will prevent you from making several themes with different backgrounds.
To handle versioning support, or even config support if you'd like custom drawables based on various device configurations, you would just create several drawable folders with a configuration specific suffix. So, for example, drawables only for version 21 and above you'd create a folder called 'drawable-21'.
I found a website that better explains what I'm talking about.
I am getting crazy with switch buttons in Android 4.
First of all, I have set a selector as background with two different PNG files selected from drawable folder:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/form_switch_no" android:state_checked="false"/>
<item android:drawable="#drawable/form_switch_ok" android:state_checked="true"/>
<item android:drawable="#drawable/form_switch_no"/>
</selector>
but I don't know why they are x-scaled. I want to manage this size, but I have tried to change layout_width/height/weight... without succes.
I have also a custom PNG file to be used as the thumb of the switch. I also need to manage the size of this thumb, because if I set textOn and textOff propieties as "", thumb gets a very small size. Moreover, I would like to change thumb padding in respect of the background, because It does not appears centered.
Here is my Switch XML definition:
<Switch
android:id="#+id/switchUsers"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/user"
android:textOn=""
android:textOff=""
android:thumb="#drawable/form_switch_slider"
android:track="#drawable/switch_user_selector" />
I have tried to change image sizes and making them nine-patch ones, but I can't reach my target.
Any help will be appreciated. Thank you!
The solucion for the extremely small slider with no text was solved with a combination of:
android:thumbTextPadding="25dp"
android:textOn=""
android:textOff=""
Then, the problem of the small padding in the same slider was a 9-patch image problem. I had to extend bottom and right black lines one more pixel simetrically.
Hope this helps someone with the same problem.
I have an Android application that uses a MapView with an ImageButton control (to move to the user's current location) I've added in the top right-hand corner. The problem I am having is that the ImageButton control's background is too transparent, but changing it with android:background="#BBFFFFFF" alters both the size of the background and removes the blue "flash" that you normally see when the button is pressed - two qualities I wish to retain.
I start with something like this:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.google.android.maps.MapView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/mapview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:clickable="true"
android:apiKey="my api key"
/>
<ImageButton android:id="#+id/googlemaps_select_location"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:layout_marginTop="13dp"
android:layout_marginRight="13dp"
android:src="#drawable/device_access_location_found"/>
</RelativeLayout>
Which achieves something that looks like this:
So then I add:
android:background="#BBFFFFFF"
And I get this:
Note that although this is basically the level of opacity I want, changing the background has affected the padding, and also doesn't display a blue "flash" when pressed (which obviously isn't illustrated in this question).
So my question is, how can I change just the background color/opacity in the non-pressed state, while retaining the other visual qualities of the button? I had a brief read about Android styles and themes, but can't even figure out where this button is getting its style/theme from and how I would go about just overriding the background color/opacity while retaining all of the other visual features.
Issue
When you are assigning a fixed color to the a view background, you are replacing the default background in the view by the fixed color you define.
In reality, the background of a button is not a simple fixed color. It's a state list of color or drawables, which means, depending on button status (focous, selected, pressed, etc.) a different background is used, resulting in the "flash" animation you see when button is pressed. If you replace this state list by a simple fixed color, not depending on buttons status, you get a fixed background (i.e. not changing when button is pressed).
Resolution
There is a xml parameter that can be used to change the image view's alfa (i.e. transparency) which is:
android:alpha="1"
where the value 1 above can be any float between 0 and 1, being 1 the maximum opacy.
However, I believe this is not solving your issue, because you want to change the alfa of background not the image alfa, if I correctly understood your issue. Anyway the default seems to be 1.
One possibility the should work for you is to define a selector to be used as background. The selector will choose the drawable based on his status.
Example
<?xml version="1.0" encoding="UTF-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="#android:color/darker_gray" />
<item android:drawable="#android:color/white" />
</selector>
Save the xml file above in your drawable-xxxx folder with the name my_selector
In this example I'm using standard android colors, but you can define your own colors. You need to assigne a color for each different button status that you want to have a different color.
Then you need to define your ImageView backgroung to be the selector you defined above:
<ImageButton
android:id="#+id/googlemaps_select_location"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginRight="13dp"
android:layout_marginTop="13dp"
android:background="#drawable/my_selector"
android:src="#drawable/device_access_location_found" />
With the above changes, the bacground color used by the button will change when the button is pressed and you can have the "flash" effect.
I ended up using a style to inherit the look of Widget.ImageButton with just a few minor tweaks for my purposes:
My /res/values/styles.xml file now looks like:
<resources>
<style name="AppTheme" parent="android:Theme.Light" />
<style name="my_loc_btn_style" parent="#android:style/Widget.ImageButton">
<item name="android:layout_marginTop">8dp</item>
<item name="android:layout_marginRight">8dp</item>
</style>
</resources>
And my layout file has:
<ImageButton android:id="#+id/googlemaps_select_location"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
style="#style/my_loc_btn_style"
android:src="#drawable/device_access_location_found"/>
This seems to have inherited a background from Widget.ImageButton that seems to be just slightly transparent, which is what I was after anyway, so I don't set the transparency at all now.
I want to set opacity to my ImageButton, so when it is unselected, I can see the background a bit, and when I press on it - it becomes normal(no transparency).
If the background you are using is itself an image, then you can't simply "set" the transparency, it's coming from the png image that is the resource for the background. I'd recommend creating 3 9-patch png images for the different stages of the button using transparency as necessary for whichever stage you like. There's a description of how to use a different graphic and xml config file for your own background images in the docs on ImageButton
http://developer.android.com/reference/android/widget/ImageButton.html
If you used a solid color for the background, transparency can be achieved using a color code that has AARRGGBB as elements.
android:background="#55FF0000" would be a partially transparent red background.
Use Selector (http://developer.android.com/reference/android/content/res/ColorStateList.html)
The layout code would look sth like that :
android:background="#drawable/my_selector"
and the selector code would be my_selector.xml with following content :
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:state_pressed="true" android:drawable="#drawable/button_without_opactity" />
<item android:state_selected="true" android:drawable="#drawable/button_without_opactity" />
<item android:drawable="#drawable/button_with_opacity" />
</selector>
button_without_opacity & button_with_opacity should be 9-patches