直接继承View实现,属性全部自定义
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- 按钮的背景色 -->
<attr name="back_ground_color" format="color" />
<!-- 点击的阴影颜色 -->
<attr name="click_color" format="color" />
<!-- 文本 -->
<attr name="text" format="string" />
<!-- 文本的位置 -->
<attr name="text_position" format="enum">
<enum name="left" value="0" />
<enum name="center" value="1" />
<enum name="right" value="2" />
</attr>
<!-- 文字的大小 -->
<attr name="text_size" format="dimension" />
<!-- 文字的颜色 -->
<attr name="text_color" format="color" />
<declare-styleable name="click_view">
<attr name="back_ground_color" />
<attr name="click_color" />
<attr name="text" />
<attr name="text_position" />
<attr name="text_size" />
<attr name="text_color" />
</declare-styleable>
</resources>
具体实现类
package com.sunrui.mysport.widget;
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.util.Log;
import android.view.MotionEvent;
import android.view.View;
import com.sunrui.mysport.R;
/**
* Created by sunrui on 15/9/9.
* 点击扩散效果的View
*/
public class ClickView extends View {
/**
* 背景颜色
*/
private int background_color;
/**
* 点击时的颜色
*/
private int click_color;
/**
* 显示的文本
*/
private String text;
/**
* 文本颜色
*/
private int text_color;
/**
* 文本位置
* 0 左侧
* 1 居中
* 2 右侧
*/
private int text_position;
/**
* 文本大小
*/
private float text_size;
/**
* 控件的宽
*/
private int width;
/**
* 控件的高
*/
private int height;
/**
* 文本区域大小
*/
private Rect text_area;
/**
* 文本画笔
*/
private Paint text_p;
/**
* 背景画笔
*/
private Paint background_p;
/**
* 点击效果的画笔
*/
private Paint click_p;
/**
* 点击阴影的半径
*/
private float radius;
/**
* 阴影部分区域
*/
private RectF shadow_area;
public ClickView(Context context) {
super(context);
}
public ClickView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public ClickView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.click_view, 0, 0);
int n = typedArray.getIndexCount();
for (int i = 0; i < n; i++) {
int attr = typedArray.getIndex(i);
switch (attr) {
case R.styleable.click_view_back_ground_color:
background_color = typedArray.getColor(attr, Color.WHITE);
break;
case R.styleable.click_view_click_color:
click_color = typedArray.getColor(attr, Color.GRAY);
break;
case R.styleable.click_view_text:
text_area = new Rect();
text = typedArray.getString(attr);
break;
case R.styleable.click_view_text_color:
text_color = typedArray.getColor(attr, Color.BLACK);
break;
case R.styleable.click_view_text_position:
text_position = typedArray.getInt(attr, 1);
break;
case R.styleable.click_view_text_size:
text_size = typedArray.getDimension(attr, 32.0f);
break;
default:
break;
}
}
background_p = new Paint();
text_p = new Paint();
click_p = new Paint();
shadow_area = new RectF(0, 0, 0, 0);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
width = 0;
height = 0;
int specMode = MeasureSpec.getMode(widthMeasureSpec);
int specSize = MeasureSpec.getSize(widthMeasureSpec);
switch (specMode) {
case MeasureSpec.EXACTLY:
width = getPaddingLeft() + getPaddingRight() + specSize;
break;
case MeasureSpec.AT_MOST:
if (text_area != null) {
width = getPaddingLeft() + getPaddingRight() + text_area.width();
} else {
width = getPaddingLeft() + getPaddingRight();
}
break;
default:
break;
}
specMode = MeasureSpec.getMode(heightMeasureSpec);
specSize = MeasureSpec.getSize(heightMeasureSpec);
switch (specMode) {
case MeasureSpec.EXACTLY:
height = getPaddingTop() + getPaddingBottom() + specSize;
break;
case MeasureSpec.AT_MOST:
if (text_area != null) {
height = getPaddingTop() + getPaddingBottom() + text_area.height();
} else {
height = getPaddingTop() + getPaddingBottom();
}
break;
default:
break;
}
setMeasuredDimension(width, height);
}
@Override
protected void onDraw(Canvas canvas) {
//绘制背景
background_p.setColor(background_color);
canvas.drawRect(0, 0, width, height, background_p);
//绘制文字
text_p.setColor(text_color);
text_p.setTextSize(text_size);
float text_x = 0f;
text_p.getTextBounds(text, 0, text.length(), text_area);
float text_y = (height + text_area.height()) / 2;
Log.v("sss", text_y + "===" + height + "===" + text_area.height());
if (text_position == 0) {
text_x = 0f;
} else if (text_position == 1) {
text_x = (width - text_area.width()) / 2;
Log.v("sss", width + "===" + text_area.width() + text_area.height());
} else if (text_position == 2) {
text_x = width - text_area.width();
}
canvas.drawText(text, text_x, text_y, text_p);
//绘制阴影
click_p.setColor(click_color);
canvas.drawArc(shadow_area, 0, 360, false, click_p);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
final float click_x = event.getX();
switch (action) {
case MotionEvent.ACTION_DOWN:
radius = height * 1.5f;
shadow_area = new RectF(click_x - radius / 2, (height - radius) / 2, click_x + radius / 2, (height + radius) / 2);
postInvalidate();
break;
case MotionEvent.ACTION_UP:
new Thread() {
@Override
public void run() {
while (true) {
if (radius > width * 2.0f) {
break;
}
radius += width / 18;
shadow_area = new RectF(click_x - radius / 2, (height - radius) / 2, click_x + radius / 2, (height + radius) / 2);
try {
Thread.sleep(300/18);
} catch (InterruptedException e) {
e.printStackTrace();
}
postInvalidate();
}
shadow_area = new RectF(0, 0, 0, 0);
}
}.start();
break;
default:
break;
}
return true;
}
}
布局文件
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.sunrui.mysport.ui.AddSportItemActivity">
<com.sunrui.mysport.widget.ClickView
android:layout_width="match_parent"
android:layout_height="48dp"
custom:back_ground_color="#ffffff"
custom:click_color="#33000000"
custom:text="点击测试"
custom:text_position="center"
custom:text_size="32px"
custom:text_color="#00ff00"/>
</RelativeLayout>
如果不是在Android studio中,将第二行的res-auto改成包名