Center CheckBox drawable within itself

你。 提交于 2019-12-02 20:12:54

I believe the problem is that the Checkbox widget uses a regular TextView with the drawableLeft attribute, because it expects text to be shown as well. (This is why you see it centered vertically, but offset slightly to the left.)

If you simply want an image button with multiple states, I suggest using a ToggleButton with your custom images in a state list selector. Or you could create a custom class that extends ImageView and implements Checkable.

You can use a parent layout to achieve this :

<LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:gravity="center">

    <CheckBox
        android:id="@+id/checkbox_star"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="Check box text" />
</LinearLayout>

This align problem can be solved by CheckableImageView, a custom View that extend ImageView or AppCompatImageView and implement Checkable directly. It also have other ImageView attributes.

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.Checkable;
import android.widget.ImageView;

/**
 * @author hendrawd on 6/23/16
 */
public class CheckableImageView extends ImageView implements Checkable {

    public CheckableImageView(Context context) {
        super(context);
    }

    public CheckableImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    private boolean mChecked = false;

    private static final int[] CHECKED_STATE_SET = {android.R.attr.state_checked};

    @Override
    public int[] onCreateDrawableState(final int extraSpace) {
        final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
        if (isChecked())
            mergeDrawableStates(drawableState, CHECKED_STATE_SET);
        return drawableState;
    }

    @Override
    public void setChecked(boolean checked) {
        if (mChecked != checked) {
            mChecked = checked;
            refreshDrawableState();
        }
    }

    @Override
    public boolean isChecked() {
        return mChecked;
    }

    @Override
    public void toggle() {
        setChecked(!mChecked);
    }

    @Override
    public void setOnClickListener(final OnClickListener l) {
        View.OnClickListener onClickListener = new OnClickListener() {
            @Override
            public void onClick(View v) {
                toggle();
                l.onClick(v);
            }
        };
        super.setOnClickListener(onClickListener);
    }
}

Just set your selector drawable in src property of your XML and the drawable state of check will follow automatically.

Example of use

<your.package.name.CheckableImageView
    android:id="@+id/some_id"
    android:layout_width="48dp"
    android:layout_height="48dp"
    android:src="@drawable/set_your_selector_here"
    android:padding="14dp"
    android:gravity="center" />

Selector example(put inside drawable folder with extension .xml)

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/ic_cb_check" android:state_checked="true" android:state_focused="true" />
    <item android:drawable="@drawable/ic_cb_uncheck" android:state_checked="false" android:state_focused="true" />
    <item android:drawable="@drawable/ic_cb_uncheck" android:state_checked="false" />
    <item android:drawable="@drawable/ic_cb_check" android:state_checked="true" />
</selector>

Change ic_cb_check and ic_cb_uncheck with your preferred images.

This code also available at https://gist.github.com/hendrawd/661824a721c22b3244667379e9358b5f

j__m
android:button="@null"
android:foreground="@drawable/btn_favorite" 
android:foregroundGravity="center"

This will work correct as need required. Just small changes in background and button attributes. This code snippet is tested successfully. Hope this helps.

 <CheckBox
android:id="@+id/checkbox_star"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="@drawable/btn_favorite"
android:button="@color/transparent"
android:layout_gravity="center"
android:minWidth="48dp" />

The only proper solution is to add insets to the image. Most of the solutions with "foreground" won't work below API 23.

btn_favorite_inset.xml in drawable dir

<inset xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/btn_favorite"
    android:insetLeft="6dp"
    android:insetTop="6dp"
    android:insetRight="6dp"
    android:insetBottom="6dp" />

Your layout file

<CheckBox
    android:id="@+id/checkbox_star"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:button="@drawable/btn_favorite_inset"
    android:layout_gravity="center"
    android:minWidth="48dp" />

Do not use this code to bypass checkbox bug with center aligment for >SDK23 if you are going to use checkboxes in recyclerview.

<CheckBox
android:button="@null"
android:drawableLeft="@drawable/checkbox_selector"
android:drawableStart="@drawable/checkbox_selector"
/>

Checkboxes will not get checked in onBindViewHolder until next refresh if RV (example: scroll,..).

David Kranitz

Set the android:width so that it only shows your checkbox, then center it using android:layout_gravity="center".

Just use following approach:

          <CheckBox
                  android:button="@null"                        
                  android:foreground="@drawable/checkbox_selector"
                  android:foregroundGravity="center"/>

It works well for me. But it works only for

targetSdkVersion >= Build.VERSION_CODES.M || view instanceof FrameLayout

I have tried j__m's answer above, and it works, but not good enough.

In my case, I wanted to add paddings around the CheckBox's drawable, in order to increase the touch area. And j__m's answer makes it hard to adjust the UI.

I think a better solution is to create an inset drawable to wrap your original state drawable, which should be very easy and work perfectly.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!