I have a dashboard with icons and text like in the picture below.
What I want is a round-cornered filled background behind the 'My status' text. I drew on the picture what I want, but it needs to be filled, not only bordered like here (it's just for clarity that I drew it like that on the picture).
Right now this button is made through a style:
<style name="DashboardButton">
<item name="android:layout_gravity">center_vertical</item>
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:gravity">center_horizontal</item>
<item name="android:drawablePadding">2dp</item>
<item name="android:textSize">14dp</item>
<item name="android:textColor">#877871</item>
<item name="android:background">#null</item>
</style>
How can I adapt this style to acheive it?
Can I also set the hover and active states via a style?
For the background to the button's text you either try to do this with a custom background graphic, but I think it would be easier to split your "button" into two parts and render the icon part as an ImageButton and for the label part as a normal button with a custom ShapeDrawable for the background, e.g. like so:
<shape>
<solid android:color="#0000FF" />
<stroke
android:width="2dp"
android:color="#FFFFFF" />
<corners
android:radius="8dp" />
<padding
android:left="8dp"
android:top="8dp"
android:right="8dp"
android:bottom="8dp" />
</shape>
For setting hover and active states you can use Android's StateListDrawable.
Related
I created custom button based on a MaterialButton that is semi-transparent (primaryColorDisabled) when pressed and disabled. Now, I would like to have its ripple effect to turn the button from its primaryColor to the primaryColorDisabled instead of the MaterialButton's default highlighted color.
My colors only differ only in alpha and are defined:
<color name="primaryColor">#283593</color>
<color name="primaryColorDisabled">#A0283593</color>
To my custom button I apply the following style:
<style name="CustomButton" parent="Widget.MaterialComponents.Button">
<item name="android:background">#drawable/custom_background</item>
</style>
Below are the recursive definitions of my drawables. I removed not pertinent bits like namespace, padding, margins, etc.
#drawable/custom_background:
<selector>
<item android:state_enabled="false"
android:drawable="#drawable/custom_disabled" />
<item android:state_pressed="true"
android:drawable="#drawable/custom_disabled" />
<item android:drawable="#drawable/custom_ripple" />
</selector>
#drawable/custom_disabled:
<inset>
<shape
android:shape="rectangle"
android:tint="#color/primaryColorDisabled" >
<solid android:color="#color/primaryColor" />
</shape>
</inset>
#drawable/custom_ripple:
<ripple android:color="?attr/colorControlHighlight">
<item android:drawable="#drawable/custom_enabled" />
</ripple>
#drawable/custom_enabled:
<inset>
<shape
android:shape="rectangle" >
<solid android:color="#color/primaryColor" />
</shape>
</inset>
Now, I tried changing in #drawable/custom_ripple the color from ?attr/colorControlHighlight to my #color/primaryColorDisabled, but then when I click on my button nothing changes: no ripple and no even 'state_pressed' look. Any ideas how to achieve that?
Here is the link to what I have in mind.
https://dribbble.com/shots/1407665-Categories/attachments/204971
Is there a popular library anyone knows that can manage this, otherwise I am alright with going the customizing route.
I have my 9 buttons defined in my XML no problem.
Next I know I have to create a xml file in the drawable folder like "button_shape.xml". Then I add this to my code:
android:background="#drawable/button_shape"
I make my button have an image, I assume with:
android:drawableTop="#drawable/buttonImage"
I guess lastly is how do I create a shape that keeps the bottom colour a consistent size with the text. While allowing different button sizes. Also can I easily alternate the colours by setting the style on each button and defining them as so:
<style name ="ButtonTheme.Custom1" parent="Base.Widget.AppCompat.Button.Colored">
<item name="colorPrimary">#android:color/holo_blue_light</item>
<item name="colorPrimaryDark">#android:color/holo_blue_dark</item>
</style>
<style name ="ButtonTheme.Custom2" parent="Base.Widget.AppCompat.Button.Colored">
<item name="colorPrimary">#android:color/holo_green_light</item>
<item name="colorPrimaryDark">#android:color/holo_green_dark</item>
</style>
<style name ="ButtonTheme.Custom3" parent="Base.Widget.AppCompat.Button.Colored">
<item name="colorPrimary">#android:color/holo_red_light</item>
<item name="colorPrimaryDark">#android:color/holo_red_dark</item>
</style>
<style name ="ButtonTheme.Custom4" parent="Base.Widget.AppCompat.Button.Colored">
<item name="colorPrimary">#android:color/holo_orange_light</item>
<item name="colorPrimaryDark">#android:color/holo_orange_dark</item>
</style>
<style name ="ButtonTheme.Custom5" parent="Base.Widget.AppCompat.Button.Colored">
<item name="colorPrimary">#android:color/holo_blue_bright</item>
<item name="colorPrimaryDark">#android:color/holo_blue_light</item>
</style>
My custom shape so far is this, which is close; but how can I make the darker color keep a consistent size while the other moves according to size of button?
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:bottom="10dp">
<shape android:shape="rectangle" >
<size android:height="10dp" />
<solid android:color="#color/colorPrimaryDark" />
</shape>
</item>
<item android:top="120dp">
<shape android:shape="rectangle" >
<size android:height="120dp" />
<solid android:color="#color/colorPrimary" />
</shape>
</item>
</layer-list>
You can use RecyclerView and StaggeredGrid
https://developer.android.com/reference/android/support/v7/widget/StaggeredGridLayoutManager.html
I've added a sidebar (navigation drawer) to my app that currently looks like this:
http://i.imgur.com/aQOnNY4.png
However, the colors are wrong. The drawable image (.png) for the plus icon inside of the red circle should be white (as the image is), but it's being tinted blue and I'm not sure how to prevent this.
It appears to be blue because of the textColorSecondary value in my styles.xml:
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:textColorPrimary">#color/dark_gray</item>
<item name="android:textColorSecondary">#color/blue</item>
</style>
Here is the list items for the sidebar:
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:checkableBehavior="single">
<item android:title="Menu">
<menu>
<item
android:icon="#drawable/ic_home_black_48dp"
android:title="One"
android:checked="true"/>
<item
android:icon="#drawable/ic_favorite_black_48dp"
android:title="Two" />
<item
android:icon="#drawable/custom_icon"
android:title="Three" />
</menu>
</item>
</group>
</menu>
Here is the custom_icon drawable used in the third item in the list:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/circle_icon">
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid
android:color="#ff0000"
/>
<size
android:width="20dp"
android:height="20dp"
/>
</shape>
</item>
<item
android:drawable="#drawable/ic_add_white"
android:adjustViewBounds="true"
android:scaleType="fitXY"
android:top="2dp"
android:right="2dp"
android:bottom="2dp"
android:left="2dp"
/>
</layer-list>
How can I prevent the color of the plus icon from being changed by the value of textColorSecondary and keep its original white color?
As an additional side question, how can I style the sidebar completely (including subheader text color, list item text color, etc)? I can't find any tutorials online.
I've solved my own question.
Simply do the following:
NavigationView sidebar = (NavigationView) findViewById(R.id.sidebar);
sidebar.setItemIconTintList(null);
Hi so I am little confused and wondering if anyone could point me in the right direction.
Go and use Google Play Store on Lollipop and pre-lollipop
You will see on lollipop that selectable views have the ripple effect.
On pre-lollipo, you get this highlight effect.
How is this done?
At the moment in my app, I have a drawable-v21 directory that contains this selector
It basically does the ripple on top of my background
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?android:colorControlHighlight">
<item android:id="#android:id/mask" android:drawable="#android:color/white"/>
<item android:drawable="#color/colorAccentWith92PercentOpacity"/>
</ripple>
However, other answers say to use
android:background="?attr/selectableItemBackground"
To get the highlight effect on pre-lollipop but this overrides my background. How could i set this on top of my current background?
Also do i have to create a ripple drawable (in drawble-v21) for every kind of button in my app? How would I do this for recycler view items?
What makes this question unique
I do not want ripple for pre-lollipop I am asking how devs efficiently make their button do ripple on lollipop and a hight light effect on pre
Option 1
Define colorControlHighlight in your theme and as long you're using default appcompat-v7 buttons the highlight color should work out-of-the-box.
Option 2
This is an example of how I backported Material button style with a bit of crossfade animation and shadows without using external libraries. May it help you on your way.
Provided the button will be white text over dark background (#color/control_normal) with light highlight:
values/themes.xml
Here I'll override default button style for the whole theme:
<style name="AppTheme" parent="Base.AppTheme">
<item name="buttonStyle">#style/Widget.AppTheme.Button</item>
</style>
values/integers.xml
<!-- Some numbers pulled from material design. -->
<integer name="button_pressed_animation_duration">100</integer>
<integer name="button_pressed_animation_delay">100</integer>
values-v21/styles.xml
Button style for Lollipop which understands theme overlays and uses ripple by default. Let's just have it color the ripple with appropriate paint:
<style name="Widget.AppTheme.Button" parent="Widget.AppCompat.Button">
<!-- On Lollipop you can define theme via style. -->
<item name="android:theme">#style/ThemeOverlay.AppTheme.Button</item>
</style>
<style name="ThemeOverlay.AppTheme.Button" parent="ThemeOverlay.AppCompat.Dark">
<!-- The magic is done here. -->
<item name="colorButtonNormal">#color/control_normal</item>
</style>
values/styles.xml
Before Lollipop it gets tricky.
<style name="Widget.AppTheme.Button" parent="Widget.AppCompat.Button">
<item name="android:background">#drawable/button_normal_background</item>
</style>
drawable/button_normal_background.xml
Thi is the composite drawable of the whole button.
<inset
xmlns:android="http://schemas.android.com/apk/res/android"
android:insetLeft="#dimen/abc_button_inset_horizontal_material"
android:insetTop="#dimen/abc_button_inset_vertical_material"
android:insetRight="#dimen/abc_button_inset_horizontal_material"
android:insetBottom="#dimen/abc_button_inset_vertical_material">
<layer-list>
<!-- Shadow. -->
<item
android:drawable="#drawable/button_shadow"
android:top="-0dp"
android:bottom="-1dp"
android:left="-0dp"
android:right="-0dp"/>
<item
android:drawable="#drawable/button_shadow_pressable"
android:top="-0dp"
android:bottom="-3dp"
android:left="-1dp"
android:right="-1dp"/>
<!-- Background. -->
<item android:drawable="#drawable/button_shape_normal"/>
<!-- Highlight. -->
<item>
<selector
android:enterFadeDuration="#integer/button_pressed_animation_duration"
android:exitFadeDuration="#integer/button_pressed_animation_duration">
<item
android:drawable="#drawable/button_shape_highlight"
android:state_focused="true"
android:state_enabled="true"/>
<item
android:drawable="#drawable/button_shape_highlight"
android:state_pressed="true"
android:state_enabled="true"/>
<item
android:drawable="#drawable/button_shape_highlight"
android:state_selected="true"
android:state_enabled="true"/>
<item android:drawable="#android:color/transparent"/>
</selector>
</item>
<!-- Inner padding. -->
<item android:drawable="#drawable/button_padding"/>
</layer-list>
</inset>
drawable/button_shadow.xml
This is the shadow when not pressed.
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:bottomLeftRadius="3dp"
android:bottomRightRadius="3dp"
android:topLeftRadius="2dp"
android:topRightRadius="2dp"/>
<solid android:color="#2000"/>
</shape>
drawable/button_shadow_pressable.xml
This is the extended shadow in pressed state. The result effect will look crude when you look up close but it's good enough from distance.
<selector
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:ignore="UnusedAttribute"
android:enterFadeDuration="#integer/button_pressed_animation_duration"
android:exitFadeDuration="#integer/button_pressed_animation_duration">
<item
android:state_pressed="true"
android:state_enabled="true">
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:bottomLeftRadius="5dp"
android:bottomRightRadius="5dp"
android:topLeftRadius="3dp"
android:topRightRadius="3dp"/>
<solid android:color="#20000000"/>
</shape>
</item>
<item android:drawable="#android:color/transparent"/>
</selector>
drawable/button_shape_normal.xml
This is the main button shape.
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="#dimen/abc_control_corner_material"/>
<solid android:color="#color/control_normal"/>
</shape>
drawable/button_padding.xml
Just additional padding to be absolutely consistent with the Material button.
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#android:color/transparent"/>
<padding
android:left="#dimen/abc_button_padding_horizontal_material"
android:top="#dimen/abc_button_padding_vertical_material"
android:right="#dimen/abc_button_padding_horizontal_material"
android:bottom="#dimen/abc_button_padding_vertical_material"/>
</shape>
drawable/button_shape_highlight.xml
This is the highlight button shape drawn over normal button shape.
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="#dimen/abc_control_corner_material"/>
<solid android:color="#color/control_highlight"/>
</shape>
#color/control_highlight can point to
#color/ripple_material_dark - translucent white, use over dark background
#color/ripple_material_light - translucent black, use over light background
Any other color you define.
You can set a background of your views in this way:
android:background="#drawable/touch_selector"
Create a version without ripple for pre lollipop:
drawable/touch_selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- State when a row is being pressed, but hasn't yet been activated (finger down) -->
<item android:state_pressed="true"
android:drawable="#color/grey"
/>
<!-- For ListView in SINGLE_CHOICE_MODE, it flags the active row -->
<item android:state_activated="true"
android:drawable="#color/light_green" />
<!-- Default, "just hangin' out" state. -->
<item android:drawable="#android:color/transparent" />
</selector>
Now do the same for lollipop and above,
but with ripple effect:
crete drawable-v21/touch_selector.xml
It will look like:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- State when a row is being pressed, but hasn't yet been activated (finger down) -->
<item android:state_pressed="true">
<ripple android:color="#color/grey" />
</item>
<!-- For ListView, when the view is "activated". In SINGLE_CHOICE_MODE, it flags the active row -->
<item android:state_activated="true"
android:drawable="#color/light_green" />
<!-- Default, "just hangin' out" state. -->
<item android:drawable="#android:color/transparent" />
</selector>
That's it.
Now you are having ripple effect at lollipop and above devices and highlight at pre lollipop.
Edit:
In case of using in a ListView - use created above as a background of ListView item
I have a Button in my layout whose background and textcolor are defined as selectors. When unpressed the button has a background color and a textcolor and when pressed another color and another text color - e.g. white background with black text -> black background with white text.
At a certain point in my code I need to replace the background/text color with a third set of colors and then go back to the original selector defined in the xml. However, after going back the text no longer appears and instead I get just a solid colored button.
<Button
android:id="#+id/somebutton"
android:layout_width="80"
android:layout_height="80"
android:textColor="#color/sometext_selector"
android:background="#drawable/somebackground_selector"
android:gravity="center"
android:text="#string/sometext"
android:textSize="15sp"
/>
At this point everything is fine, but when I do this:
someButton.setBackgroundDrawable(ResourcesCompat.getDrawable(getResources(), R.drawable.backgroundRed, null));
someButton.setTextColor(getResources().getColor(android.R.color.holo_red_light));
and then afterwards this:
someButton.setBackgroundDrawable(ResourcesCompat.getDrawable(getResources(), R.drawable.originalBackgroundSelectorDefinedInXml, null));
someButton.setTextColor(getResources().getColor(R.color.originalTextSelectorDefinedInXml));
is when the problems begin.
Here are the xmls for my selectors - apologies for pseudocode, just imagine appropriate hex values:
First - the background:
<item android:drawable="#drawable/color_purple_full" android:state_selected="true"/>
<item android:drawable="#drawable/color_purple_full" android:state_pressed="true"/>
<item android:drawable="#drawable/color_purple_full" android:state_focused="true"/>
<item android:drawable="#drawable/color_purple_outline"/>
color_purple_outline:
android:shape="oval">
<stroke android:width="2dp" android:color="#somepurplehexa" />
<size android:width="80dp" android:height="80dp"/> </shape>
color_purple_full:
android:shape="oval">
<solid android:color="#somepurplehexa"/>
<size android:width="80dp" android:height="80dp" /> </shape>
for text:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#android:color/black" android:state_selected="true"/>
<item android:color="#android:color/black" android:state_pressed="true"/>
<item android:color="#android:color/black" android:state_focused="true"/>
<item android:color="#color/green"/>
What I'm seeing is the correct background in the unpressed state but in the pressed state I'm just getting a solid color with no text on it at all. I'd be grateful for any ideas as to why this is happening and why in the original xml it works fine but only stops working after changing it programmatically?
SOLVED:
turns out the problem was here:
someButton.setTextColor(getResources().getColor(R.color.originalTextSelectorDefinedInXml));
should have been
someButton.setTextColor(getResources().getColorStateList(R.color.originalTextSelectorDefinedInXml));