参考鸿洋大神博客:http://blog.csdn.net/lmj623565791/article/details/24300125
主要内容:
1.自定义view
2.自定义view的属性
3.在view的构造方法中获取自定义的属性
4.重写onMeasure()
5.重写onDraw()
效果:实现进度条效果

1.自定义View属性示例:
在values下新建attrs.xml
<?xml version="1.0" encoding="utf-8" ?>
<resources>
<attr name="titleText" format="string"/>
<attr name="titleTextColor" format="color"/>
<attr name="titleTextSize" format="dimension"/>
<attr name="firstColor" format="color"/>
<attr name="secondColor" format="color"/>
<attr name="circleWidth" format="dimension"/>
<attr name="speed" format="integer"/>
<declare-styleable name="CustomTitleView">
<attr name="titleText"/>
<attr name="titleTextColor"/>
<attr name="titleTextSize"/>
</declare-styleable>
<declare-styleable name="CustomProgressBar">
<attr name="firstColor"/>
<attr name="secondColor"/>
<attr name="circleWidth"/>
<attr name="speed"/>
</declare-styleable>
</resources>
布局
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
//此处特别注意:需添加如下声明
xmlns:custom="http://schemas.android.megvii.customview"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" tools:context="megvii.customview.MainActivity">
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content"
android:text="Hello World!" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<megvii.customview.CustomTitleView
android:id="@+id/custom"
//自定义的属性
custom:titleTextColor="#ff0000"
custom:titleTextSize="40sp"
custom:titleText="nihaoahgagaga"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<megvii.customview.CustomProgressBar
custom:circleWidth="60sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</android.support.constraint.ConstraintLayout>
两个自定义View,不同效果进阶:
CustomTitleView:
public class CustomTitleView extends View {
private String mTitleText = "ggaggagh";
private int mTitleTextColor = Color.BLUE;
private int mTitleTextSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics());
private Rect mBound;
private Paint mPaint = new Paint();
public CustomTitleView(Context context) {
this(context, null);
}
public CustomTitleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
Log.i("hello", "gas");
//获得自定义样式属性
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CustomTitleView);
int n = ta.length();
Log.i("hello", "gggggggg" + n);
for (int i = 0; i < n; i++) {
int attr = ta.getIndex(i);
switch (attr) {
case R.styleable.CustomTitleView_titleText:
//不知道为什么,这个函数就是不好使,运行就闪退
mTitleText = ta.getString(attr);
break;
case R.styleable.CustomTitleView_titleTextColor:
//默认设置为蓝色
mTitleTextColor = ta.getColor(attr, Color.BLUE);
break;
case R.styleable.CustomTitleView_titleTextSize:
//默认设置为16sp
mTitleTextSize = ta.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 26, getResources().getDisplayMetrics()));
break;
}
}
ta.recycle();
Log.wtf("nihao", mTitleText);
//获得文本宽高
mPaint.setTextSize(mTitleTextSize);
mBound = new Rect();
mPaint.getTextBounds(mTitleText, 0, mTitleText.length(), mBound);
this.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mTitleText = randomText();
postInvalidate();
}
});
}
public CustomTitleView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
private String randomText(){
Random random = new Random(System.currentTimeMillis());
Set<Integer> si = new HashSet<Integer>();
while(si.size() < 10){
int rand = random.nextInt();
si.add(rand);
}
StringBuffer sb = new StringBuffer();
for(Integer i : si){
sb.append("" + i);
}
return sb.toString();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//通过重写onMeasure可以解决wrap_content与padding问题
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int width;
int height;
if (widthMode == MeasureSpec.EXACTLY) {
width = widthSize;
} else {
mPaint.setTextSize(mTitleTextSize);
mPaint.getTextBounds(mTitleText, 0, mTitleText.length(), mBound);
float textWidth = mBound.width();
int desired = (int) (getPaddingLeft() + textWidth + getPaddingRight());
width = desired;
}
if (heightMode == MeasureSpec.EXACTLY) {
height = heightSize;
} else {
mPaint.setTextSize(mTitleTextSize);
mPaint.getTextBounds(mTitleText, 0, mTitleText.length(), mBound);
float textheight = mBound.height();
int desired = (int) (getPaddingTop() + textheight + getPaddingBottom());
height = desired;
}
setMeasuredDimension(width, height);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPaint.setColor(Color.YELLOW);
canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint);
mPaint.setColor(mTitleTextColor);
canvas.drawText(mTitleText, getWidth() / 2 - mBound.width() / 2, getHeight() / 2 + mBound.height() / 2, mPaint);
}
}
CustomProgressBar
public class CustomProgressBar extends View{
private int mFirstColor;
private int mSecondColor;
private int mCircleWidth;
private Paint mPaint;
private int mProgress;
private int mSpeed;
private boolean isNext = false;
public CustomProgressBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomProgressBar);
int n = a.length();
for(int i = 0; i < n; i++){
int attr = a.getIndex(i);
switch (attr){
case R.styleable.CustomProgressBar_firstColor:
mFirstColor = a.getColor(attr, Color.GREEN);
break;
case R.styleable.CustomProgressBar_secondColor:
mSecondColor = a.getColor(attr, Color.RED);
break;
case R.styleable.CustomProgressBar_circleWidth:
mCircleWidth = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, 140, getResources().getDisplayMetrics()));
break;
case R.styleable.CustomProgressBar_speed:
mSpeed = a.getInt(attr, 20);
break;
}
}
a.recycle();
mPaint = new Paint();
new Thread(){
@Override
public void run() {
while(true){
mProgress++;
if(mProgress == 360){
mProgress = 0;
if(!isNext)
isNext = true;
else
isNext = false;
}
postInvalidate();
try{
Thread.sleep(mSpeed);
}catch (Exception e){
e.printStackTrace();
}
}
};
}.start();
}
@Override
protected void onDraw(Canvas canvas) {
int center = getWidth() / 2;//获取圆心的x坐标
int radius = center - mCircleWidth / 2 -60;//半径
mPaint.setStrokeWidth(100);//设置圆环的宽度
mPaint.setAntiAlias(true);//消除锯齿
mPaint.setStyle(Paint.Style.STROKE);//设置空心
RectF oval = new RectF(center-radius, center-radius, center+radius, center+radius);
//定义圆弧的形状和大小的界限
if(!isNext){
mPaint.setColor(mFirstColor);//设置圆环颜色
canvas.drawCircle(center, center, radius, mPaint);//画出圆圈
mPaint.setColor(mSecondColor);//设置圆环颜色
canvas.drawArc(oval, -90, mProgress, false, mPaint);//根据进度画圆弧
}else{
mPaint.setColor(mSecondColor);
canvas.drawCircle(center, center, radius, mPaint);
mPaint.setColor(mFirstColor);
canvas.drawArc(oval, -90, mProgress, false, mPaint);
}
}
public CustomProgressBar(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public CustomProgressBar(Context context) {
this(context, null);
}
}
网友评论