【问题标题】:android RadioButton button drawable gravityandroid RadioButton按钮可绘制重力
【发布时间】:2010-12-10 09:53:01
【问题描述】:

我正在使用

动态生成 RadioButtons
RadioButton radioButton=new RadioButton(context);  

LayoutParams layoutParams=new LayoutParams(radioWidth,radioHeight);
layoutParams.gravity=Gravity.CENTER;

radioButton.setLayoutParams(layoutParams);
radioButton.setGravity(Gravity.CENTER);

BitmapDrawable bitmap = ((BitmapDrawable)drawableResource);
bitmap.setGravity(Gravity.CENTER);

radioButton.setBackgroundDrawable(getResources().getDrawable(R.drawable.itabs_radio));
radioButton.setButtonDrawable(bitmap);

如您所见,我拼命尝试将可绘制按钮的重力设置为居中,但没有理由它始终居中和左对齐,这就是原因 - android 单选按钮的默认样式:

<style name="Widget.CompoundButton">
<item name="android:focusable">true</item> 
<item name="android:clickable">true</item>
<item name="android:textAppearance">?android:attr/textAppearance</item> 
<item name="android:textColor">?android:attr/textColorPrimaryDisableOnly</item> 
<item name="android:gravity">center_vertical|left</item> 
</style>

<style name="Widget.CompoundButton.RadioButton">
<item name="android:background">@android:drawable/btn_radio_label_background</item> 
<item name="android:button">@android:drawable/btn_radio</item> 
</style>

有什么方法可以让可绘制的按钮居中对齐吗?

【问题讨论】:

    标签: android radio-button center drawable


    【解决方案1】:

    根据CompoundButton.onDraw() source code,它始终是左对齐的。

    (注意buttonDrawable.setBounds(0, y, buttonDrawable.getIntrinsicWidth(), y + height);这一行)

    您必须从RadioButton 派生一个新类并覆盖onDraw()

    稍后添加的示例:

    好的,这就是你要做的。首先,这是一个布局:

    <?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>
    

    其次是自定义绘图 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);
                }
            }   
    }
    

    最后,您需要将一个 attrs.xml 文件放入 res/values 中,以便代码可以获取平台定义的属性。

    <?xml version="1.0" encoding="utf-8"?>
    <resources>    
         <declare-styleable name="CompoundButton">
            <attr name="android:button" />
        </declare-styleable>
    </resources>
    

    【讨论】:

    • 非常感谢 Shardul。请允许我指出,您的版本有一个自定义构造函数,没有正确使用属性,因此不能用作 RadioButton 的替代品。没关系。这是我最后一次遇到这种麻烦。
    • 另外,请允许我指出我确实回答了你的问题:你是 RadioButton 的子类。
    • 而不是 android.R.id.empty ,定义透明颜色并改用 R.color.transparent ,否则会抛出 InflateException 但真正的原因是android.content.res.Resources$NotFoundException: File from drawable resource ID #0x1020004
    • setButtonDrawable(android.R.color.transparent);
    • 当使用 compile 'com.android.support:design:23.0.1' a.getDrawable(1); 返回 null。不过,使用 a.getDrawable(R.styleable.CompoundButton_android_button); 对我有用。
    【解决方案2】:

    简单的解决方案,可以给 RadioButton 添加背景,或者设置 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"/>
    

    更新:

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

    【讨论】:

    • 这并不能解决问题 - 收音机的按钮仍会向左对齐
    • 哎呀,感谢您的努力 - 但仍然没有。任务是对齐button 对象,您正在使用drawableTop。查看接受的答案 - 您需要实现自定义 RadioButton 来实现这一点。
    • 很好,这绝对是一个 hack,但它确实有效。我必须有一个单选按钮,只有一个图像没有文本,并且图像需要居中。我刚刚使 textsize = 0 并得到了我所需要的 +1
    【解决方案3】:

    根据@hoot 的回答,我对其进行了自定义,以在不使用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
            )
        }
    }
    

    }

    【讨论】:

      【解决方案4】:

      基于@Reprator 的回答。

      JAVA 版本:

      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();}
        }
      }
      

      【讨论】:

        【解决方案5】:

        我也认为这听起来像是一个错误,因为它总是左对齐。就我而言,我通过设置android:minWidth="0dp"android:layout_width="wrap_content" 解决了这个问题,因为Material 组件已将android:minWidth 设置为大于可绘制宽度的宽度。如果RadioButton 需要居中,则可以将其添加到容器中,因此无需实现自定义视图。

        这是它的外观示例:

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

        但是,请注意,此处设置最小宽度是有原因的,Material design 使用了?attr/minTouchTargetSize。所以如果你喜欢上面的方法,容器也应该是可触摸的。

        【讨论】:

          【解决方案6】:

          &lt;radiogroup android:paddingLeft = "20dp" android:background="@color/gray"&gt;

          基本上 - 我有一个水平对齐的单选组,通过将背景颜色扩展到左侧 20dp(或单选按钮宽度的 1/2),它看起来好像居中。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2015-01-13
            • 2014-07-16
            • 2015-09-05
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-04-12
            相关资源
            最近更新 更多