android RadioButton button drawable gravity

前端 未结 6 1432
再見小時候
再見小時候 2020-12-02 11:20

I am generating RadioButtons dynamically with

RadioButton radioButton=new RadioButton(context);  

LayoutParams layoutParams=new LayoutParams(radioWidth,rad         


        
相关标签:
6条回答
  • 2020-12-02 11:54

    Based on @Reprator answers.

    JAVA version:

    public class RadioButtonCentered extends AppCompatRadioButton {
    
      private Drawable buttonDrawable;
    
    
      public RadioButtonCentered(Context context) {
        super(context);
      }
    
      public RadioButtonCentered(Context context, AttributeSet attrs) {
        super(context, attrs);
      }
    
      public RadioButtonCentered(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
      }
    
    
    
    
      @Override
      protected void onDraw(Canvas canvas) {
          if (buttonDrawable != null) {
            int iconHeight = buttonDrawable.getIntrinsicHeight();
            int buttonWidth = buttonDrawable.getIntrinsicWidth();
            int width = getWidth();
            float totalWidth = buttonWidth + getPaint().measureText(getText().toString()) + getPaddingLeft() + getPaddingRight() + getCompoundDrawablePadding();
    
            if (totalWidth >= width) { super.onDraw(canvas); }
            else {
                int yTop = 0;
                int height = getHeight();
                int availableSpace = (int) ((width - totalWidth) / 2);
                int verticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK;
                int rightWidth = availableSpace + buttonWidth;
    
                switch (verticalGravity) {
                    case Gravity.BOTTOM:
                        yTop = height - iconHeight;
                        break;
                    case Gravity.CENTER_VERTICAL:
                        yTop = (height - iconHeight) / 2;
                        break;
                }
    
                setButtonDrawable(android.R.color.transparent);
                buttonDrawable.setState(getDrawableState());
                buttonDrawable.setBounds(availableSpace, yTop, rightWidth, yTop + iconHeight);
                buttonDrawable.draw(canvas);
    
                float yPos = (height / 2 - (getPaint().descent() + getPaint().ascent()) / 2);
    
                canvas.drawText(getText().toString(), ((float) (rightWidth + getCompoundDrawablePadding())), yPos, getPaint());
            }
        } else {buttonDrawable = CompoundButtonCompat.getButtonDrawable(this); invalidate();}
      }
    }
    
    0 讨论(0)
  • 2020-12-02 12:00

    Simple solution, you can add a background to RadioButton, or set background="@null", .

    <RadioButton
                    android:id="@+id/cp_rd_btn"
                    android:layout_width="0dp"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:background="@null"/>
    

    updated:

    <RadioGroup
                    android:layout_width="fill_parent"
                    android:layout_height="wrap_content"
                    android:orientation="horizontal" >
    
                    <RadioButton
                        android:layout_width="0dp"
                        android:layout_height="wrap_content"
                        android:layout_weight="1"
                        android:background="@null"
                        android:button="@null"
                        android:drawableTop="@drawable/account_coolme_selector"
                        android:gravity="center" />
    
                    <RadioButton
                        android:layout_width="0dp"
                        android:layout_height="fill_parent"
                        android:layout_weight="1"
                        android:background="@null"
                        android:button="@null"
                        android:drawableTop="@drawable/account_qq_selector"
                        android:gravity="center"
                        />
                </RadioGroup>
    
    0 讨论(0)
  • 2020-12-02 12:03

    Based on @hoot answers, I had customised it to make both text and drawable to the center without using attars,

    class RadioButtonCenter(context: Context, attrs: AttributeSet) : RadioButton(context, attrs) {
    internal var buttonDrawable: Drawable? = null
    
    
    init {
        buttonDrawable = CompoundButtonCompat.getButtonDrawable(this@RadioButtonCenter)
    
    }
    
    override fun onDraw(canvas: Canvas) {
        val iconHeight = buttonDrawable!!.intrinsicHeight
        val buttonWidth = buttonDrawable!!.intrinsicWidth
    
        val totalWidth =
            buttonWidth + paint.measureText(text.toString()) + paddingLeft + paddingRight + compoundDrawablePadding
        if (totalWidth >= width) {
            super.onDraw(canvas)
        } else {
            setButtonDrawable(android.R.color.transparent)
    
            val availableSpace = ((width - totalWidth) / 2).toInt()
    
            buttonDrawable!!.state = drawableState
            val height = height
            var yTop = 0
            val verticalGravity = gravity and Gravity.VERTICAL_GRAVITY_MASK
            when (verticalGravity) {
                Gravity.BOTTOM -> yTop = height - iconHeight
                Gravity.CENTER_VERTICAL -> yTop = (height - iconHeight) / 2
            }
            var rightWidth = availableSpace + buttonWidth
    
            buttonDrawable!!.setBounds(availableSpace, yTop, rightWidth, yTop + iconHeight)
            buttonDrawable!!.draw(canvas)
    
            rightWidth += compoundDrawablePadding
    
            val yPos = (height / 2 - (paint.descent() + paint.ascent()) / 2) as Float
            canvas.drawText(
                text.toString(),
                (rightWidth).toFloat(),
                yPos,
                paint
            )
        }
    }
    

    }

    0 讨论(0)
  • 2020-12-02 12:03

    <radiogroup android:paddingLeft = "20dp" android:background="@color/gray">

    Basically - I have a horizontally aligned radio group, and by expanding the background color to the left 20dp (or whatever 1/2 of your width of radio button) it appears as if it's centered.

    0 讨论(0)
  • 2020-12-02 12:06

    According to CompoundButton.onDraw() source code it's always left-aligned.

    (Note the line buttonDrawable.setBounds(0, y, buttonDrawable.getIntrinsicWidth(), y + height);)

    You will have to derive a new class from RadioButton and override onDraw().

    EXAMPLE ADDED LATER:

    Ok, so here's what you do. Firstly, here's a layout:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        >
    <org.test.TestProj.RadioButtonCenter
        android:id="@+id/myview"
        android:layout_width="fill_parent" 
        android:layout_height="100dp" 
        android:layout_centerInParent="true"
        android:text="Button test"
        />
    </RelativeLayout>
    

    Secondly here's the custom-drawing RadioButtonCenter:

    package org.test.TestProj;
    
    import android.content.Context;
    import android.content.res.TypedArray;
    import android.util.AttributeSet;
    import android.view.Gravity;
    import android.widget.RadioButton;
    import android.graphics.Canvas;
    import android.graphics.drawable.Drawable;
    
    public class RadioButtonCenter extends RadioButton {
    
        public RadioButtonCenter(Context context, AttributeSet attrs) {
            super(context, attrs);
            TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CompoundButton, 0, 0);
            buttonDrawable = a.getDrawable(1);
            setButtonDrawable(android.R.color.transparent);
        }
        Drawable buttonDrawable;
    
    
         @Override
            protected void onDraw(Canvas canvas) {
                super.onDraw(canvas);
    
                if (buttonDrawable != null) {
                    buttonDrawable.setState(getDrawableState());
                    final int verticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK;
                    final int height = buttonDrawable.getIntrinsicHeight();
    
                    int y = 0;
    
                    switch (verticalGravity) {
                        case Gravity.BOTTOM:
                            y = getHeight() - height;
                            break;
                        case Gravity.CENTER_VERTICAL:
                            y = (getHeight() - height) / 2;
                            break;
                    }
    
                int buttonWidth = buttonDrawable.getIntrinsicWidth();
                int buttonLeft = (getWidth() - buttonWidth) / 2;
                buttonDrawable.setBounds(buttonLeft, y, buttonLeft+buttonWidth, y + height);
                    buttonDrawable.draw(canvas);
                }
            }   
    }
    

    Finally, here's an attrs.xml file you need to put in res/values so the code can get at platform-defined attributes.

    <?xml version="1.0" encoding="utf-8"?>
    <resources>    
         <declare-styleable name="CompoundButton">
            <attr name="android:button" />
        </declare-styleable>
    </resources>
    
    0 讨论(0)
  • 2020-12-02 12:13

    I also think this sounds like a bug since it's always left-aligned. In my case I solved the issue by setting android:minWidth="0dp" and android:layout_width="wrap_content", since Material components had set the android:minWidth to a width larger than the drawable width. If the RadioButton needs to be centered it can then be added to a container and thus no custom view needs to be implemented.

    Here's an example of how it could look:

    <FrameLayout
        android:layout_width="200dp"
        android:layout_height="200dp">
    
        <RadioButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:clickable="false"
            android:minWidth="0dp" />
    
     </FrameLayout>
    

    However, be aware that the minimum width was set there for a reason, Material design used ?attr/minTouchTargetSize. So if you do like above, the container should maybe also be touchable.

    0 讨论(0)
提交回复
热议问题