图片预览
1. 分析和实现原理
1. 自定义一个圆环
2. 自定义ViewGroup,然后添加圆环
3. onMeasue和onLayout处理
4. 绘制文字
2. 绘制圆环
//平移坐标系到中心点
canvas.translate(mCenterX,mCenterY);
mPaint.setColor(mRingColor);
//两种思路 画圆 或者画圆环
canvas.drawCircle(0,0,mRingRadius,mPaint);
//或者画圆环
// float left = -mRingRadius;
// float top = -mRingRadius;
// float right = mRingRadius;
// float bottom = mRingRadius;
// mRectF.set(left,top,right,bottom);
// canvas.drawArc(mRectF,0,360,false,mPaint);
3. ViewGroup中添加圆环
int margin = dp2px(8);
//添加5个圆环
for (int i = 0; i < 5; i++) {
MarginLayoutParams lp = new MarginLayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
lp.setMargins(margin, margin, 0, margin);
addView(new RingProgressBar(context, attrs),lp);
}
4. onMeasure处理
这个代码都很简单 没什么解释的
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
//wrap_content计算宽高
int width = 0;
int height = 0;
//计算上面 下面的宽高
int tWidth = 0;
int bWidth = 0;
int tHeight = 0;
int bHeight = 0;
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
//测量每一个子孩子的宽高
measureChild(child,widthMeasureSpec,heightMeasureSpec);
MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
int cWidth = child.getMeasuredWidth() + lp.leftMargin;
int cHeight = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
if(i < 3){
tWidth += cWidth;
tHeight = cHeight;
}else{
bWidth += cWidth;
bHeight = tHeight / 2 + cHeight;
}
}
mRingMaxHeight = Math.max(tHeight,bHeight);
width = Math.max(tWidth,bWidth);
//要加上文字的高度和上下间距
height = Math.max(tHeight,bHeight) + mENDescHeight + mCNDescHeight+ textSpacing * 2;
//wrap_content 取子View测量的宽高
int measureWidth = widthMode == MeasureSpec.AT_MOST ? width : widthSize;
int measureHeight = heightMode == MeasureSpec.AT_MOST ? height : heightSize;
setMeasuredDimension(measureWidth,measureHeight);
}
5. onLayout处理
计算每一个圆环左上右下的值,完成布局,完成放置子View的位置
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
//上面下面子view距离左边的间距
int tLeft = 0;
int bLeft = 0;
int top = 0;
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
//如果子View是GONE,则不处理
if(child.getVisibility() == View.GONE){
continue;
}
MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
int cWidth = child.getMeasuredWidth();
int cHeight = child.getMeasuredHeight();
//上面三个圆环 top都是一样的。
//left值等于前一个圆环的宽度加上左边的margin值
if(i < 3){
if(i == 0){
tLeft = lp.leftMargin;
}else {
tLeft = tLeft + cWidth + lp.leftMargin;
}
top = lp.topMargin;
child.layout(tLeft, top, tLeft + cWidth, top + cHeight);
}else {
//下面两个圆环top的高度等于topMargin+上面圆环高度的1/2,左边的left第一个圆环等于
// 上面圆环的宽度取它的0.55倍+距离左边的间距,第二个圆环等于下面
// 第一个圆环的left+圆环宽度+leftMargin
if( i == 3){
bLeft = (int) (0.55f * cWidth + lp.leftMargin);
}else{
bLeft = bLeft + cWidth + lp.leftMargin;
}
top = (int) (lp.topMargin + 0.5 * cHeight);
child.layout(bLeft,top,bLeft + cWidth,top + cHeight);
}
}
}
6. 绘制文字
绘制文字的时候文字的top值=上面圆环的高度+文字之间的间距
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//画文字
float cnY = mRingMaxHeight + textSpacing;
float enY = cnY + mCNDescHeight+ textSpacing;
canvas.drawText(chineseDesc,mCenterX,cnY,mPaint);
canvas.drawText(englishDesc,mCenterX, enY,mPaint);
}
7. 小结和源码下载
小结:
最核心还是onMeasure和onlayout的处理
源码下载:
最后统一提供代码下载地址
8.联系方式
QQ:1509815887