Center CheckBox drawable within itself

大憨熊 提交于 2019-12-03 06:22:58

问题


I have a CheckBox that I want centered within its own boundaries, not pushed to the side. Probably easier demonstrated than explained:

Note that it isn't centered. Currently defined as:

<CheckBox
    android:id="@+id/checkbox_star"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:button="@drawable/btn_favorite"

    android:layout_gravity="center"
    android:minWidth="48dp" />

Nevermind the custom button drawable. It behaves the same with a vanilla CheckBox as well (the small check box behaves the same).


回答1:


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.




回答2:


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>



回答3:


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




回答4:


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



回答5:


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" />



回答6:


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" />



回答7:


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




回答8:


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,..).




回答9:


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




回答10:


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.



来源:https://stackoverflow.com/questions/13411288/center-checkbox-drawable-within-itself

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