重写Button实现图片drawableTop和文字一起居中

很多情况下,我们需要这样的Button。


当然是可以通过建立一个LinearLayout来摆放一个ImageView和TextView来实现。这里就不说这种方法了。
还有一个实现方法是通过下面标签实现:
android:drawableLeft,
android:drawableRight,
android:drawableTop,
android:drawableBottom;

可是通过上面的标签来实现的话,图片会被贴着边缘摆放,如下图,这样没办法跟文字一起居中。



这里我们可以通过重写Button的onDraw(Canvas canvas) 方法,把图片和文字一起居中。

public class DrawableHorizontalButton extends Button {

	public DrawableHorizontalButton(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	@Override
	protected void onDraw(Canvas canvas) {
		canvas = getTopCanvas(canvas);
		super.onDraw(canvas);
	}

	private Canvas getTopCanvas(Canvas canvas) {
		Drawable[] drawables = getCompoundDrawables();
		if (drawables == null) {
			return canvas;
		}
		Drawable drawable = drawables[0];// 左面的drawable
		if (drawable == null) {
			drawable = drawables[2];// 右面的drawable
		}

		// float textSize = getPaint().getTextSize(); // 使用这个会导致文字竖向排下来
		float textSize = getPaint().measureText(getText().toString());
		int drawWidth = drawable.getIntrinsicWidth();
		int drawPadding = getCompoundDrawablePadding();
		float contentWidth = textSize + drawWidth + drawPadding;
		int leftPadding = (int) (getWidth() - contentWidth);
		setPadding(0, 0, leftPadding, 0); // 直接贴到左边
		float dx = (getWidth() - contentWidth) / 2;
		canvas.translate(dx, 0);// 往右移动
		return canvas;
	}
}

布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <com.example.view.DrawableHorizontalButton
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:drawableLeft="@drawable/ic_android_small"
        android:includeFontPadding="false"
        android:text="@string/hello_world"
        android:textSize="20sp" />
    
    <com.example.view.DrawableHorizontalButton
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:drawableRight="@drawable/ic_android_small"
        android:includeFontPadding="false"
        android:text="@string/hello_world"
        android:textSize="20sp" />

</LinearLayout>

运行上面的代码可以看到效果图:


很好,就是这样已经居中了。这里说一下实现原理。就是通过setPadding(int left, int top, int right, int bottom)方法把文字移动到边缘与图片挨起来,然后使用canvas.translate(float dx, float dy)把图片和文字一同移动到控件的中间。实现一起居中效果;


同理我们可以在实现上下型的居中:

代码如下:

public class DrawableVerticalButton extends Button {

	public DrawableVerticalButton(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	@Override
	protected void onDraw(Canvas canvas) {
		canvas = getTopCanvas(canvas);
		super.onDraw(canvas);
	}

	private Canvas getTopCanvas(Canvas canvas) {
		Drawable[] drawables = getCompoundDrawables();
		if (drawables == null) {
			return canvas;
		}
		Drawable drawable = drawables[1];// 上面的drawable
		if(drawable == null){
			drawable = drawables[3];// 下面的drawable
		}
		
		float textSize = getPaint().getTextSize();
		int drawHeight = drawable.getIntrinsicHeight();
		int drawPadding = getCompoundDrawablePadding();
		float contentHeight = textSize + drawHeight + drawPadding;
		int topPadding = (int) (getHeight() - contentHeight);
		setPadding(0, topPadding , 0, 0);
		float dy = (contentHeight - getHeight())/2;
		canvas.translate(0, dy);
		Log.i("DrawableTopButton", "setPadding(0,"+topPadding+",0,0");
		Log.i("DrawableTopButton", "translate(0,"+dy+")");
		return canvas;
	}

}
布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <com.example.view.DrawableVerticalButton
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:drawableBottom="@drawable/ic_android_small"
        android:includeFontPadding="false"
        android:text="@string/hello_world"
        android:textSize="20sp" />
    
    <com.example.view.DrawableVerticalButton
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:drawableTop="@drawable/ic_android_small"
        android:includeFontPadding="false"
        android:text="@string/hello_world"
        android:textSize="20sp" />

</LinearLayout>
运行或者直接预览可以看到效果图如下:

上下和左右方向的实现原理都是一样的,都是把文字移动到边缘,然后文字和图片一同移动到中间,所以上下方向的代码是一样的。左右的方法是一样的。于是就是分开来写。大部分情况下我们都是使用上下方向的。

关于自定义控件时重写draw还是重写onDraw呢,Android官方推荐重写的话使用onDraw接口。
“When implementing a view, do not override this method; instead, you should implement onDraw”

来自CSDN博客:http://blog.csdn.net/dreamintheworld/article/details/45243663


  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值