Android 自定义RadioButton 实现文字上下左右方向的图片大小设置

好久没有更新博客,写这篇技术时,感觉很多东西生疏了好多。于是心有感慨:我们做技术的,要是长时间不搞技术,那就是被技术搞!所以攻守之间,大家谨慎思量。

冬天已过,放假出去玩耍时,看到两旁嫩嫩的树叶,想起贺知章的诗句: 

《咏柳》

碧玉妆成一树高, 

万条垂下绿丝绦。

不知细叶谁裁出, 

二月春风似剪刀。

犹自感叹,春天来了,美腿还会远么


好了,闲言少叙,言归正传。

代码效果


前两天一个朋友提出的需求,用RadioButton实现的应用页面切换。效果图如下


这种想法很好,但也出现了两个问题:其一,界面扩展性很差;其二,RadioButton设置图片后,无法在xml中设置图片大小,导致布局不美观。那么问题来了?如何设置这个图片的大小。

百度常见的回答是,在代码中动态设置图片大小。然后设置在布局上。代码如下:

[java]  view plain copy
  1. mRadioButton.setCompoundDrawables(left, top, right, bottom);  
 参数类型都是Drawable,分别是左,上,右,下四个方向要显示的Drawable图片我们查看setCompoundDrawables(left, top, right, bottom)方法:有这样的一段说明:

Sets the Drawables (if any) to appear to the left of, above, to the right of, and below the text. Use null if you do not want a Drawable there. The Drawables must already have hadDrawable.setBounds called.

意思是说,用次方法之前,需要用Drawable.setBounds()方法来为Drawable图片设置边界,即要显示的大小。

达到同样效果的还有一个方法:

[java]  view plain copy
  1. setCompoundDrawablesWithIntrinsicBounds(drawableLeft, drawableTop, drawableRight, drawableBottom);  
进入源码查看该方法的具体实现:

[java]  view plain copy
  1. public void setCompoundDrawablesWithIntrinsicBounds(Drawable left, Drawable top,  
  2.             Drawable right, Drawable bottom) {  
  3.   
  4.         if (left != null) {  
  5.             left.setBounds(00, left.getIntrinsicWidth(), left.getIntrinsicHeight());  
  6.         }  
  7.         if (right != null) {  
  8.             right.setBounds(00, right.getIntrinsicWidth(), right.getIntrinsicHeight());  
  9.         }  
  10.         if (top != null) {  
  11.             top.setBounds(00, top.getIntrinsicWidth(), top.getIntrinsicHeight());  
  12.         }  
  13.         if (bottom != null) {  
  14.             bottom.setBounds(00, bottom.getIntrinsicWidth(), bottom.getIntrinsicHeight());  
  15.         }  
  16.         setCompoundDrawables(left, top, right, bottom);  
  17.     }  
 原来这个方法,同样调用了setCompoundDrawables(left, top, right, bottom)方法,并在调用之前,给传入的图片设置了边界范围,即图片自身的大小。再看这个方法的注释:

Sets the Drawables (if any) to appear to the left of, above, to the right of, and below the text. Use null if you do not want a Drawable there. The Drawables' bounds will be set to their intrinsic bounds.

意思是说:设置drawable图像显示在文字的上下左右的位置,如果不想设置,则传递null参数。drawable图片的边界是其自身固定的边界范围。

OK,一切明了,那么是不是我们自己改变这个边界值参数,就能达到改变图片大小的目的呢?答案是肯定的。下面,是见证奇迹的时刻。
首先,我们要在xml中用到设置图片大小的属性,这里用drawableSize来显示。然后分别给出四个方向的图片属性。最后我们得到的attrs.xml文件的内容为:

[html]  view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <resources>  
  3.       
  4.     <declare-styleable name="MyRadioButton">  
  5.           
  6.         <attr name="drawableSize" format="dimension"/>  
  7.         <attr name="drawableTop" format="reference"/>  
  8.         <attr name="drawableLeft" format="reference"/>  
  9.         <attr name="drawableRight" format="reference"/>  
  10.         <attr name="drawableBottom" format="reference"/>  
  11.           
  12.     </declare-styleable>  
  13.       
  14. </resources>  

规定了属性后,我们需要在代码中获取到这些属性,从而来在视图中显示我们需要的情况。

获取属性的代码如下:

[java]  view plain copy
  1. Drawable drawableLeft = null, drawableTop = null, drawableRight = null, drawableBottom = null;  
  2.         TypedArray a = context.obtainStyledAttributes(attrs,  
  3.                 R.styleable.MyRadioButton);  
  4.   
  5.         int n = a.getIndexCount();  
  6.         for (int i = 0; i < n; i++) {  
  7.             int attr = a.getIndex(i);  
  8.             Log.i("MyRadioButton""attr:" + attr);  
  9.             switch (attr) {  
  10.             case R.styleable.MyRadioButton_drawableSize:  
  11.                 mDrawableSize = a.getDimensionPixelSize(R.styleable.MyRadioButton_drawableSize, 50);  
  12.                 Log.i("MyRadioButton""mDrawableSize:" + mDrawableSize);  
  13.                 break;  
  14.             case R.styleable.MyRadioButton_drawableTop:  
  15.                 drawableTop = a.getDrawable(attr);  
  16.                 break;  
  17.             case R.styleable.MyRadioButton_drawableBottom:  
  18.                 drawableRight = a.getDrawable(attr);  
  19.                 break;  
  20.             case R.styleable.MyRadioButton_drawableRight:  
  21.                 drawableBottom = a.getDrawable(attr);  
  22.                 break;  
  23.             case R.styleable.MyRadioButton_drawableLeft:  
  24.                 drawableLeft = a.getDrawable(attr);  
  25.                 break;  
  26.             default :  
  27.                     break;  
  28.             }  
  29.         }  
  30.         a.recycle();  

好了,这里我们已经获取到设置的图片,以及需要图片显示的大小drawableSize。接下来重写setCompoundDrawablesWithIntrinsicBounds方法。将我们需要的图片大小设置给图片。

[java]  view plain copy
  1. public void setCompoundDrawablesWithIntrinsicBounds(Drawable left,  
  2.             Drawable top, Drawable right, Drawable bottom) {  
  3.   
  4.         if (left != null) {  
  5.             left.setBounds(00, mDrawableSize, mDrawableSize);  
  6.         }  
  7.         if (right != null) {  
  8.             right.setBounds(00, mDrawableSize, mDrawableSize);  
  9.         }  
  10.         if (top != null) {  
  11.             top.setBounds(00, mDrawableSize, mDrawableSize);  
  12.         }  
  13.         if (bottom != null) {  
  14.             bottom.setBounds(00, mDrawableSize, mDrawableSize);  
  15.         }  
  16.         setCompoundDrawables(left, top, right, bottom);  
  17.     }  

设置给图片后,不要忘了调用setCompoundDrawables(left, top, right, bottom)方法,我们要在视图中显示图片。这个方法的内容感兴趣的可以自己查阅源码。

到此,我们代码部分已经编写完毕。

接下来添加需要的图片资源以及xml布局设置。

xml布局如下:

[html]  view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     xmlns:myradio="http://schemas.android.com/apk/res/com.example.test"  
  4.     android:layout_width="match_parent"  
  5.     android:layout_height="match_parent" >  
  6.   
  7.     <LinearLayout  
  8.         android:layout_width="fill_parent"  
  9.         android:layout_height="fill_parent"  
  10.         android:orientation="vertical" >  
  11.   
  12.         <FrameLayout  
  13.             android:id="@+id/tab_content"  
  14.             android:layout_width="fill_parent"  
  15.             android:layout_height="0dp"  
  16.             android:layout_weight="1.0"  
  17.             android:background="#FFFFFF" />  
  18.           
  19.           
  20.   
  21.         <RadioGroup  
  22.             android:id="@+id/rgs"  
  23.             android:layout_width="match_parent"  
  24.             android:layout_height="wrap_content"  
  25.             android:background="@color/whiet"  
  26.             android:gravity="center"  
  27.             
  28.             android:orientation="horizontal" >  
  29.   
  30.               
  31.             <com.example.test.MyRadioButton  
  32.                 android:id="@+id/tab_a"  
  33.                 android:layout_width="0dp"  
  34.                 android:layout_height="wrap_content"  
  35.                 android:layout_weight="1"  
  36.                 android:layout_marginLeft="10dp"  
  37.                 android:layout_marginRight="10dp"  
  38.                 android:background="@color/whiet"  
  39.                 android:button="@null"  
  40.                 android:clickable="true"  
  41.                   
  42.                 myradio:drawableTop="@drawable/shouye_radiobutton"  
  43.                 myradio:drawableSize="20dp"  
  44.                   
  45.                   
  46.                 android:gravity="center"  
  47.                 android:text="首页"  
  48.                 android:textSize="13sp" />  
  49.   
  50.             <com.example.test.MyRadioButton  
  51.                 android:id="@+id/tab_b"  
  52.                 android:layout_width="0dp"  
  53.                 android:layout_height="wrap_content"  
  54.                 android:layout_weight="1"  
  55.                 android:background="@color/whiet"  
  56.                 android:layout_marginLeft="10dp"  
  57.                 android:layout_marginRight="10dp"  
  58.                 android:button="@null"  
  59.                 android:checked="true"  
  60.                 android:clickable="true"  
  61.                   
  62.                 myradio:drawableTop="@drawable/fenlei_radiobutton"  
  63.                 myradio:drawableSize="30dp"  
  64.                   
  65.                 android:gravity="center"  
  66.                 android:text="分类"  
  67.                 android:textSize="13sp" />  
  68.   
  69.             <RadioButton  
  70.                 android:id="@+id/tab_c"  
  71.                 android:layout_width="wrap_content"  
  72.                 android:layout_height="wrap_content"  
  73.                 android:layout_marginBottom="10dp"  
  74.                 android:background="@color/whiet"  
  75.                 android:button="@null"  
  76.                 android:drawableTop="@drawable/gouwuche_bg"  
  77.                 android:gravity="center"  
  78.                 android:paddingTop="10dip" />  
  79.   
  80.             <RadioButton  
  81.                 android:id="@+id/tab_d"  
  82.                 android:layout_width="0dp"  
  83.                 android:layout_height="wrap_content"  
  84.                 android:layout_weight="1"  
  85.                 android:layout_marginLeft="10dp"  
  86.                 android:layout_marginRight="10dp"  
  87.                 android:background="@color/whiet"  
  88.                 android:button="@null"  
  89.                 android:drawableTop="@drawable/faxian_radiobutton"  
  90.                 android:gravity="center"  
  91.                 android:text="发现"  
  92.                 android:textSize="13sp" />  
  93.   
  94.             <RadioButton  
  95.                 android:id="@+id/tab_e"  
  96.                 android:layout_width="0dp"  
  97.                 android:layout_height="wrap_content"  
  98.                 android:layout_weight="1"  
  99.                 android:background="@color/whiet"  
  100.                 android:layout_marginLeft="10dp"  
  101.                 android:layout_marginRight="10dp"  
  102.                 android:button="@null"  
  103.                 android:drawableTop="@drawable/wode_radiobutton"  
  104.                 android:gravity="center"  
  105.                 android:text="我的"  
  106.                   
  107.                 android:textSize="13sp" />  
  108.         </RadioGroup>  
  109.     </LinearLayout>  
  110.   
  111. </RelativeLayout>  

其中,头两个RadioButton用了自定义的。另外的是系统的,用来做对比。不要忘了用自定义属性时的命名空间和自定义的RadioButton的可点击属性。android:clickable="true"。

自定义RadioButton的完整源码如下:

[java]  view plain copy
  1. package com.example.test;  
  2.   
  3. import android.R.integer;  
  4. import android.R.raw;  
  5. import android.content.Context;  
  6. import android.content.res.Resources;  
  7. import android.content.res.TypedArray;  
  8. import android.graphics.drawable.Drawable;  
  9. import android.util.AttributeSet;  
  10. import android.util.Log;  
  11. import android.widget.RadioButton;  
  12.   
  13. public class MyRadioButton extends RadioButton {  
  14.   
  15.     private int mDrawableSize;// xml文件中设置的大小  
  16.   
  17.     public MyRadioButton(Context context) {  
  18.         this(context, null0);  
  19.     }  
  20.   
  21.     public MyRadioButton(Context context, AttributeSet attrs) {  
  22.         this(context, attrs, 0);  
  23.     }  
  24.   
  25.     public MyRadioButton(Context context, AttributeSet attrs, int defStyle) {  
  26.         super(context, attrs, defStyle);  
  27.         // TODO Auto-generated constructor stub  
  28.         Drawable drawableLeft = null, drawableTop = null, drawableRight = null, drawableBottom = null;  
  29.         TypedArray a = context.obtainStyledAttributes(attrs,  
  30.                 R.styleable.MyRadioButton);  
  31.   
  32.         int n = a.getIndexCount();  
  33.         for (int i = 0; i < n; i++) {  
  34.             int attr = a.getIndex(i);  
  35.             Log.i("MyRadioButton""attr:" + attr);  
  36.             switch (attr) {  
  37.             case R.styleable.MyRadioButton_drawableSize:  
  38.                 mDrawableSize = a.getDimensionPixelSize(R.styleable.MyRadioButton_drawableSize, 50);  
  39.                 Log.i("MyRadioButton""mDrawableSize:" + mDrawableSize);  
  40.                 break;  
  41.             case R.styleable.MyRadioButton_drawableTop:  
  42.                 drawableTop = a.getDrawable(attr);  
  43.                 break;  
  44.             case R.styleable.MyRadioButton_drawableBottom:  
  45.                 drawableRight = a.getDrawable(attr);  
  46.                 break;  
  47.             case R.styleable.MyRadioButton_drawableRight:  
  48.                 drawableBottom = a.getDrawable(attr);  
  49.                 break;  
  50.             case R.styleable.MyRadioButton_drawableLeft:  
  51.                 drawableLeft = a.getDrawable(attr);  
  52.                 break;  
  53.             default :  
  54.                     break;  
  55.             }  
  56.         }  
  57.         a.recycle();  
  58.           
  59.         setCompoundDrawablesWithIntrinsicBounds(drawableLeft, drawableTop, drawableRight, drawableBottom);  
  60.   
  61.     }  
  62.   
  63.     public void setCompoundDrawablesWithIntrinsicBounds(Drawable left,  
  64.             Drawable top, Drawable right, Drawable bottom) {  
  65.   
  66.         if (left != null) {  
  67.             left.setBounds(00, mDrawableSize, mDrawableSize);  
  68.         }  
  69.         if (right != null) {  
  70.             right.setBounds(00, mDrawableSize, mDrawableSize);  
  71.         }  
  72.         if (top != null) {  
  73.             top.setBounds(00, mDrawableSize, mDrawableSize);  
  74.         }  
  75.         if (bottom != null) {  
  76.             bottom.setBounds(00, mDrawableSize, mDrawableSize);  
  77.         }  
  78.         setCompoundDrawables(left, top, right, bottom);  
  79.     }  
  80.   
  81. }  

代码很简单,就没有写注释。解释的内容都在文中了。

至此自定义改变Drawable图片大小的RadioButton已经完成。经此一役,我们可以定义任何想要的东东。没有做不到,只有想不到。


源码下载地址

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值