http://blog.csdn.net/allen315410/article/details/39343401
一直想找机会学自定义控件的自定义属性,首先感谢这篇BLOG,以下是我写的一个自定义按钮,可修改圆角边,按钮颜色,文字颜色,带阴影,有按下效果
1、attrs.xml,Android Studio中没有attrs,在values下新建一个attrs,name="MyButton"这个MyButton就是我自定义控件的控件类名,AS很人性化,新建一个自定义View,继承View之后就能自动显示出来
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="MyButton">
<attr name="btnColor" format="color"/>
<attr name="btnCorner" format="float"/>
<attr name="btnEnabled" format="boolean"/>
<attr name="btnText" format="string"/>
<attr name="btnTextSize" format="dimension"/>
<attr name="btnTextColor" format="color"/>
</declare-styleable>
</resources>
2、自定义控件,说明一下,BaseClcxView是我自己写的一个抽象类,其实里面就是一个抽象init方法,然后在每一个构造方法里调用init,我嫌麻烦所以写了个抽象类统一起来
package com.clcx.goldenmaster.customview;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import com.clcx.goldenmaster.R;
import java.util.jar.Attributes;
/**
* Created by ljc123 on 2016/11/1.
*/
public class MyButton extends BaseClcxView {
private Paint mPaint;
private float corner;
private int color;
private boolean mEnabled;
private String text;
private int textColor;
private int textSize;
private boolean clickFlag;//一个触碰flag,如果按下就为true,松开就为false
private static final int shadowOffset = 4;//阴影偏移量
public MyButton(Context context) {
super(context);
}
public MyButton(Context context, AttributeSet attrs) {
super(context, attrs);
initAttrs(attrs);
}
public MyButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initAttrs(attrs);
}
@Override
protected void init() {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
clickFlag = false;
}
//初始化attrs
private void initAttrs(AttributeSet attrs) {
//用TypedArray获取attrs
TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.MyButton);
int count = ta.getIndexCount();
for (int a = 0; a < count; a++) {
//遍历attrs里面,name为MyButton的declare-styleable中,所有的attr标签
int itemId = ta.getIndex(a);
switch (itemId) {
case R.styleable.MyButton_btnColor:
this.color = ta.getInt(itemId, Color.GRAY);
break;
case R.styleable.MyButton_btnCorner:
this.corner = ta.getFloat(itemId, 0.0f);
break;
case R.styleable.MyButton_btnEnabled:
this.mEnabled = ta.getBoolean(itemId, false);
break;
case R.styleable.MyButton_btnText:
this.text = ta.getString(itemId);
break;
case R.styleable.MyButton_btnTextSize:
this.textSize = ta.getDimensionPixelSize(itemId, 0);
break;
case R.styleable.MyButton_btnTextColor:
this.textColor = ta.getInt(itemId, Color.BLACK);
break;
default:
break;
}
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
drawShadow(canvas);
if (clickFlag) {
drawButtonClick(canvas);
} else {
drawButtonNormal(canvas);
}
}
private void drawShadow(Canvas c) {
mPaint.setColor(Color.GRAY);
c.drawRoundRect(new RectF(shadowOffset, shadowOffset, getMeasuredWidth(), getMeasuredHeight()), corner,
corner, mPaint);
}
private void drawButtonNormal(Canvas c) {
mPaint.setColor(color);
c.drawRoundRect(new RectF(0, 0, getMeasuredWidth() - shadowOffset, getMeasuredHeight() - shadowOffset),
corner, corner, mPaint);
drawText(c, false);
}
private void drawButtonClick(Canvas c) {
mPaint.setColor(color);
c.drawRoundRect(new RectF(shadowOffset, shadowOffset, getMeasuredWidth(), getMeasuredHeight()), corner,
corner, mPaint);
drawText(c, true);
}
private void drawText(Canvas c, boolean ifclick) {
mPaint.setTextSize(textSize);
mPaint.setColor(textColor);
Rect bounds = new Rect();
mPaint.getTextBounds(text, 0, text.length(), bounds);
if (ifclick) {
c.drawText(text, (getMeasuredWidth() - bounds.width()) / 2 + shadowOffset, (getMeasuredHeight() + bounds
.height()) / 2 + shadowOffset,
mPaint);
} else {
c.drawText(text, (getMeasuredWidth() - bounds.width()) / 2 - shadowOffset, (getMeasuredHeight() + bounds
.height()) / 2 - shadowOffset,
mPaint);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
clickFlag = true;
break;
case MotionEvent.ACTION_UP:
clickFlag = false;
break;
default:
break;
}
invalidate();
return super.onTouchEvent(event);
}
public void setCorner(float corner) {
this.corner = corner;
invalidate();
}
public void setColor(int color) {
this.color = color;
invalidate();
}
public void setmEnabled(boolean mEnabled) {
this.mEnabled = mEnabled;
invalidate();
}
public void setText(String text) {
this.text = text;
invalidate();
}
public void setTextColor(int textColor) {
this.textColor = textColor;
invalidate();
}
public void setTextSize(int textSize) {
this.textSize = textSize;
invalidate();
}
}
3、具体使用
<com.clcx.goldenmaster.customview.MyButton
android:id="@+id/btnCreator"
android:layout_width="match_parent"
android:layout_height="64dp"
android:layout_marginTop="8dp"
app:btnColor="@color/colorPrimary"
app:btnCorner="20"
app:btnText="创建"
app:btnTextColor="#fff"
app:btnTextSize="16sp"/>
注意一点,高度必须定义,不能用wrap_content,这个问题暂时没有解决,因为其实不是大问题,反正实际项目基本上使用百分比布局或者固定大小,有感兴趣的可以完善一下,百度“自定义控件wrap_content”,有相关分析