I have problem with implementing selector in custom view. I have searched it for the last 1 hour but I could not find the solution. I have custom view with imageview, some textviews and nine patch background but the problem is when it's on pressed state, the color of selector doesn't cover the image view.
For the implementation, I'm using background selector for the layout and I just change the 9 patch image on pressed and un-pressed state, then disable default selector in listview.
Do you have any better solution? I see in google play, the blue selector covers all of the views and that is what I want.
For the xml,
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/touch_selector"
android:orientation="horizontal"
android:padding="16dp" >
<ImageView />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView />
<TextView />
</LinearLayout>
</LinearLayout>
And for the touch selector
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/card_background_pressed" android:state_focused="true"/>
<item android:drawable="#drawable/card_background_pressed" android:state_pressed="true"/>
<item android:drawable="#drawable/card_background_white" android:state_focused="false" android:state_pressed="false"/>
</selector>
where card_background is 9 patch image.
EDIT :
This is the example from google play,
The accepted is not correct.
It's possible to use a nine-path in the selector, you just need to use the <nine-patch>. Something like this:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true">
<nine-patch
android:src="#drawable/marker"/>
</item>
<item>
<shape>
<solid android:color="#000000" />
</shape>
</item>
</selector>
Related
I have following spinner:
<Spinner
android:id="#+id/safe_network_time_spinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:background="#drawable/spinner_selector"
android:entries="#array/schedule_edit_days_repeat"
android:popupBackground="#drawable/custom_dropdown_white_background"
android:spinnerMode="dropdown"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#id/divider4"
tool:listitem="#layout/custom_dropdown_spinner_button" />
The spinner_selector is:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<bitmap android:gravity="right|center_vertical" android:src="#drawable/down_red_arrow" />
</item>
</selector>
The dropdown list appears like this:
When I select an item of the dropdown list, if it is too long it overlaps the arrov bitmap. how can I avoid this?
Try using a layer-list
bg_spinner.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<!-- This is the actual spinner background -->
<selector >
<!-- Feel free to use your own drawable for these states -->
<item android:state_window_focused="false" android:drawable="#drawable/bg_border_accent_thin"/>
<item android:state_pressed="true" android:drawable="#drawable/bg_border_accent_thin"/>
<item android:state_window_focused="true" android:state_pressed="false" android:drawable="#drawable/bg_border_grey_thin"/>
</selector>
</item>
<!-- This is the spinner drawable, use your custom drawable aswell. android:right does the magin to separate this drawable from the spinner content-->
<item android:drawable="#drawable/ic_ripple_arrow"
android:gravity="center_vertical|right"
android:right="16dp"/>
</layer-list>
Edit 02/02/2020
My apologies for a weekend-long lunch.
If you are using the androidx dependencies (which I suggest you do) here's the code that I use to properly add spacing between the text and the selected item in the spinner.
On your layout.xml
<!-- The line I think you need is the one giving padding to the right -->
<androidx.appcompat.widget.AppCompatSpinner
android:paddingTop="4dp"
android:paddingBottom="4dp"
android:paddingRight="36dp"
android:background="#drawable/bg_spinner"
android:popupBackground="#drawable/bg_spinner_popup"/>
The bg_spinner.xml is the one provided a couple of lines above.
And the popup one doesn't really matter, since it gives some directives on how to paint a background, nothing important but here it is either way...
bg_spinner_popup.xml
<?xml version="1.0" encoding="utf-8" ?>
<shape xmlns:android="http://schemas.android.com/apk/res/android
android:shape="rectangle">
<corners android:radius="3dp"/>
<solid android:color ="#android:color/white"/>
<stroke android:width="5px" android:color="#color/primaryColor"/>
</shape>
I am using the following xml drawable as the background of my recyclerview list item.
touch_selector.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_activated="true"
android:drawable="#color/green_text_500"/>
<!-- Default, "just hangin' out" state. The base state also
implements the ripple effect. -->
<item android:drawable="#drawable/touch_selector_base" />
</selector>
touch_selector_base.xml
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#color/light_grey">
<item android:id="#android:id/mask" android:drawable="#color/light_grey" />
<item android:drawable="#color/dark_grey"/>
</ripple>
In the list item I am using the touch_selector.xml as follows in my list_item_quote.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="86dp"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:clickable="true"
android:focusable="true"
android:background="#drawable/touch_selector"
>
// layout
</LinearLayout>
SIMILARLY I have another xml drawable touch_selector_dark.xml and touch_selector_base_dark.xml
In my recycler-view-adapter I alternate between these two drawables based on the index. For even indexes I use the darker drawable and for the odd index I use the lighter background to produce an alternating effect. But the issue is that the ripple effect is not working.
Here are the colors:
light_grey = #5b5b5b
dark_grey = #212121
green_text_500 = #37863a
use this line in your recycleview list layout
android:background="?android:attr/selectableItemBackground"
try this
worked for me
android:clickable="true"
android:focusable="true"
android:foreground="?attr/selectableItemBackground"
I think your ripple file is not valid, you can check this:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<shape android:shape="rectangle">
<solid android:color="#color/dark_grey"/>
</shape>
</item>
</selector>
You can use android:foreground="#drawable/touch_selector" to display the ripple effect and also use android:background="" to set any other drawable background.
I want to make a weekly calendar, where every day is a custom checkbox with objective to look like the image bellow:
(http://i.imgur.com/WjIKCd0.png)
When the user clicks on a day (Monday in this case), the "background" and "button" checkbox changes as well the text color...
I made the drawables and it seems to work fine... check bellow the code:
Checkbox layout:
<CheckBox
android:id="#+id/selectMonday"
android:layout_width="40dp"
android:layout_height="40dp"
android:button="#drawable/ic_none"
style="#style/CheckBoxBackgroundView"
android:onClick="selectDay"
android:text="#string/monday_letter"
android:gravity="center"
android:checked="true"/>
(the drawable "ic_none", is simple a 135x135 "transparent" image with nothing in it...)
Style (CheckBoxBackgroundView):
<style name="CheckBoxBackgroundView">
<item name="android:background">#drawable/background_day_week_picker_box_selector</item>
<item name="android:textColor">#color/text_color_day_week_picker_box_selector</item>
<item name="android:textSize">#dimen/text_spinner_text</item>
<item name="android:textStyle">bold</item>
</style>
Background Selector (background_day_week_picker_box_selector):
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="false"
android:drawable="#drawable/background_day_of_week_picker_unselected" />
<item android:state_checked="true"
android:drawable="#drawable/background_day_of_week_picker_selected" />
</selector>
Background selected (background_day_of_week_picker_selected):
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<!-- view background color -->
<solid
android:color="#color/red_color" >
</solid>
<!-- view border color and width -->
<stroke
android:width="3dp"
android:color="#color/transparent">
</stroke>
<!-- Here is the corner radius -->
<corners
android:radius="10dp" >
</corners>
</shape>
and finally the color selector (text_color_day_week_picker_box_selector):
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="false"
android:color="#color/red_color"></item>
<item android:state_checked="true"
android:color="#color/white"></item>
</selector>
I tried this in several devices... in some, it appears like it suppose to, in others the text disappears and it looks like this:
(http://i.imgur.com/Jy9FrPS.png)
probably is coincidence, but all the devices that worked are below 5 inches...
is there anything wrong with my code that I'm not seeing? anyone have any suggestions?
Thanks in advance
The problem is that the 135x135 button drawable is pushing the text out of the bounds of your CheckBox's width. Instead of using a drawable, you can just set android:button="#color/transparent".
I customized the Toggle button by using a drawable defined by using a selector. I use this drawable as background for the Toggle button.
<ToggleButton
android:id="#+id/mailbox:toggle_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_weight="1"
android:background="#drawable/toggle_background"
android:gravity="center_horizontal|center_vertical" />
The toggle_background is defined here:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="#drawable/img1"
android:state_checked="true" />
<item
android:drawable="#drawable/img2"
android:state_checked="false" />
</selector>
The problem is that the image is always stretched. Is there a way to define an image for the two states that is not stretched?
What I need is a background that will be stretched and in the center of the button an icon that must not be stretched.
Is it possible?
This is my final solution.
In the layout:
<ToggleButton
android:id="#+id/mailbox:toggle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#drawable/toggle_drawable_layers"/>
in the toggle_drawable_layers.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="#drawable/toggle_drawable_bkg"></item>
<item android:left="10dp" android:drawable="#drawable/toggle_drawable_left"
android:gravity="center_vertical|center_horizontal" />
</layer-list>
in the toggle_drawable_left.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true">
<bitmap android:src="#drawable/bitmap_checked"
android:gravity="center_vertical|center_horizontal" />
</item>
<item android:state_checked="false">
<bitmap android:src="#drawable/bitmap_unchecked"
android:gravity="center_vertical|center_horizontal" />
</item>
</selector>
I did the same task this way, the button:
<ToggleButton android:id="#+id/mlAbout"
android:textOn="#string/about"
android:textOff="#string/about"
android:background="#drawable/ml_about" />
#drawable/ml_about:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="#drawable/list_bg_top"></item>
<item android:left="10dp">
<bitmap android:src="#drawable/waiting_status_btn"
android:gravity="center_vertical|left" />
</item>
</layer-list>
#drawable/list_bg_top background image that will be stretched and #drawable/waiting_status_btn is the icon the will not be stretched with the widget
Just use bitmaps instead of drawables in your selector like so (no need to use layers):
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="#drawable/img1"
android:state_checked="true" />
<item
android:drawable="#drawable/img2"
android:state_checked="false" />
</selector>
Also, don't forget to declare
android:textOff=""
android:textOn=""
in your ToggleButton declaration
There is another way to overcome the issue of stretching:
Just convert the image into a Nine-Patch image, where the stretchable areas are just on all sides of the image.
Then Android will stretch the image only in invisible areas, and keep the visible image unchanged.
I need to do round cornered button with background color change in android.
How could i do that?
Example link/code is much appreciated.
You want to use Android's Shape Drawables.
http://developer.android.com/guide/topics/resources/drawable-resource.html#Shape
drawable/cool_button_background.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:radius="#dimen/corner_radius" />
<gradient
android:angle="270"
android:startColor="#color/almost_white"
android:endColor="#color/somewhat_gray"
android:type="linear" />
</shape>
Then you'd have to create a "selector" drawable from those shape drawables. This allows you to make the button appear different depending on the state. IE: Pressed, focused, etc.
http://developer.android.com/guide/topics/resources/drawable-resource.html#StateList
drawable/cool_button.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:drawable="#drawable/cool_inner_press_bottom" />
<item android:state_focused="true" android:state_enabled="true"
android:state_window_focused="true"
android:drawable="#drawable/cool_inner_focus_bottom" />
<item
android:drawable="#drawable/cool_button_background" />
</selector>
Bonus: You might want to create a style for the button so you can have them be consistent throughout the program. You can cut this step out and just set the button's android:background="#drawable/cool_button".
values/styles.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="MyCoolButton">
<item name="android:background">#drawable/cool_button_background</item>
</style>
</resources>
Finally, the button!
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:background="#drawable/appwidget_bg">
<Button
android:id="#+id/btnAction"
android:layout_width="wrap_content"
android:layout_weight="wrap_content"
style="#style/CoolButton"
/>
</LinearLayout>
Import PorterDuff and use setColorFilter() as follows
import android.graphics.PorterDuff.Mode;
Button btn = (Button) findViewById(R.id.myButton);
btn.getBackground().setColorFilter(Color.GRAY, Mode.MULTIPLY);