参考鸿洋大神博客:http://blog.csdn.net/lmj623565791/article/details/24300125
主要内容:
1.自定义view
2.自定义view的属性
3.在view的构造方法中获取自定义的属性
4.重写onMeasure()
5.重写onDraw()
效果:实现进度条效果
1.自定义View属性示例:
在values下新建attrs.xml
布局
两个自定义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 si = new HashSet();
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);
}
}