扫描--不是网传雷达

网传雷达都是使用Handler延时来实现,但是如果延时时间设置比较长就会出现卡帧的情况,

这里使用属性动画获取渐变值,然后赋给矩阵作为旋转的角度,平滑扫描

效果图如上




public class YcSaomiaoView extends View {

    private Paint mPaint,mPaintCircle;
    private float mValue;
    private float initValue=0;
    private float endValue=360;
    private ValueAnimator mAnimator;
    private float mContentWidth;
    private float mContetnHeight;
    private Paint mSmallCirclePaint;
    private Context mContext;
    private Matrix mMatrix;
    private float mCenterX;
    private float mCenterY;
    private float mRadius;
    //用于奇数偶数点的调整计数
    private int count;
    private SparseArray<Point> points=new SparseArray<>();
    private int mMinX;
    private int mMinY;
    private int mMaxX;
    private int mMaxY;

    public void startUp(){
        if(mAnimator!=null&&mAnimator.isRunning()){
            return;
        }
        // 启动就是不断的获取渐变值,然后重绘
        mAnimator = ValueAnimator.ofFloat(initValue,endValue);
        mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mValue = (float) animation.getAnimatedValue();
                postInvalidate();
            }
        });
        mAnimator.setDuration(8000);
        mAnimator.setInterpolator(new LinearInterpolator());
        mAnimator.setRepeatCount(ValueAnimator.INFINITE);
        mAnimator.start();
        mAnimator.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {}

            @Override
            public void onAnimationEnd(Animator animation) {}

            @Override
            public void onAnimationCancel(Animator animation) {}

            @Override
            public void onAnimationRepeat(Animator animation) {
                //第一次走完到后面每次开始时,这个方法调用,我们就开始调整点的位置,但是注意这里只做部分点调整
                count++;
                for(int i=0;i<5;i++){
                    int needX = (int) (mMinX+Math.random()*(mMaxX-mMinX+1));
                    int needY = (int) (mMinY+Math.random()*(mMaxY-mMinY+1));
                    Point point=points.get(i);
                    if(point==null) {
                        point = new Point(needX, needY);
                    }else{
                        if((i+count)%2==0) {
                            point.x = needX;
                            point.y = needY;
                        }
                    }
                    points.append(i,point);
                }
            }
        });


    }
    public void end(){
        if(mAnimator!=null&&mAnimator.isRunning()) {
            mAnimator.cancel();
            initValue = mValue;
            endValue = initValue + 360;
        }
    }
    public YcSaomiaoView(Context context, AttributeSet attrs) {
       this(context, attrs,0);
    }

    public YcSaomiaoView(Context context) {
        this(context,null);
    }

    public YcSaomiaoView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }
   //设置画笔
    private void init(Context context) {
        mContext=context;
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setStyle(Paint.Style.FILL);
        mMatrix = new Matrix();

        mPaintCircle = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaintCircle .setColor(Color.WHITE);
        mPaintCircle .setStyle(Paint.Style.STROKE);


        mSmallCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mSmallCirclePaint .setColor(Color.WHITE);
        mSmallCirclePaint .setStyle(Paint.Style.FILL);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        drawStrokeCircles(canvas);
        drawPoints(canvas);
        canvas.save();
        drawBigCircleandRotateCanvas(canvas);
        canvas.restore();
    }
    //绘制5个白点
    private void drawPoints(Canvas canvas) {
        for(int i=0;i<points.size();i++){
            Point point=points.get(i);
            canvas.drawCircle(point.x,point.y,YcDensityUtil.dip2px(mContext,4),mSmallCirclePaint);
        }

    }
    //画最大的圆圈,这里效果看成以为是扇形,其实是整个圆圈,只不过调整postions
    private void drawBigCircleandRotateCanvas(Canvas canvas) {
        mMatrix.setRotate(mValue,mCenterX,mCenterY);
        canvas.concat(mMatrix);
        canvas.drawCircle(mCenterX,mCenterY,mRadius,mPaint);
    }

   //画多个空心圆
    private void drawStrokeCircles(Canvas canvas) {
        //考虑padding
        float everyLenght=mRadius*1.0f/5;
        for(int i=1;i<6;i++){
                canvas.drawCircle(mCenterX, mCenterY, everyLenght*i, mPaintCircle);
        }

    }
    //保证在除精确测量外还能显示,默认大小为80
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec,heightMeasureSpec);
        //就是当用户的设置为atMost的时候,要指定为Exactly测量
        int contentWidth= YcDensityUtil.dip2px(getContext(),80);
        int contentHeight= YcDensityUtil.dip2px(getContext(),80);
        //用户必须的是精确测量啊
        int height=getMeasurement(contentHeight,heightMeasureSpec);
        int width=getMeasurement(contentWidth,widthMeasureSpec);
        int needValue=Math.min(width,height);
        setMeasuredDimension(needValue,needValue);
    }

    private int getMeasurement(int contentWidth, int widthMeasureSpec) {
        int spcifiWidth=MeasureSpec.getSize(widthMeasureSpec);
        int mode=MeasureSpec.getMode(widthMeasureSpec);
        switch (mode){
            case MeasureSpec.AT_MOST:
                return Math.min(spcifiWidth,contentWidth);
            case MeasureSpec.UNSPECIFIED:
                return contentWidth;
            case MeasureSpec.EXACTLY:
                return spcifiWidth;
            default:
                return 0;
        }
    }
    private int mWidth;
    private int mHeight;

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        if(h!=oldh||w!=oldw){
            mWidth=w;
            mHeight=h;
            //考虑padding的情况
            mContentWidth = mWidth-getPaddingRight()-getPaddingLeft();
            mContetnHeight = mHeight-getPaddingTop()-getPaddingBottom();
            //最大圆的圆心
            mCenterX = mContentWidth*1.0f/2+getPaddingLeft();
            mCenterY = mContetnHeight*1.0f/2+getPaddingTop();
            //最大圆的半径
            mRadius = (mWidth-getPaddingLeft()-getPaddingRight())*1.0f/2;
            //渐变值的颜色
            int[] colors=new int[]{mContext.getResources().getColor(R.color.colorlightwhite), mContext.getResources().getColor(R.color.colorwhite)};
            //针对渐变色来调整显示
            float[] positions=new float[]{0.9f,1.0f};
            SweepGradient sweeep=new SweepGradient(mCenterX,mCenterY,colors,positions);
            mPaint.setShader(sweeep);

            //生成5个随机点在圆圈内,,这里偷懒了,直接让点在圆中正方形的范围
            int length= (int) Math.sqrt(mRadius*mRadius/2);
            int offset= (int) (mRadius-length);
            //生成随机的在圆内的5个点
            mMinX = getPaddingLeft()+offset;
            mMinY = getPaddingTop()+offset;
            mMaxX = mWidth-getPaddingRight()-offset;
            mMaxY = mHeight-getPaddingBottom()-offset;
            for(int i=0;i<5;i++){
                int needX = (int) (mMinX +Math.random()*(mMaxX - mMinX +1));
                int needY = (int) (mMinY +Math.random()*(mMaxY - mMinY +1));
                Point point=points.get(i);
                if(point==null) {
                    point = new Point(needX, needY);
                }
                points.append(i,point);
            }

        }
    }

}

源码链接:点我



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值