自定义图文并茂的Button

系统 2030 0
anroid内置了Button和ImageButton,但是没有提供既能显示图片又能显示文字的button。
这里我自定义了一个ImageTextButton
其中了XML文件中使用了自定义属性custom:icon="@drawable/icon"
下面是ImageTextButton源码:
    
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.widget.Button;

public class ImageTextButton extends Button {
	private final String namespace =  "http://www.iteye.com/custom";
	private int resourceId =0;
	private Bitmap bitmap;
	public ImageTextButton(Context context, AttributeSet attrs) {
		super(context, attrs);
		// TODO Auto-generated constructor stub
		setClickable(true);
		//默认使用R.drawable.icon这张图片
		resourceId = attrs.getAttributeResourceValue(namespace, "icon", R.drawable.icon);
		bitmap = BitmapFactory.decodeResource(getResources(), resourceId);
	}
	@Override
	protected void onDraw(Canvas canvas) {
		// TODO Auto-generated method stub
		//图片顶部居中显示
		int x=(this.getMeasuredWidth()-bitmap.getWidth())>>1;
		int y=0;
        canvas.drawBitmap(bitmap, x, y, null); 
        //坐标需要转换,因为默认情况下Button中的文字居中显示
        //这里需要让文字在底部显示
		canvas.translate(0, (this.getMeasuredHeight()>>1)-(int)this.getTextSize());
		
		super.onDraw(canvas);
	}

    public void setIcon(Bitmap bitmap){
		this.bitmap=bitmap;
                invalidate();
	}
    public void setIcon(int resourceId){
		this.bitmap=BitmapFactory.decodeResource(getResources(), resourceId);
                invalidate();
	}
}

  


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

    <com.wt.app.ImageTextButton 
    android:text="OK"
    custom:icon="@drawable/icon"
    android:id="@+id/button_0" 
	android:layout_width="80dip" 
	android:layout_height="80dip"
    />
    <com.wt.app.ImageTextButton 
    android:text="OK"
    custom:icon="@drawable/icon"
    android:id="@+id/button_1" 
	android:layout_width="80dip" 
	android:layout_height="100dip"
	android:textSize="30dip"
	android:textColor="#ff0000"
    />
    
    <com.wt.app.ImageTextButton 
    android:text="OK"
    custom:icon="@drawable/icon"
    android:id="@+id/button_2" 
	android:layout_width="200dip" 
	android:layout_height="200dip"
	android:textSize="30dip"
    />
   
</LinearLayout>


  

自定义图文并茂的Button


另一种实现:
    
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.view.MotionEvent;
import android.view.View;
 
public class ImageTextButton extends View{
 
private final static int WIDTH_PADDING = 8;
private final static int HEIGHT_PADDING = 10;
private final static int SPACE = 10;
private final String label;
private final int imageResId;
private final Bitmap image;
private int fontWidth;
private int fontHeight;
 
public ImageTextButton(final Context c,int rid,String text){
super(c);
this.label = text;
this.imageResId = rid;
this.image = BitmapFactory.decodeResource(c.getResources(),imageResId);
setFocusable(true);
setClickable(true);
getFontWidthAndHeight();
}
 
private void getFontWidthAndHeight(){
Paint pFont = new Paint(); 
Rect rect = new Rect(); 
pFont.getTextBounds("信 ", 0, 1, rect); 
this.fontHeight = rect.height();
this.fontWidth = rect.width();
}
 
private int getTextWidth(String text){
return text.length()*this.fontWidth;
}
 
@Override
protected void onFocusChanged(boolean gainFocus, int direction,
Rect previouslyFocusedRect) {
if (gainFocus == true){
this.setBackgroundColor(Color.rgb(255, 165, 0));
}
else{
this.setBackgroundColor(Color.alpha(0));
}
}
 
@Override
protected void onDraw(Canvas canvas) {
Paint textPaint = new Paint();
textPaint.setColor(Color.WHITE);
canvas.drawBitmap(image, WIDTH_PADDING / 2, HEIGHT_PADDING / 2, null);
canvas.drawText(label, (image.getWidth()-getTextWidth(label)/2)/ 2, (HEIGHT_PADDING / 2) +
image.getHeight() + 8+SPACE, textPaint);
}
 
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
switch(action){
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
this.setBackgroundColor(Color.rgb(255, 165, 0));
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
this.setBackgroundColor(Color.alpha(0));
break;
}
 
return super.onTouchEvent(event);
}
 
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(measureWidth(widthMeasureSpec),measureHeight(heightMeasureSpec));
}
 
private int measureWidth(int measureSpec){
int preferred = image.getWidth() * 2;
return getMeasurement(measureSpec, preferred);
}
private int measureHeight(int measureSpec){
   int preferred = image.getHeight()+this.fontHeight+SPACE*2;
   return getMeasurement(measureSpec, preferred);
}
 
private int getMeasurement(int measureSpec, int preferred){
  int specSize = MeasureSpec.getSize(measureSpec);
int measurement = 0;
switch(MeasureSpec.getMode(measureSpec)){
case MeasureSpec.EXACTLY:
measurement = specSize;
break;
case MeasureSpec.AT_MOST:
measurement = Math.min(preferred, specSize);
break;
default:
measurement = preferred;
break;
}
return measurement;
}
 
public String getLabel(){
return label;
}  
 
public int getImageResId(){
return imageResId;
}
 
}

  


说说Android 两种为自定义组件添加属性的使用方法和区别
http://terryblog.blog.51cto.com/1764499/414884

Android高手进阶教程(四)之----Android 中自定义属性(attr.xml,TypedArray)的使用!
http://blog.csdn.net/Android_Tutor/archive/2010/04/20/5508615.aspx

linearlayout继承扩展篇
http://wang-peng1.iteye.com/blog/576151

另一篇:编写Android自定义按钮
http://marshal.easymorse.com/archives/3059

自定义图文并茂的Button
实现按钮,这里没有通过Button类或者子类去做派生,而是通过TextView派生出来的。在这里三个按钮是三个TextView派生类实例,中间的白线,是1px宽的白色矩形,这样就可以做出类似上面的效果。
看布局文件:
    
<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="vertical" android:layout_width="fill_parent"
    android:layout_height="fill_parent" android:background="@drawable/background_color"> 
    <LinearLayout android:layout_width="fill_parent" 
        android:layout_height="10dip" /> 
    <LinearLayout android:layout_width="fill_parent" 
        android:layout_height="40dip"> 
        <com.easymorse.textbutton.TextButton 
            android:layout_width="fill_parent" android:layout_height="fill_parent" 
            android:layout_weight="1" android:text="电影" 
            android:gravity="center_vertical|center_horizontal" 
            android:background="@drawable/button" android:focusable="true" android:clickable="true"/> 
        <View android:layout_width="2px" android:layout_height="fill_parent" 
            android:background="#ffffffff" /> 
        <com.easymorse.textbutton.TextButton 
            android:layout_width="fill_parent" android:layout_height="fill_parent" android:clickable="true" 
            android:layout_weight="1" android:text="电视" 
            android:gravity="center_vertical|center_horizontal" 
            android:background="@drawable/button" android:focusable="true" /> 
        <View android:layout_width="2px" android:layout_height="fill_parent" 
            android:background="#ffffffff" /> 
        <com.easymorse.textbutton.TextButton 
            android:layout_width="fill_parent" android:layout_height="fill_parent" android:clickable="true" 
            android:layout_weight="1" android:text="明星" 
            android:gravity="center_vertical|center_horizontal" 
            android:background="@drawable/button" android:focusable="true" /> 
    </LinearLayout> 
</LinearLayout>

  

这里需要注意的几点:

对于布局的像素设置,一般要用dip,这样在更大或者更小的屏幕下展示可以自动适配,如果是px,是物理像素,这样在小的屏幕里面可能会显得大,在大的屏幕中显得小
在按钮布局中要使用android:focusable="true" android:clickable="true",这样才能比如通过轨迹球聚焦到按钮上,才能用手触摸按钮的时候触发事件
点击按钮变色,主要在android:background="@drawable/button"配置,button配置了点击事件发生后的背景色改变,而不需要编写代码
下面来看看drawable/button.xml文件:
    
<?xml version="1.0" encoding="utf-8"?> 
<selector xmlns:android="http://schemas.android.com/apk/res/android" 
    android:constantSize="true"> 
    <item android:state_focused="true"> 
        <shape> 
            <gradient android:startColor="#FFE5CF33" android:endColor="#FFF1E7A2" 
                android:angle="90.0"> 
            </gradient> 
        </shape> 
    </item> 
    <item android:state_enabled="true" android:state_pressed="false"> 
        <shape> 
            <gradient android:startColor="#FF1B1B1B" android:endColor="#FF969696" 
                android:angle="90.0"> 
            </gradient> 
        </shape> 
    </item> 
    <item android:state_enabled="true" android:state_pressed="true"> 
        <shape> 
            <gradient android:startColor="#FF000000" android:endColor="#FF474747" 
                android:angle="90.0"> 
            </gradient> 
        </shape> 
    </item> 
    <item android:state_enabled="false" android:state_pressed="true"> 
        <shape> 
            <gradient android:startColor="#FF000000" android:endColor="#FF474747" 
                android:angle="90.0"> 
            </gradient> 
        </shape> 
    </item> 
    <item> 
        <shape> 
            <gradient android:startColor="#FF000000" android:endColor="#FF474747" 
                android:angle="90.0"> 
            </gradient> 
        </shape> 
    </item> 
</selector>

  

这个文件中定义了当条目(也就是按钮)enable和(或)pressed的情况下的背景渐近色的配置情况。

实际上,上面介绍的部分,在不使用自定义按钮(也就是不是<com.easymorse.textbutton.TextButton而直接写<TextView…)的情况下,已经可以出现除了点击后Toast消息。
说一下TextView的派生类,其实只是在touche按钮的时候显示提示信息:
    
import android.content.Context; 
import android.util.AttributeSet; 
import android.view.MotionEvent; 
import android.view.View; 
import android.widget.TextView; 
import android.widget.Toast;

public class TextButton extends TextView {

    public TextButton(Context context) { 
        super(context); 
    }

    public TextButton(Context context, AttributeSet attrs, int defStyle) { 
        super(context, attrs, defStyle); 
    }

    public TextButton(final Context context, AttributeSet attrs) { 
        this(context, attrs, 0);

        this.setOnTouchListener(new OnTouchListener() {

            @Override 
            public boolean onTouch(View v, MotionEvent event) { 
                if (event.getAction() == MotionEvent.ACTION_CANCEL 
                        || event.getAction() == MotionEvent.ACTION_UP 
                        || event.getAction() == MotionEvent.ACTION_OUTSIDE) { 
                    Toast.makeText(context, "touched", Toast.LENGTH_SHORT).show(); 
                } 
                return false; 
            } 
        }); 
    }

}

  

在这里主要是写了设置OnTouchListener的代码。

这里只针对3种情况才显示提示:

当手指从按钮抬起,ACTION_UP
取消,ACTION_CANCEL
手指移出按钮,ACTION_OUTSIDE
另外,要返回false,因为返回true,系统将不会调用drawable/button.xml的效果,因为true表示自己已经处理了onTouche事件,不需要别的逻辑再处理了。
源代码见: http://easymorse.googlecode.com/svn/tags/textButton-0.1.0/

用自定义Button实现ToggleButton
http://marshal.easymorse.com/archives/3045

附送:自定义的竖着的seekbar(转)

自定义图文并茂的Button


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论