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

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

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

《咏柳》

碧玉妆成一树高, 

万条垂下绿丝绦。

不知细叶谁裁出, 

二月春风似剪刀。

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


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

代码效果

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

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


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

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

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图片设置边界,即要显示的大小。

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

setCompoundDrawablesWithIntrinsicBounds(drawableLeft, drawableTop, drawableRight, drawableBottom);
进入源码查看该方法的具体实现:

public void setCompoundDrawablesWithIntrinsicBounds(Drawable left, Drawable top,
            Drawable right, Drawable bottom) {

        if (left != null) {
            left.setBounds(0, 0, left.getIntrinsicWidth(), left.getIntrinsicHeight());
        }
        if (right != null) {
            right.setBounds(0, 0, right.getIntrinsicWidth(), right.getIntrinsicHeight());
        }
        if (top != null) {
            top.setBounds(0, 0, top.getIntrinsicWidth(), top.getIntrinsicHeight());
        }
        if (bottom != null) {
            bottom.setBounds(0, 0, bottom.getIntrinsicWidth(), bottom.getIntrinsicHeight());
        }
        setCompoundDrawables(left, top, right, bottom);
    }
原来这个方法,同样调用了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文件的内容为:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    
    <declare-styleable name="MyRadioButton">
        
        <attr name="drawableSize" format="dimension"/>
        <attr name="drawableTop" format="reference"/>
        <attr name="drawableLeft" format="reference"/>
        <attr name="drawableRight" format="reference"/>
        <attr name="drawableBottom" format="reference"/>
        
    </declare-styleable>
    
</resources>


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

获取属性的代码如下:

Drawable drawableLeft = null, drawableTop = null, drawableRight = null, drawableBottom = null;
		TypedArray a = context.obtainStyledAttributes(attrs,
				R.styleable.MyRadioButton);

		int n = a.getIndexCount();
		for (int i = 0; i < n; i++) {
			int attr = a.getIndex(i);
			Log.i("MyRadioButton", "attr:" + attr);
			switch (attr) {
			case R.styleable.MyRadioButton_drawableSize:
				mDrawableSize = a.getDimensionPixelSize(R.styleable.MyRadioButton_drawableSize, 50);
				Log.i("MyRadioButton", "mDrawableSize:" + mDrawableSize);
				break;
			case R.styleable.MyRadioButton_drawableTop:
				drawableTop = a.getDrawable(attr);
				break;
			case R.styleable.MyRadioButton_drawableBottom:
				drawableRight = a.getDrawable(attr);
				break;
			case R.styleable.MyRadioButton_drawableRight:
				drawableBottom = a.getDrawable(attr);
				break;
			case R.styleable.MyRadioButton_drawableLeft:
				drawableLeft = a.getDrawable(attr);
				break;
			default :
					break;
			}
		}
		a.recycle();

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

public void setCompoundDrawablesWithIntrinsicBounds(Drawable left,
			Drawable top, Drawable right, Drawable bottom) {

		if (left != null) {
			left.setBounds(0, 0, mDrawableSize, mDrawableSize);
		}
		if (right != null) {
			right.setBounds(0, 0, mDrawableSize, mDrawableSize);
		}
		if (top != null) {
			top.setBounds(0, 0, mDrawableSize, mDrawableSize);
		}
		if (bottom != null) {
			bottom.setBounds(0, 0, mDrawableSize, mDrawableSize);
		}
		setCompoundDrawables(left, top, right, bottom);
	}

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

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

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

xml布局如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:myradio="http://schemas.android.com/apk/res/com.example.test"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical" >

        <FrameLayout
            android:id="@+id/tab_content"
            android:layout_width="fill_parent"
            android:layout_height="0dp"
            android:layout_weight="1.0"
            android:background="#FFFFFF" />
        
        

        <RadioGroup
            android:id="@+id/rgs"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/whiet"
            android:gravity="center"
          
            android:orientation="horizontal" >

            
            <com.example.test.MyRadioButton
                android:id="@+id/tab_a"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:layout_marginLeft="10dp"
                android:layout_marginRight="10dp"
                android:background="@color/whiet"
                android:button="@null"
                android:clickable="true"
                
                myradio:drawableTop="@drawable/shouye_radiobutton"
                myradio:drawableSize="20dp"
                
                
                android:gravity="center"
                android:text="首页"
                android:textSize="13sp" />

            <com.example.test.MyRadioButton
                android:id="@+id/tab_b"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:background="@color/whiet"
                android:layout_marginLeft="10dp"
                android:layout_marginRight="10dp"
                android:button="@null"
                android:checked="true"
                android:clickable="true"
                
                myradio:drawableTop="@drawable/fenlei_radiobutton"
                myradio:drawableSize="30dp"
                
                android:gravity="center"
                android:text="分类"
                android:textSize="13sp" />

            <RadioButton
                android:id="@+id/tab_c"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginBottom="10dp"
                android:background="@color/whiet"
                android:button="@null"
                android:drawableTop="@drawable/gouwuche_bg"
                android:gravity="center"
                android:paddingTop="10dip" />

            <RadioButton
                android:id="@+id/tab_d"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:layout_marginLeft="10dp"
                android:layout_marginRight="10dp"
                android:background="@color/whiet"
                android:button="@null"
                android:drawableTop="@drawable/faxian_radiobutton"
                android:gravity="center"
                android:text="发现"
                android:textSize="13sp" />

            <RadioButton
                android:id="@+id/tab_e"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:background="@color/whiet"
                android:layout_marginLeft="10dp"
                android:layout_marginRight="10dp"
                android:button="@null"
                android:drawableTop="@drawable/wode_radiobutton"
                android:gravity="center"
                android:text="我的"
                
                android:textSize="13sp" />
        </RadioGroup>
    </LinearLayout>

</RelativeLayout>

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

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

package com.example.test;

import android.R.integer;
import android.R.raw;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.RadioButton;

public class MyRadioButton extends RadioButton {

	private int mDrawableSize;// xml文件中设置的大小

	public MyRadioButton(Context context) {
		this(context, null, 0);
	}

	public MyRadioButton(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
	}

	public MyRadioButton(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		// TODO Auto-generated constructor stub
		Drawable drawableLeft = null, drawableTop = null, drawableRight = null, drawableBottom = null;
		TypedArray a = context.obtainStyledAttributes(attrs,
				R.styleable.MyRadioButton);

		int n = a.getIndexCount();
		for (int i = 0; i < n; i++) {
			int attr = a.getIndex(i);
			Log.i("MyRadioButton", "attr:" + attr);
			switch (attr) {
			case R.styleable.MyRadioButton_drawableSize:
				mDrawableSize = a.getDimensionPixelSize(R.styleable.MyRadioButton_drawableSize, 50);
				Log.i("MyRadioButton", "mDrawableSize:" + mDrawableSize);
				break;
			case R.styleable.MyRadioButton_drawableTop:
				drawableTop = a.getDrawable(attr);
				break;
			case R.styleable.MyRadioButton_drawableBottom:
				drawableRight = a.getDrawable(attr);
				break;
			case R.styleable.MyRadioButton_drawableRight:
				drawableBottom = a.getDrawable(attr);
				break;
			case R.styleable.MyRadioButton_drawableLeft:
				drawableLeft = a.getDrawable(attr);
				break;
			default :
					break;
			}
		}
		a.recycle();
		
		setCompoundDrawablesWithIntrinsicBounds(drawableLeft, drawableTop, drawableRight, drawableBottom);

	}

	public void setCompoundDrawablesWithIntrinsicBounds(Drawable left,
			Drawable top, Drawable right, Drawable bottom) {

		if (left != null) {
			left.setBounds(0, 0, mDrawableSize, mDrawableSize);
		}
		if (right != null) {
			right.setBounds(0, 0, mDrawableSize, mDrawableSize);
		}
		if (top != null) {
			top.setBounds(0, 0, mDrawableSize, mDrawableSize);
		}
		if (bottom != null) {
			bottom.setBounds(0, 0, mDrawableSize, mDrawableSize);
		}
		setCompoundDrawables(left, top, right, bottom);
	}

}


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

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


源码下载地址

转载请注明出处



你可能感兴趣的:(Android 自定义RadioButton 实现文字上下左右方向的图片大小设置)