ListView Item Selected State not working - android

So I have a ListView and I want to change the color of each items background and text. This ListView is inside a ListFragment. My code inflates the layout in the onCreateView and inflates the layout of each item in the newView.
The android:state_pressed="true" is working fine, whenever I press in one item the background changes to that color. But when selecting an item neither the bg color or text color changes, even though I've defined an item with android:state_selected="true" in the selector.
Edit: I'm using SDK level 11 (Android 3.0) and a Motorola Xoom.
The list fragment layout:
<?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">
<ListView
android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
</LinearLayout>
The list item layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="25dp"
android:background="#drawable/list_item_bg_selector">
<TextView android:id="#+id/form_title"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="#dimen/text_size_xlarge"
android:textStyle="bold"
android:textColor="#drawable/list_item_text_selector" />
<TextView android:id="#+id/form_subtitle"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="#dimen/text_size_medium"
android:textStyle="normal"
android:layout_marginTop="5dp"
android:textColor="#drawable/list_item_text_selector" />
</LinearLayout>
The background selector:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_pressed="true"
android:drawable="#color/white" />
<item
android:state_selected="true"
android:drawable="#drawable/list_item_bg_selected" />
<item
android:drawable="#color/list_bg" />
</selector>
The text selector:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_selected="true"
android:drawable="#color/white" />
<item
android:drawable="#color/list_text_blue" />
</selector>

The answer is to use the android:state_activated="true" state, instead of the "selected" state. More on this here: ListFragment Item Selected Background

The best solution with support of all API levels is to implement Checkable feature for list item View which means that the top view of your list item layout has to implement Checkable interface (in my case it was TextView, but the same can be applied on ViewGroup classes like LinearLayout). When you click on a list item, the ListView call setChecked method and there we change the state of View to use android:state_checked="true" selector. Together with list view android:choiceMode="singleChoice" it will select only one item.
The trick is to override onCreateDrawableState method and set the checked state here for drawables. See example of SelectableTextView bellow. After the setChecked is called, the checked state is stored and called refreshDrawableState.
Example of SelectableTextView:
package com.example.widget.SelectableTextView;
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.util.AttributeSet;
import android.widget.Checkable;
import android.widget.TextView;
public class SelectableTextView extends TextView implements Checkable {
private static final int[] CHECKED_STATE_SET = {
android.R.attr.state_checked
};
private boolean mChecked;
public SelectableTextView(Context context) {
super(context);
}
public SelectableTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SelectableTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public SelectableTextView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
#Override
public void setChecked(boolean checked) {
if (mChecked != checked) {
mChecked = checked;
refreshDrawableState();
}
}
#Override
public boolean isChecked() {
return mChecked;
}
#Override
public void toggle() {
setSelected(!mChecked);
}
#Override
protected int[] onCreateDrawableState(int extraSpace) {
final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
if (isChecked()) {
mergeDrawableStates(drawableState, CHECKED_STATE_SET);
}
return drawableState;
}
}
Example of selectable_list_item.xml layout:
<?xml version="1.0" encoding="utf-8"?>
<com.example.widget.SelectableTextView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#android:id/text1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textColor="#color/list_item_selector_foreground"
android:background="#drawable/list_item_selector_background"
tools:text="Item 1"/>
Example of list_item_selector_foreground.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- checked -->
<item android:color="#color/list_item_text_active" android:state_checked="true"/>
<item android:color="#color/list_item_text"/>
</selector>
Example of list_item_selector_background.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#color/list_item_background_selected" android:state_pressed="true"/>
<item android:drawable="#color/list_item_background_selected" android:state_focused="true"/>
<item android:drawable="#color/list_item_background_active" android:state_checked="true"/>
<item android:drawable="#color/list_item_background"/>
</selector>

Do not forget to set clickable="true" for the layout. This solved my problem.
List item layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/list_item_bg_selector"
android:clickable="true" >
<TextView
android:id="#+id/tvNewsPreviewTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="3"
android:ellipsize="end"
android:textSize="#dimen/news_preview_title_textsize"
android:textStyle="bold" />
</RelativeLayout>
Background selector:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" >
<shape android:shape="rectangle">
<stroke android:width="1dp" android:color="#color/black" />
<gradient android:startColor="#color/white" android:endColor="#color/white" />
</shape>
</item>
<item>
<shape android:shape="rectangle">
<stroke android:width="1dp" android:color="#color/holo_gray_darker" />
<gradient android:startColor="#color/holo_gray_bright" android:endColor="#color/holo_gray_bright" />
</shape>
</item>
</selector>

#Andrew S: Along with using activated state in selector , activated state must be set to false for default case as shown in below selector code.
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="false"
android:state_activated="false"
android:color="#color/dark_text_blue"/>
<item android:state_pressed="true"
android:color="#color/red"/>
<item android:state_activated="true"
android:color="#color/red"/>
</selector>

Related

Coordinating drawable state between parent and child

I have a custom view LockButton which is just a FrameLayout that holds two specific child views. It holds an ImageButton as well as a type of custom view ProgressIndicator. This question centers around the behavior of LockButton and ImageButton. In particular I have added a custom state to the LockButton. The ImageButton has a StateListDrawable for it's source and a ColorStateList for its background.
The problem is when I change the state in LockButton, that change is not displayed in the ImageButton
What am I doing wrong?
LockButton Class:
public class LockButton extends FrameLayout {
private static final int[] STATE_LOCKED = {R.attr.state_locked};
private boolean locked = true;
View button;
public LockButton(#NonNull Context context) {
this(context, null);
}
public LockButton(#NonNull Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
LayoutInflater.from(context).inflate(R.layout.lock_button, this);
button = findViewById(R.id.lock_button_actual);
}
#Override
public void setOnClickListener(#Nullable OnClickListener l) {
button.setOnClickListener(l);
}
#Override
public int[] onCreateDrawableState(int extraSpace) {
final int[] drawableState;
if(locked){
drawableState = super.onCreateDrawableState(extraSpace + 1);
mergeDrawableStates(drawableState, STATE_LOCKED);
} else {
drawableState = super.onCreateDrawableState(extraSpace);
}
return drawableState;
}
public void lock(boolean locked) {
if(this.locked != locked) {
this.locked = locked;
}
refreshDrawableState();
button.refreshDrawableState();
}
public static class ProgressCircle extends View {...}
}
LockButton Layout:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
app:state_locked="true"
android:layout_gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<view class="com.example.LockButton$ProgressCircle"
android:layout_width="68dp"
android:layout_height="68dp"
android:layout_gravity="center"
/>
<ImageButton
android:id="#+id/lock_button_actual"
android:layout_width="#dimen/fab_size"
android:layout_height="#dimen/fab_size"
android:background="#drawable/button_lock_background"
android:src="#drawable/icon_lock_status"
android:tint="#color/white"
android:elevation="6dp"
android:layout_gravity="center"
android:duplicateParentState="true"
/>
</FrameLayout>
Attributes XML:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="lockState">
<attr name="state_locked" format="boolean" />
</declare-styleable>
</resources>
Drawable icon_lock_status.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item app:state_locked="false" android:drawable="#drawable/icon_lock_open" />
<item app:state_locked="true" android:drawable="#drawable/icon_lock_closed"/>
</selector>
Drawable button_lock_background.xml:
<?xml version="1.0" encoding="utf-8"?>
<ripple
xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?android:colorControlHighlight"
>
<item>
<shape android:shape="oval">
<solid android:color="#color/button_lock_color" />
</shape>
</item>
</ripple>
Color button_lock_color.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item app:state_locked="false" android:color="#color/grey_dark" />
<item app:state_locked="true" android:color="#color/vibrant_red" />
</selector>
When I need to change the state, I simply call
lockButton.lock(true); // or false
on the LockButton
I have also tested to see if using default states instead of my custom one would work any better. This did not help. The ImageButton still does not respond to changes in the default states.
Setting a StateListDrawable as a background to the LockButton (FrameLayout) does work. So the state change is working properly on the parent, it is just not reflected in the child.

How to set Material design style to disabled EditText (android)?

I'm trying to make my disabled EditText's style like in guidelines:
https://www.google.com/design/spec/components/text-fields.html#text-fields-labels
<EditText
android:id="#+id/account_number"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/test_account"
android:enabled="false" />
I've already implemented material design styles, so all my widgets look material.
The question is: Is there any way to get this dotted underline using styles, without putting additional views?
My styles.xml:
<style name="Theme.Main" parent="#style/Theme.AppCompat.Light.NoActionBar">
<item name="android:editTextStyle">#style/android:Widget.Material.EditText</item>
</style>
Finally I managed to do as you've shown, It looks like
Create dotted.xml inside drawable folder and paste these
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:bottom="1dp"
android:left="-2dp"
android:right="-2dp"
android:top="-2dp">
<shape android:shape="rectangle">
<stroke
android:width="0.5dp"
android:color="#android:color/black" />
<solid android:color="#ffffff" />
<stroke
android:width="1dp"
android:color="#030310"
android:dashGap="5dp"
android:dashWidth="5dp" />
<padding
android:bottom="5dp"
android:left="5dp"
android:right="5dp"
android:top="5dp" />
</shape>
</item>
</layer-list>
Then simply set the android:background attribute to dotted.xml we just created. Your EditText looks like this.
<EditText
android:id="#+id/account_number"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="test account"
android:background="#drawable/dotted"
style="#style/Theme.Main" <!--Its your custom style-->
android:enabled="false" />
AFAIK, there is no "stock" way. Take the material design guidelines as it is, a guideline ;)
Finally I ended up with a custom view. It might be not the most elegant solution but it solves my task.
Hope it will be helpful for someone.
DisabledTextField.java:
package com.kabunov.example.ui.common;
import android.content.Context;
import android.content.res.TypedArray;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.TextView;
import com.kabunov.example.R;
public final class DisabledTextField extends FrameLayout {
private TextView tvCaption;
private TextView tvText;
private View divider;
public DisabledTextField(final Context context) {
this(context, null);
}
public DisabledTextField(final Context context, final AttributeSet attrs) {
this(context, attrs, 0);
}
public DisabledTextField(final Context context, final AttributeSet attrs, final int defStyleAttr) {
super(context, attrs, defStyleAttr);
View.inflate(getContext(), R.layout.component_disabled_text_field, this);
tvCaption = (TextView) findViewById(R.id.caption);
tvText = (TextView) findViewById(R.id.value);
final TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.DisabledTextField);
if (null != typedArray) {
final String captionText = typedArray.getString(R.styleable.DisabledTextField_caption);
if (TextUtils.isEmpty(captionText)) {
tvCaption.setVisibility(GONE);
} else {
tvCaption.setText(captionText);
tvCaption.setVisibility(VISIBLE);
}
final String text = typedArray.getString(R.styleable.DisabledTextField_disabledText);
tvText.setText(text);
typedArray.recycle();
}
}
public final void setCaption(final CharSequence caption) {
this.tvCaption.setText(caption);
this.tvCaption.setVisibility(VISIBLE);
}
public final void setDisabledText(final CharSequence value) {
this.tvText.setText(value);
}
}
/layout/component_disabled_text.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:orientation="vertical">
<TextView
android:id="#+id/caption"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="#style/DisabledTextFieldCaption"/>
<TextView
android:id="#+id/value"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="#style/DisabledTextFieldValue"/>
<View
android:id="#+id/divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#drawable/disabled_text_field_background"
android:layerType="software"/>
</LinearLayout>
/values/attributes_disabled_text_field.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="DisabledTextField">
<attr name="caption" format="string"/>
<attr name="disabledText" format="string"/>
</declare-styleable>
</resources>
/drawable/disabled_text_field_background.xml:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:bottom="-1dp"
android:left="-1dp"
android:right="-1dp"
android:top="0dp">
<shape android:shape="rectangle">
<stroke
android:width="1dp"
android:color="#color/text_color_disabled_text_view"
android:dashGap="2dp"
android:dashWidth="1dp" />
<solid android:color="#android:color/transparent" />
</shape>
</item>
</layer-list>
/values/styles.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="text_color_disabled_text_view">#61000000</color>
<style name="DisabledTextFieldCaption">
<item name="android:textSize">12sp</item>
<item name="android:textColor">#color/text_color_disabled_text_view</item>
</style>
<style name="DisabledTextFieldValue">
<item name="android:layout_marginTop">3dp</item>
<item name="android:layout_marginBottom">8dp</item>
<item name="android:textSize">16sp</item>
<item name="android:textColor">#color/text_color_disabled_text_view</item>
</style>
</resources>
Example of usage:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.kabunov.example.ui.common.DisabledTextField
android:id="#+id/example"
android:layout_width="match_parent"
android:layout_height="wrap_content"
custom:caption="Some caption"
custom:disabledText="Disabled text"/>
</LinearLayout>
And the result:

Selector background does not work?

Use Selector as view's background, like following codes :
my_selector.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/cell_bg_e" />
<item android:state_checked="true" android:drawable="#drawable/cell_bg_e" />
<item android:state_selected="true" android:drawable="#drawable/cell_bg_e" />
<item android:drawable="#drawable/cell_bg_n_trans" />
</selector>
MyView.java
public class MyView extends LinearLayout
{
public MyView(Context context, CharSequence text, Drawable drawable) {
super(context);
setBackgroundResource(R.drawable.my_selector);
}
}
it works on all the devices except for some certain 800x480 resolution device(lick htc g12)
why ?
You should ensure the view you have set this selector drawable as a background of is clickable.
You can do this in code:
public MyView(Context context, CharSequence text, Drawable drawable) {
super(context);
setClickable(true);
setBackgroundResource(R.drawable.my_selector);
}
Alternatively in XML:
<MyView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/my_selector"
android:clickable="true"
android:orientation="horizontal"/>

How to set text color as link?

I have textview which I want to change the color when I focus or cliclked it like a link text in web I have try to follow this but it still doesn't work
please help, thanks
this is my java code
public class TextColorActivity extends Activity {
/** Called when the activity is first created. */
ColorStateList cl = null;
private TextView title;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
title = (TextView)findViewById(R.id.hello);
try {
Log.d("test","try");
XmlResourceParser xpp = getResources().getXml(R.drawable.selector_txt);
cl = ColorStateList.createFromXml(getResources(), xpp);
} catch (Exception e) {}
title.setTextColor(cl);
title.setFocusable(true);
title.setClickable(true);
title.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Log.d("test","click");
}
});
}
this is my selector_txt.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true" android:color="#color/Darkgoldenrod"/>
<item android:state_pressed="true" android:state_enabled="false"
android:color="#color/Darkgreen" />
<item android:state_enabled="false" android:color="#color/Red" />
<item android:color="#color/blue"/>
and this is my main.xml
<?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" >
<TextView
android:id="#+id/hello"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/hello"
android:textSize="30dp"
android:textStyle="bold"
android:duplicateParentState="true"/>
You can also set your color in the xml if you want. Just create a color folder in your res folder and move the xml file there then you can set it via android:textColor="#color/selector_txt"
Regards the problem you're having. Android will always use the first match in a selector. If a TextView is pressed it is also focused. So add android:pressed="false" to your first item or move the line after the pressed status line.
That's the full xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="false" android:color="#color/Red" />
<item android:state_pressed="true" android:color="#color/Darkgreen" />
<item android:state_focused="true" android:color="#color/Darkgoldenrod"/>
<item android:color="#color/blue"/>
</selector>

Custom checkbox image android

Is there an easy way to use a custom image for a checkbox? I'm looking to duplicate the "starred" behavior of gmail. So I want to have a checkbox that, when checked, is a filled in star. And when unchecked is an empty star. Do I have to use an imageview and do my own logic myself?
Create a drawable checkbox selector:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="#drawable/checkbox"
android:state_checked="false"/>
<item android:drawable="#drawable/checkboxselected"
android:state_checked="true"/>
<item android:drawable="#drawable/checkbox"/>
</selector>
Make sure your checkbox is like this android:button="#drawable/checkbox_selector"
<CheckBox
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:button="#drawable/checkbox_selector"
android:text="CheckBox"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="#color/Black" />
Checkboxes being children of Button you can just give your checkbox a background image with several states as described here, under "Button style":
...and exemplified here:
Copy the btn_check.xml from android-sdk/platforms/android-#/data/res/drawable to your project's drawable folder and change the 'on' and 'off' image states to your custom images.
Then your xml will just need android:button="#drawable/btn_check"
<CheckBox
android:button="#drawable/btn_check"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true" />
If you want to use different default android icons, you can use android:button="#android:drawable/..."
res/drawable/day_selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="#drawable/dayselectionunselected"
android:state_checked="false"/>
<item android:drawable="#drawable/daysselectionselected"
android:state_checked="true"/>
<item android:drawable="#drawable/dayselectionunselected"/>
</selector>
res/layout/my_layout.xml
<CheckBox
android:id="#+id/check"
android:layout_width="39dp"
android:layout_height="39dp"
android:background="#drawable/day_selector"
android:button="#null"
android:gravity="center"
android:text="S"
android:textColor="#color/black"
android:textSize="12sp" />
If you have Android open source code, you can find the styles definition under:
src/frameworks/base/core/res/res/values
<style name="Widget.CompoundButton.CheckBox">
<item name="android:background">
#android:drawable/btn_check_label_background
</item>
<item name="android:button">
?android:attr/listChoiceIndicatorMultiple
</item>
</style>
Based on the Enselic and Rahul answers.
It works for me (before and after API 21):
<CheckBox
android:id="#+id/checkbox"
android:layout_width="40dp"
android:layout_height="40dp"
android:text=""
android:gravity="center"
android:background="#drawable/checkbox_selector"
android:button="#null"
app:buttonCompat="#null" />
Try it -
package com;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;
public class CheckBoxImageView extends ImageView implements View.OnClickListener {
boolean checked;
int defImageRes;
int checkedImageRes;
OnCheckedChangeListener onCheckedChangeListener;
public CheckBoxImageView(Context context, AttributeSet attr, int defStyle) {
super(context, attr, defStyle);
init(attr, defStyle);
}
public CheckBoxImageView(Context context, AttributeSet attr) {
super(context, attr);
init(attr, -1);
}
public CheckBoxImageView(Context context) {
super(context);
}
public boolean isChecked() {
return checked;
}
public void setChecked(boolean checked) {
this.checked = checked;
setImageResource(checked ? checkedImageRes : defImageRes);
}
private void init(AttributeSet attributeSet, int defStyle) {
TypedArray a = null;
if (defStyle != -1)
a = getContext().obtainStyledAttributes(attributeSet, R.styleable.CheckBoxImageView, defStyle, 0);
else
a = getContext().obtainStyledAttributes(attributeSet, R.styleable.CheckBoxImageView);
defImageRes = a.getResourceId(0, 0);
checkedImageRes = a.getResourceId(1, 0);
checked = a.getBoolean(2, false);
a.recycle();
setImageResource(checked ? checkedImageRes : defImageRes);
setOnClickListener(this);
}
#Override
public void onClick(View v) {
checked = !checked;
setImageResource(checked ? checkedImageRes : defImageRes);
onCheckedChangeListener.onCheckedChanged(this, checked);
}
public void setOnCheckedChangeListener(OnCheckedChangeListener onCheckedChangeListener) {
this.onCheckedChangeListener = onCheckedChangeListener;
}
public static interface OnCheckedChangeListener {
void onCheckedChanged(View buttonView, boolean isChecked);
}
}
Add this attrib -
<declare-styleable name="CheckBoxImageView">
<attr name="default_img" format="integer"/>
<attr name="checked_img" format="integer"/>
<attr name="checked" format="boolean"/>
</declare-styleable>
Use like -
<com.adonta.ziva.consumer.wrapper.CheckBoxImageView
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/checkBox"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:clickable="true"
android:padding="5dp"
app:checked_img="#drawable/check_box_checked"
app:default_img="#drawable/check_box" />
It will fix all your porblems.
Another option is to use a ToggleButton with null background and a custom button.
Bellow an example that includes a selector to the text color as well.
<ToggleButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:button="#drawable/toggle_selector"
android:background="#null"
android:paddingLeft="10dp"
android:layout_centerHorizontal="true"
android:gravity="center"
android:textColor="#drawable/toggle_text"
android:textOn="My on state"
android:textOff="My off state" />
toggle_selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_checked="true"
android:drawable="#drawable/state_on" />
<item
android:drawable="#drawable/state_off" />
</selector>
toggle_text.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_checked="true"
android:color="#color/app_color" />
<item
android:color="#android:color/darker_gray" />
</selector>
If you are using custom adapters than android:focusable="false" and android:focusableInTouchMode="false" are nessesury to make list items clickable while using checkbox.
<CheckBox
android:id="#+id/checkbox_fav"
android:focusable="false"
android:focusableInTouchMode="false"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:button="#drawable/checkbox_layout"/>
In drawable>checkbox_layout.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="#drawable/uncked_checkbox"
android:state_checked="false"/>
<item android:drawable="#drawable/selected_checkbox"
android:state_checked="true"/>
<item android:drawable="#drawable/uncked_checkbox"/>
</selector>
If you use androidx.appcompat:appcompat and want a custom drawable (of type selector with android:state_checked) to work on old platform versions in addition to new platform versions, you need to use
<CheckBox
app:buttonCompat="#drawable/..."
instead of
<CheckBox
android:button="#drawable/..."
Adding custom drawable in the android:button did not work for me in Material Checkbox version-1.3.0 . I had to set android:drawable="#drawable/checkbox_selector" instead and also set android:button="#null" . You can also add android:drawablePadding to make it look good. However, this makes the entire checkbox clickable (along with the text).

Categories

Resources