View的测量与绘制:
测量的3种模式
MeasureSpec:封装了测量模式和长宽大小
一般重写View的模板:
public class MyView extends View {
public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public MyView(Context context) {
super(context);
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
}
/**
* 控制View的大小
*/
@Override
protected void
onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
/**
* 在View上绘制图形图像
*/
@Override
protected void
onDraw(Canvas canvas) {
super.onDraw(canvas);
//
getMeasuredWidth(); getMeasuredHeight() ,获取高宽
}
/**
* 屏幕大小改变和时调用
* 这里主要是获取变化后的长宽
*/
@Override
protected void
onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
int height = getHeight() ;
int width = getWidth() ;
}
/**
* 在这里控制View的布局参数,一般View不需要复写该方法
一般是在ViewGroup复写onLayout(),用来控制子View的布局位置
*/
@Override
protected void
onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
//getLayoutParams() 获取View 的布局参数,获取包括外边距,内边距,布局方向,布局的高度
ViewGroup.MarginLayoutParams mlp = (ViewGroup.MarginLayoutParams)getLayoutParams() ;
mlp.leftMargin = 10 ;
setLayoutParams(mlp);
}
}
public class CustomView extends View {
public CustomView(Context context) {
super(context);
}
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
/**
* View的测量,主要是测量该View在大小
* View的布局模式和大小都封装在widthMeasureSpec和heightMeasureSpec中
* 需使用MeasureSpec类将其解析出来,然后随便自定义
*/
@Override
protected void
onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int viewWidth = measureWidth(widthMeasureSpec) ;
int viewHeight = measureHeight(heightMeasureSpec);
//setMeasuredDimension()是设置View的尺寸
setMeasuredDimension(viewWidth,viewHeight);
}
/**
* 测量View的宽度
* @param widthMeasureSpec
* @return
*/
private int measureWidth(int widthMeasureSpec){
int result = 0 ;
int specMode = MeasureSpec.getMode(widthMeasureSpec) ;
int specSize = MeasureSpec.getSize(widthMeasureSpec) ;
if(specMode == MeasureSpec.EXACTLY){
result = specSize ;
}else{ //对其他模式的情况进行处理,如果不处理,其他模式(如wrap_content)下也会match_parent
result = 200 ;
if(specMode == MeasureSpec.AT_MOST){
//取较小的一个
result = Math.min(result,specSize) ;
}
}
return result ;
}
/**
* 测量View的高度
*/
private int measureHeight(int heightMeasureSpec){
int result = 0 ;
int specMode = MeasureSpec.getMode(heightMeasureSpec) ;
int specSize = MeasureSpec.getSize(heightMeasureSpec) ;
if(specMode == MeasureSpec.EXACTLY){
result = specSize ;
}else{ //对其他模式的情况进行处理,如果不处理,其他模式(如wrap_content)下也会match_parent
result = 200 ;
if(specMode == MeasureSpec.AT_MOST){
//取较小的一个
result = Math.min(result,specSize) ;
}
}
return result ;
}
/**
* View的绘制
*/
@Override
protected void
onDraw(Canvas canvas) {
super.onDraw(canvas);
//将整个画布绘制成白色
canvas.drawColor(Color.RED);
//设置画笔
Paint pt = new Paint() ;
pt.setStyle(Paint.Style.STROKE);
pt.setColor(Color.BLUE);
pt.setStrokeWidth(2);
//画圆形
canvas.drawCircle(50, 50, 30, pt);
//画正方形矩形
canvas.drawRect(10,90,90,170,pt);
//画矩形
canvas.drawRect(10, 200, 110, 250, pt);
//画圆角矩形
RectF rf1 = new RectF(20,300,120,350) ;
canvas.drawRoundRect(rf1, 10, 10, pt);
//画椭圆
RectF rf2 = new RectF(10,400,120,450) ;
canvas.drawOval(rf2, pt);
//画弧形
RectF rf3 = new RectF(10,500,410,800) ;
canvas.drawArc(rf3,180,120,false,pt);
}
}
自定义View,继承了TextView
效果图;
public class CustomTextView extends TextView {
private Paint mPaint1 = null ;
private Paint mPaint2 = null ;
public CustomTextView(Context context) {
super(context);
initView();
}
public CustomTextView(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
public CustomTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initView();
}
/**
* 这里不需要复写onMeasure()方法,不需要再重新测量大小了,因为TextView已经搞好了
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onDraw(Canvas canvas) {
//绘制外层矩形
canvas.drawRect(0,0,getMeasuredWidth(),getMeasuredHeight(),mPaint1);
canvas.drawRect(5,5, getMeasuredWidth() - 5, getMeasuredHeight() - 5, mPaint2);
//设置偏移距离之前保存画布
canvas.save();
//设置画布的原点偏移距离,x轴偏移10个像素
canvas.translate(5,0);
//父类onDraw()负责绘制文本
super.onDraw(canvas);
//恢复画布
canvas.restore();
}
/**
* 初始化View
*/
private void initView(){
//初始化画笔
mPaint1 = new Paint() ;
mPaint1.setStyle(Paint.Style.FILL);
mPaint1.setColor(Color.RED);
mPaint2 = new Paint();
mPaint2.setStyle(Paint.Style.FILL);
mPaint2.setColor(Color.BLUE);
}
}
自定义View,实现圆形进度图
效果图:
public class CustomCircleProcess extends View {
private int mMeasureWidth = 0 ;
private int mMeasureHeight = 0 ;
//圆形圆心
private float mCircleXY = 0 ;
//圆形半径
private float mCircleRadius = 0 ;
//圆形所用到的画笔
private Paint mCirclePaint ;
//弧形所需要的矩形
private RectF mArcRectF ;
//弧形起始角度,默认值:270
private float mArcStartAngle = 270 ;
//弧形的跨越度数 ,默认值:25
private float mArcSweepAngle = 25 ;
//弧形所需要的画笔
private Paint mArcPaint ;
//绘制文本所需要的Paint
private Paint mTextPaint ;
//文本内容
private String mTextContent = "万紫辉" ;
//文本大小
private float mTextSize = 20f ;
public CustomCircleProcess(Context context) {
super(context);
}
public CustomCircleProcess(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomCircleProcess(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
/**
* 复写onMeasure()方法,测量其大小
* @param widthMeasureSpec
* @param heightMeasureSpec
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//这个View只有MeasureSpec.EXACTLY模式(绝对值或match_parent),没有对其他模式(如:wrap_content)进行处理,
//所以在其他模式下,长宽也都是match_parent
//其实这里不需要wrap_content的情况
mMeasureWidth = MeasureSpec.getSize(widthMeasureSpec) ;
mMeasureHeight = MeasureSpec.getSize(heightMeasureSpec) ;
setMeasuredDimension(mMeasureWidth, mMeasureHeight);
initView();
}
@Override
protected void onDraw(Canvas canvas) {
//画圆
canvas.drawCircle(mCircleXY, mCircleXY, mCircleRadius, mCirclePaint);
//画弧
canvas.drawArc(mArcRectF, mArcStartAngle, mArcSweepAngle, false, mArcPaint);
//画文本
canvas.drawText(mTextContent, mCircleXY, mCircleXY, mTextPaint);
}
private void initView(){
float length = 0f ;
if(mMeasureHeight > mMeasureWidth){
length = mMeasureWidth ;
}else{
length = mMeasureHeight ;
}
mCircleXY = length / 2 ;
mCircleRadius =length / 4 ;
mCirclePaint = new Paint() ;
mCirclePaint.setStyle(Paint.Style.FILL);
mCirclePaint.setColor(Color.RED);
mCirclePaint.setAntiAlias(true);
mArcRectF = new RectF(
(float)(length*0.1),
(float)(length*0.1),
(float)(length*0.9),
(float)(length*0.9)) ;
mArcSweepAngle = 240f ;
mArcPaint = new Paint() ;
mArcPaint.setAntiAlias(true);
mArcPaint.setStyle(Paint.Style.STROKE);
mArcPaint.setStrokeWidth((float)(length*0.1));
mArcPaint.setColor(Color.BLUE);
mTextPaint = new Paint() ;
mTextPaint.setStyle(Paint.Style.STROKE);
mTextPaint.setStrokeWidth(2f);
mTextPaint.setColor(Color.GREEN);
//设置要绘制文本的大小
mTextPaint.setTextSize(mTextSize);
//设置要绘制文本的对其方式
mTextPaint.setTextAlign(Paint.Align.CENTER); //CENTER :文本原点为中心点,LEFT or RIGHT :文本原点为起点
}
/**
* 设置弧形范围
* @param value
*/
public void setSweepAngle(float value){
if(value >= 0){
mArcSweepAngle = value ;
}else{
mArcSweepAngle = 25 ;
}
//重绘视图
this.invalidate();
}
public void setTextContent(String value){
mTextContent = value ;
this.invalidate();
}
}
条形梯度图:
效果图:
public class CustomGradientView extends View {
private Paint mPaint ;
private int mViewWidth ;
private int mViewHeight ;
private int mRectWidth ;
private int mRectHeight ;
private int mRectCount = 10 ;
private int offset = 3 ;
public CustomGradientView(Context context) {
super(context);
initView() ;
}
public CustomGradientView(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
public CustomGradientView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initView();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
/**
* 绘制图像
* @param canvas
*/
@Override
protected void
onDraw(Canvas canvas) {
canvas.drawColor(Color.RED);
for(int i = 0 ; i < mRectCount ; i++){
// 0.0 <= random < 1.0
double random = Math.random() ;
float topDistance = (float)(mRectHeight * random) ;
float leftDistance = (float)(mViewWidth * 0.1 + mRectWidth * i + offset*i) ;
float rightDistance = (float)(mViewWidth * 0.1 + mRectWidth * (i+1) + offset*i) ;
float bottomDistance = mRectHeight ;
canvas.drawRect(leftDistance,topDistance,rightDistance,bottomDistance,mPaint);
}
//过500毫秒在重新绘制
postInvalidateDelayed(500);
}
/**
* 横竖屏变化时,获取其长宽
*/
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mViewWidth = getWidth() ;
mViewHeight = getHeight() ;
mRectHeight = mViewHeight ;
mRectWidth =(int)(( mViewWidth / mRectCount ) * 0.7) ;
}
private void initView(){
//初始化画笔
mPaint = new Paint() ;
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(Color.YELLOW);
}
}
ViewGroup的测量和绘制:
一把要复写:
onMeasure() ; onDraw() ; onLayout()
public class CustomScrollView extends ViewGroup {
//屏幕高度
private int mScreenHeight= 0 ;
private Scroller mScroller;
private int mLastY;
private int mStart;
private int mEnd;
public CustomScrollView(Context context) {
super(context);
initView(context);
}
public CustomScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
initView(context);
}
public CustomScrollView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initView(context);
}
private void initView(Context context){
//获取屏幕高度(像素高度)
WindowManager wm = (WindowManager)(context.getSystemService(Context.WINDOW_SERVICE)) ;
DisplayMetrics dm = new DisplayMetrics() ;
wm.getDefaultDisplay().getMetrics(dm);
mScreenHeight = dm.heightPixels ;
}
/**
* onMeasure() 用于设计ViewGoup的大小
* widthMeasureSpec和heightMeasureSpec封装了ViewGroup的模式和大小,
* 以这个参数,调用measureChild()来测量子View的大小
* @param widthMeasureSpec
* @param heightMeasureSpec
*/
@Override
protected void
onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int count = getChildCount() ;
for (int i = 0; i < count; i++) {
View childView = getChildAt(i) ;
measureChild(childView,widthMeasureSpec,heightMeasureSpec);
}
}
/**
* onLayout() 用于控制ViewGroup的(子View)布局情况
* 主要就是控制View的布局方向,各种外边距的
*/
@Override
protected void
onLayout(boolean changed, int l, int t, int r, int b) {
int count =
getChildCount() ;
//getLayoutParams() 获取View 的布局参数,获取包括外边距,内边距,布局方向,布局的高度
MarginLayoutParams mlp = (MarginLayoutParams)getLayoutParams() ;
mlp.height = mScreenHeight * count;
//setLayoutParams() 设置布局参数
setLayoutParams(mlp);
for(int i = 0 ; i < count ; i++){
View childView =
getChildAt(i) ;
//控制子的布局情况
childView.layout(l,i * mScreenHeight,r,(i+1)*mScreenHeight);
}
}
/**
* onDraw() 用于在ViewGroup上绘的图像,
* 如果不是设置ViewGroup的背景,一般不需要复写ViewGroup的onDraw()方法
* @param canvas
*/
@Override
protected void
onDraw(Canvas canvas) {
super.onDraw(canvas);
}
/**
* 用于监听响应事件
* @param event
* @return
*/
@Override
public boolean
onTouchEvent(MotionEvent event) {
int y = (int) event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mLastY = y;
mStart = getScrollY();
break;
case MotionEvent.ACTION_MOVE:
if (!mScroller.isFinished()) {
mScroller.abortAnimation();
}
int dy = mLastY - y;
if (getScrollY() < 0) {
dy = 0;
}
if (getScrollY() > getHeight() - mScreenHeight) {
dy = 0;
}
scrollBy(0, dy);
mLastY = y;
break;
case MotionEvent.ACTION_UP:
mEnd = getScrollY();
int dScrollY = mEnd - mStart;
if (dScrollY > 0) {
if (dScrollY < mScreenHeight / 3) {
mScroller.startScroll(
0, getScrollY(),
0, -dScrollY);
} else {
mScroller.startScroll(
0, getScrollY(),
0, mScreenHeight - dScrollY);
}
} else {
if (-dScrollY < mScreenHeight / 3) {
mScroller.startScroll(
0, getScrollY(),
0, -dScrollY);
} else {
mScroller.startScroll(
0, getScrollY(),
0, -mScreenHeight - dScrollY);
}
}
break;
}
postInvalidate();
return true;
}
@Override
public void computeScroll() {
super.computeScroll();
if (mScroller.computeScrollOffset()) {
scrollTo(0, mScroller.getCurrY());
postInvalidate();
}
}
}
View的测量与绘制:
测量的3种模式
MeasureSpec:封装了测量模式和长宽大小
1
一般重写View的模板:
public class MyView extends View {
public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public MyView(Context context) {
super(context);
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
}
/**
* 控制View的大小
*/
@Override
protected void
onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
/**
* 在View上绘制图形图像
*/
@Override
protected void
onDraw(Canvas canvas) {
super.onDraw(canvas);
//
getMeasuredWidth(); getMeasuredHeight() ,获取高宽
}
/**
* 屏幕大小改变和时调用
* 这里主要是获取变化后的长宽
*/
@Override
protected void
onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
int height = getHeight() ;
int width = getWidth() ;
}
/**
* 在这里控制View的布局参数,一般View不需要复写该方法
一般是在ViewGroup复写onLayout(),用来控制子View的布局位置
*/
@Override
protected void
onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
//getLayoutParams() 获取View 的布局参数,获取包括外边距,内边距,布局方向,布局的高度
ViewGroup.MarginLayoutParams mlp = (ViewGroup.MarginLayoutParams)getLayoutParams() ;
mlp.leftMargin = 10 ;
setLayoutParams(mlp);
}
}
public class CustomView extends View {
public CustomView(Context context) {
super(context);
}
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
/**
* View的测量,主要是测量该View在大小
* View的布局模式和大小都封装在widthMeasureSpec和heightMeasureSpec中
* 需使用MeasureSpec类将其解析出来,然后随便自定义
*/
@Override
protected void
onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int viewWidth = measureWidth(widthMeasureSpec) ;
int viewHeight = measureHeight(heightMeasureSpec);
//setMeasuredDimension()是设置View的尺寸
setMeasuredDimension(viewWidth,viewHeight);
}
/**
* 测量View的宽度
* @param widthMeasureSpec
* @return
*/
private int measureWidth(int widthMeasureSpec){
int result = 0 ;
int specMode = MeasureSpec.getMode(widthMeasureSpec) ;
int specSize = MeasureSpec.getSize(widthMeasureSpec) ;
if(specMode == MeasureSpec.EXACTLY){
result = specSize ;
}else{ //对其他模式的情况进行处理,如果不处理,其他模式(如wrap_content)下也会match_parent
result = 200 ;
if(specMode == MeasureSpec.AT_MOST){
//取较小的一个
result = Math.min(result,specSize) ;
}
}
return result ;
}
/**
* 测量View的高度
*/
private int measureHeight(int heightMeasureSpec){
int result = 0 ;
int specMode = MeasureSpec.getMode(heightMeasureSpec) ;
int specSize = MeasureSpec.getSize(heightMeasureSpec) ;
if(specMode == MeasureSpec.EXACTLY){
result = specSize ;
}else{ //对其他模式的情况进行处理,如果不处理,其他模式(如wrap_content)下也会match_parent
result = 200 ;
if(specMode == MeasureSpec.AT_MOST){
//取较小的一个
result = Math.min(result,specSize) ;
}
}
return result ;
}
/**
* View的绘制
*/
@Override
protected void
onDraw(Canvas canvas) {
super.onDraw(canvas);
//将整个画布绘制成白色
canvas.drawColor(Color.RED);
//设置画笔
Paint pt = new Paint() ;
pt.setStyle(Paint.Style.STROKE);
pt.setColor(Color.BLUE);
pt.setStrokeWidth(2);
//画圆形
canvas.drawCircle(50, 50, 30, pt);
//画正方形矩形
canvas.drawRect(10,90,90,170,pt);
//画矩形
canvas.drawRect(10, 200, 110, 250, pt);
//画圆角矩形
RectF rf1 = new RectF(20,300,120,350) ;
canvas.drawRoundRect(rf1, 10, 10, pt);
//画椭圆
RectF rf2 = new RectF(10,400,120,450) ;
canvas.drawOval(rf2, pt);
//画弧形
RectF rf3 = new RectF(10,500,410,800) ;
canvas.drawArc(rf3,180,120,false,pt);
}
}
自定义View,继承了TextView
效果图;
public class CustomTextView extends TextView {
private Paint mPaint1 = null ;
private Paint mPaint2 = null ;
public CustomTextView(Context context) {
super(context);
initView();
}
public CustomTextView(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
public CustomTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initView();
}
/**
* 这里不需要复写onMeasure()方法,不需要再重新测量大小了,因为TextView已经搞好了
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onDraw(Canvas canvas) {
//绘制外层矩形
canvas.drawRect(0,0,getMeasuredWidth(),getMeasuredHeight(),mPaint1);
canvas.drawRect(5,5, getMeasuredWidth() - 5, getMeasuredHeight() - 5, mPaint2);
//设置偏移距离之前保存画布
canvas.save();
//设置画布的原点偏移距离,x轴偏移10个像素
canvas.translate(5,0);
//父类onDraw()负责绘制文本
super.onDraw(canvas);
//恢复画布
canvas.restore();
}
/**
* 初始化View
*/
private void initView(){
//初始化画笔
mPaint1 = new Paint() ;
mPaint1.setStyle(Paint.Style.FILL);
mPaint1.setColor(Color.RED);
mPaint2 = new Paint();
mPaint2.setStyle(Paint.Style.FILL);
mPaint2.setColor(Color.BLUE);
}
}
自定义View,实现圆形进度图
效果图:
public class CustomCircleProcess extends View {
private int mMeasureWidth = 0 ;
private int mMeasureHeight = 0 ;
//圆形圆心
private float mCircleXY = 0 ;
//圆形半径
private float mCircleRadius = 0 ;
//圆形所用到的画笔
private Paint mCirclePaint ;
//弧形所需要的矩形
private RectF mArcRectF ;
//弧形起始角度,默认值:270
private float mArcStartAngle = 270 ;
//弧形的跨越度数 ,默认值:25
private float mArcSweepAngle = 25 ;
//弧形所需要的画笔
private Paint mArcPaint ;
//绘制文本所需要的Paint
private Paint mTextPaint ;
//文本内容
private String mTextContent = "万紫辉" ;
//文本大小
private float mTextSize = 20f ;
public CustomCircleProcess(Context context) {
super(context);
}
public CustomCircleProcess(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomCircleProcess(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
/**
* 复写onMeasure()方法,测量其大小
* @param widthMeasureSpec
* @param heightMeasureSpec
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//这个View只有MeasureSpec.EXACTLY模式(绝对值或match_parent),没有对其他模式(如:wrap_content)进行处理,
//所以在其他模式下,长宽也都是match_parent
//其实这里不需要wrap_content的情况
mMeasureWidth = MeasureSpec.getSize(widthMeasureSpec) ;
mMeasureHeight = MeasureSpec.getSize(heightMeasureSpec) ;
setMeasuredDimension(mMeasureWidth, mMeasureHeight);
initView();
}
@Override
protected void onDraw(Canvas canvas) {
//画圆
canvas.drawCircle(mCircleXY, mCircleXY, mCircleRadius, mCirclePaint);
//画弧
canvas.drawArc(mArcRectF, mArcStartAngle, mArcSweepAngle, false, mArcPaint);
//画文本
canvas.drawText(mTextContent, mCircleXY, mCircleXY, mTextPaint);
}
private void initView(){
float length = 0f ;
if(mMeasureHeight > mMeasureWidth){
length = mMeasureWidth ;
}else{
length = mMeasureHeight ;
}
mCircleXY = length / 2 ;
mCircleRadius =length / 4 ;
mCirclePaint = new Paint() ;
mCirclePaint.setStyle(Paint.Style.FILL);
mCirclePaint.setColor(Color.RED);
mCirclePaint.setAntiAlias(true);
mArcRectF = new RectF(
(float)(length*0.1),
(float)(length*0.1),
(float)(length*0.9),
(float)(length*0.9)) ;
mArcSweepAngle = 240f ;
mArcPaint = new Paint() ;
mArcPaint.setAntiAlias(true);
mArcPaint.setStyle(Paint.Style.STROKE);
mArcPaint.setStrokeWidth((float)(length*0.1));
mArcPaint.setColor(Color.BLUE);
mTextPaint = new Paint() ;
mTextPaint.setStyle(Paint.Style.STROKE);
mTextPaint.setStrokeWidth(2f);
mTextPaint.setColor(Color.GREEN);
//设置要绘制文本的大小
mTextPaint.setTextSize(mTextSize);
//设置要绘制文本的对其方式
mTextPaint.setTextAlign(Paint.Align.CENTER); //CENTER :文本原点为中心点,LEFT or RIGHT :文本原点为起点
}
/**
* 设置弧形范围
* @param value
*/
public void setSweepAngle(float value){
if(value >= 0){
mArcSweepAngle = value ;
}else{
mArcSweepAngle = 25 ;
}
//重绘视图
this.invalidate();
}
public void setTextContent(String value){
mTextContent = value ;
this.invalidate();
}
}
条形梯度图:
效果图:
public class CustomGradientView extends View {
private Paint mPaint ;
private int mViewWidth ;
private int mViewHeight ;
private int mRectWidth ;
private int mRectHeight ;
private int mRectCount = 10 ;
private int offset = 3 ;
public CustomGradientView(Context context) {
super(context);
initView() ;
}
public CustomGradientView(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
public CustomGradientView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initView();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
/**
* 绘制图像
* @param canvas
*/
@Override
protected void
onDraw(Canvas canvas) {
canvas.drawColor(Color.RED);
for(int i = 0 ; i < mRectCount ; i++){
// 0.0 <= random < 1.0
double random = Math.random() ;
float topDistance = (float)(mRectHeight * random) ;
float leftDistance = (float)(mViewWidth * 0.1 + mRectWidth * i + offset*i) ;
float rightDistance = (float)(mViewWidth * 0.1 + mRectWidth * (i+1) + offset*i) ;
float bottomDistance = mRectHeight ;
canvas.drawRect(leftDistance,topDistance,rightDistance,bottomDistance,mPaint);
}
//过500毫秒在重新绘制
postInvalidateDelayed(500);
}
/**
* 横竖屏变化时,获取其长宽
*/
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mViewWidth = getWidth() ;
mViewHeight = getHeight() ;
mRectHeight = mViewHeight ;
mRectWidth =(int)(( mViewWidth / mRectCount ) * 0.7) ;
}
private void initView(){
//初始化画笔
mPaint = new Paint() ;
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(Color.YELLOW);
}
}
ViewGroup的测量和绘制:
一把要复写:
onMeasure() ; onDraw() ; onLayout()
public class CustomScrollView extends ViewGroup {
//屏幕高度
private int mScreenHeight= 0 ;
private Scroller mScroller;
private int mLastY;
private int mStart;
private int mEnd;
public CustomScrollView(Context context) {
super(context);
initView(context);
}
public CustomScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
initView(context);
}
public CustomScrollView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initView(context);
}
private void initView(Context context){
//获取屏幕高度(像素高度)
WindowManager wm = (WindowManager)(context.getSystemService(Context.WINDOW_SERVICE)) ;
DisplayMetrics dm = new DisplayMetrics() ;
wm.getDefaultDisplay().getMetrics(dm);
mScreenHeight = dm.heightPixels ;
}
/**
* onMeasure() 用于设计ViewGoup的大小
* widthMeasureSpec和heightMeasureSpec封装了ViewGroup的模式和大小,
* 以这个参数,调用measureChild()来测量子View的大小
* @param widthMeasureSpec
* @param heightMeasureSpec
*/
@Override
protected void
onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int count = getChildCount() ;
for (int i = 0; i < count; i++) {
View childView = getChildAt(i) ;
measureChild(childView,widthMeasureSpec,heightMeasureSpec);
}
}
/**
* onLayout() 用于控制ViewGroup的(子View)布局情况
* 主要就是控制View的布局方向,各种外边距的
*/
@Override
protected void
onLayout(boolean changed, int l, int t, int r, int b) {
int count =
getChildCount() ;
//getLayoutParams() 获取View 的布局参数,获取包括外边距,内边距,布局方向,布局的高度
MarginLayoutParams mlp = (MarginLayoutParams)getLayoutParams() ;
mlp.height = mScreenHeight * count;
//setLayoutParams() 设置布局参数
setLayoutParams(mlp);
for(int i = 0 ; i < count ; i++){
View childView =
getChildAt(i) ;
//控制子的布局情况
childView.layout(l,i * mScreenHeight,r,(i+1)*mScreenHeight);
}
}
/**
* onDraw() 用于在ViewGroup上绘的图像,
* 如果不是设置ViewGroup的背景,一般不需要复写ViewGroup的onDraw()方法
* @param canvas
*/
@Override
protected void
onDraw(Canvas canvas) {
super.onDraw(canvas);
}
/**
* 用于监听响应事件
* @param event
* @return
*/
@Override
public boolean
onTouchEvent(MotionEvent event) {
int y = (int) event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mLastY = y;
mStart = getScrollY();
break;
case MotionEvent.ACTION_MOVE:
if (!mScroller.isFinished()) {
mScroller.abortAnimation();
}
int dy = mLastY - y;
if (getScrollY() < 0) {
dy = 0;
}
if (getScrollY() > getHeight() - mScreenHeight) {
dy = 0;
}
scrollBy(0, dy);
mLastY = y;
break;
case MotionEvent.ACTION_UP:
mEnd = getScrollY();
int dScrollY = mEnd - mStart;
if (dScrollY > 0) {
if (dScrollY < mScreenHeight / 3) {
mScroller.startScroll(
0, getScrollY(),
0, -dScrollY);
} else {
mScroller.startScroll(
0, getScrollY(),
0, mScreenHeight - dScrollY);
}
} else {
if (-dScrollY < mScreenHeight / 3) {
mScroller.startScroll(
0, getScrollY(),
0, -dScrollY);
} else {
mScroller.startScroll(
0, getScrollY(),
0, -mScreenHeight - dScrollY);
}
}
break;
}
postInvalidate();
return true;
}
@Override
public void computeScroll() {
super.computeScroll();
if (mScroller.computeScrollOffset()) {
scrollTo(0, mScroller.getCurrY());
postInvalidate();
}
}
}