android 积累一些自定义view的知识
16lz
2021-01-24
1.仿造QQ计步器(用于统计的自定义View)
步骤:
1.定义属性
<?xml version="1.0" encoding="utf-8"?>
2.拿属性
public TongjiView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); //获取自定义属性 Log.i(TAG,"TongjiView3"); TypedArray array=context.obtainStyledAttributes(attrs,R.styleable.TongjiView); mFirstColor=array.getColor(R.styleable.TongjiView_firstColor, Color.GRAY); mSecondColor=array.getColor(R.styleable.TongjiView_secondColor,Color.BLACK); mTongjiTextColor=array.getColor(R.styleable.TongjiView_tongjiTextColor,Color.BLACK); mBorderWidth= (int) array.getDimension(R.styleable.TongjiView_borderWidth,20); mTongjiTextSize=array.getDimensionPixelSize(R.styleable.TongjiView_tongjiTextSize,20); mTongjiText=array.getString(R.styleable.TongjiView_tongjiText); array.recycle(); initPaint(); initTextPaint(); }
3.画两条弧和文字
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); Log.i(TAG,"onDraw"); mPaint.setColor(mFirstColor); //画第一层 int circleCenter=getWidth()/2; int radius=getHeight()/2-mBorderWidth/2;//直接减去画笔的宽度也行 RectF rectF=new RectF(circleCenter-radius,circleCenter-radius,circleCenter+radius,circleCenter+radius); canvas.drawArc(rectF,135,270,false,mPaint); //画第二层 mPaint.setColor(mSecondColor); canvas.drawArc(rectF,135,(270*currentSecondProgress)/maxSecondProgress,false,mPaint); //画文字 Rect textBounds=new Rect(); mTextPaint.getTextBounds(mTongjiText,0,mTongjiText.length(),textBounds); Paint.FontMetricsInt fontMetrics = mTextPaint.getFontMetricsInt(); int baseLineY = getHeight()/2 - (fontMetrics.bottom-fontMetrics.top)/2- fontMetrics.top; canvas.drawText(mTongjiText,getWidth()/2-textBounds.width()/2,baseLineY,mTextPaint); }
package com.wyt.hcy.testcustomview;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.support.annotation.Nullable;import android.util.AttributeSet;import android.util.Log;import android.view.View;/** * Created by hcy on 2017/5/27 0027. */public class TongjiView extends View { private int mFirstColor; private int mSecondColor; private int mBorderWidth; private int mTongjiTextColor; private int mTongjiTextSize; private Paint mPaint; private static final String TAG="TongjiView"; private int maxSecondProgress=100; private int currentSecondProgress=80; private Paint mTextPaint; private String mTongjiText; public TongjiView(Context context) { this(context, null); Log.i(TAG,"TongjiView1"); } public TongjiView(Context context, @Nullable AttributeSet attrs) { this(context, attrs,0); Log.i(TAG,"TongjiView2"); } public TongjiView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); //获取自定义属性 Log.i(TAG,"TongjiView3"); TypedArray array=context.obtainStyledAttributes(attrs,R.styleable.TongjiView); mFirstColor=array.getColor(R.styleable.TongjiView_firstColor, Color.GRAY); mSecondColor=array.getColor(R.styleable.TongjiView_secondColor,Color.BLACK); mTongjiTextColor=array.getColor(R.styleable.TongjiView_tongjiTextColor,Color.BLACK); mBorderWidth= (int) array.getDimension(R.styleable.TongjiView_borderWidth,20); mTongjiTextSize=array.getDimensionPixelSize(R.styleable.TongjiView_tongjiTextSize,20); mTongjiText=array.getString(R.styleable.TongjiView_tongjiText); array.recycle(); initPaint(); initTextPaint(); } private void initTextPaint() { mTextPaint=new Paint(); mTextPaint.setAntiAlias(true);//抗锯齿 mTextPaint.setStyle(Paint.Style.STROKE); mTextPaint.setTextSize(mTongjiTextSize); mTextPaint.setColor(mTongjiTextColor); } private void initPaint() { Log.i(TAG,"initPaint"); mPaint=new Paint(); mPaint.setAntiAlias(true);//抗锯齿 mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeCap(Paint.Cap.ROUND); mPaint.setStrokeWidth(mBorderWidth); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // super.onMeasure(widthMeasureSpec, heightMeasureSpec); Log.i(TAG,"onMeasure"); int width = 0,height = 0; int widthMode=MeasureSpec.getMode(widthMeasureSpec); int widthSize=MeasureSpec.getSize(widthMeasureSpec); int heightMode=MeasureSpec.getMode(heightMeasureSpec); int heightSize=MeasureSpec.getSize(heightMeasureSpec); //保持一个正方形 Log.i(TAG,"widthSize:"+widthSize); Log.i(TAG,"heightSize:"+heightSize); setMeasuredDimension(widthSize,heightSize); /*if (widthMode==MeasureSpec.AT_MOST){ Log.i(TAG,"widthMode==MeasureSpec.AT_MOST"); width=40;//设置最小宽度 }else if (widthMode==MeasureSpec.EXACTLY){ Log.i(TAG,"widthMode==MeasureSpec.EXACTLY"); width=widthSize; } if (heightMode==MeasureSpec.AT_MOST){ Log.i(TAG,"heightMode==MeasureSpec.AT_MOST"); height=40; }else if (heightMode==MeasureSpec.EXACTLY){ height=heightSize; Log.i(TAG,"heightMode==MeasureSpec.EXACTLY"); } //宽高不一致,获取最小的 int length=width>height?height:width; Log.i(TAG,"length:"+length); setMeasuredDimension(width>height?height:width,width>height?height:width); //保持一个正方形 //*/ } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); Log.i(TAG,"onDraw"); mPaint.setColor(mFirstColor); //画第一层 int circleCenter=getWidth()/2; int radius=getHeight()/2-mBorderWidth/2;//直接减去画笔的宽度也行 RectF rectF=new RectF(circleCenter-radius,circleCenter-radius,circleCenter+radius,circleCenter+radius); canvas.drawArc(rectF,135,270,false,mPaint); //画第二层 mPaint.setColor(mSecondColor); canvas.drawArc(rectF,135,(270*currentSecondProgress)/maxSecondProgress,false,mPaint); //画文字 Rect textBounds=new Rect(); mTextPaint.getTextBounds(mTongjiText,0,mTongjiText.length(),textBounds); Paint.FontMetricsInt fontMetrics = mTextPaint.getFontMetricsInt(); int baseLineY = getHeight()/2 - (fontMetrics.bottom-fontMetrics.top)/2- fontMetrics.top; canvas.drawText(mTongjiText,getWidth()/2-textBounds.width()/2,baseLineY,mTextPaint); }}
难点:
1.画弧的时候,
定义中心点,也就是自定view的中心点坐标(getWidth()/2,getHeight/2)
定义RectF
2.画文字的时候,如何确定基线
baseLineY = centerY - (fm.bottom-fm.top)/2- fm.top;
3.知识点:View的四个属性:
top:相对于父容器的左上纵坐标
left:相对于父容器的左上横坐标
right:相对于父容器的右下横坐标
bottom:相对于父容器的右下纵坐标
相对坐标 平移的时候 值不会改变
View 的其他四个参数:
X:View的左上角相对于屏幕的横坐标
Y:View的左上角相对于屏幕的纵坐标
translationX:貌似可以理解为父容器的相对于屏幕的横坐标
translationY::貌似可以理解为父容器的相对于屏幕的纵坐标
4.实现View滑动的三种方式
1.通过View本身的scrollTo/scrollBy方法
2.通过平移动画
3.通过layoutparams
更多相关文章
- Android(安卓)仿今日头条频道管理(上)(GridView之间Item的移动和拖
- android PopupWindow的用法
- Android打造万能适配器--RecyclerView
- Android(安卓)开发中Parcel存储类型和数据容器
- Android经典完美退出方法
- android 退出整个程序
- Android(安卓)View和ViewGroup
- Android(安卓)UI 之SlidingMenu实现方法(二)
- 【转】Android(安卓)statusBar添加back,home,menu按钮