最近因为项目的需求做的一个加载中圆,刚好记录一下

/** * 自定义加载中的圆,主要代码 */public class LoadingSearchView extends View {    private Paint mCirclePaint;    private Paint mInnerPaint;    private float mCircleRadius;    private final static float RADIUS = 180f;    private final static float INITIAL_ANGLE = 90f;    /**     * 旋转角度     */    private float mRotationAngle = 0;    /**     * 实心半圆最初的位置     */    private float mCircleStartAngle;    /**     * 实心半圆应该绘制多大的     */    private float mCircleSweepAngle;    /**     * 文字的画笔     */    private Paint mTextPaint;    /**     * 外圈圆的宽     */    private float mLoadingRoundWidth;    /**     * 外圈圆与内圆的间距     */    private float mSpacingOfCircles;    /**     * 内圆的颜色     */    private int mInnerCircleColor;    /**     * 设置几个默认的值     */    private float mInitialDefaultSize, mLoadingRoundDefaultWidth, mSpacingOfDefaultCircles;    public LoadingSearchView(Context context) {        this(context, null);    }    public LoadingSearchView(Context context, @Nullable AttributeSet attrs) {        this(context, attrs, 0);    }    public LoadingSearchView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        initDefaultValue();        initAttributeSet(attrs);        setCirclePaint();        initTextPaint();    }    /**     * 初始化一些默认值     */    private void initDefaultValue() {        mCircleStartAngle = INITIAL_ANGLE;        mLoadingRoundDefaultWidth = dp2px(getContext(), 8);        mInitialDefaultSize = sp2px(getContext(), 50);        mSpacingOfDefaultCircles = dp2px(getContext(), 5);    }    /**     * 初始化画笔的颜色     */    private void initTextPaint() {        mTextPaint = new Paint();        mTextPaint.setAntiAlias(true);        mTextPaint.setTextSize(sp2px(getContext(), 16));        mTextPaint.setColor(Color.WHITE);    }    /**     * 初始化圆的画笔     */    private void setCirclePaint() {        mCirclePaint = initCircle();        mCirclePaint.setStyle(Paint.Style.STROKE);        mCirclePaint.setStrokeWidth(mLoadingRoundWidth);        mInnerPaint = initCircle();        mInnerPaint.setStyle(Paint.Style.FILL);        mInnerPaint.setColor(mInnerCircleColor);    }    private Paint initCircle() {        Paint paint = new Paint();        paint.setAntiAlias(true);        paint.setStrokeCap(Paint.Cap.ROUND);        paint.setStrokeJoin(Paint.Join.ROUND);        return paint;    }    private void initAttributeSet(AttributeSet attrs) {        TypedArray array = getContext().obtainStyledAttributes(attrs, R.styleable.LoadingSearchView);        mLoadingRoundWidth = array.getDimension(R.styleable.LoadingSearchView_loading_round_width, mLoadingRoundDefaultWidth);        mSpacingOfCircles = array.getDimension(R.styleable.LoadingSearchView_spacing_of_circles, mSpacingOfDefaultCircles);        float defaultCircle = mLoadingRoundDefaultWidth + mSpacingOfDefaultCircles + mInitialDefaultSize;        mCircleRadius = array.getDimension(R.styleable.LoadingSearchView_loading_circle_radius, defaultCircle);        mInnerCircleColor = array.getColor(R.styleable.LoadingSearchView_inner_circle_color, Color.parseColor("#00d8c9"));        array.recycle();    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        int measuredWidth = getMeasuredWidth();        float digitalDifference = (measuredWidth - mCircleRadius * 2) / 2;        if (digitalDifference < 0) {            setMeasuredDimension((int) (mCircleRadius * 2), (int) (mCircleRadius * 2));        }        drawOuterCircle(digitalDifference, canvas);        drawInnerCircle(digitalDifference, canvas);        drawSuccessAnimator(digitalDifference, canvas);    }    private void drawSuccessAnimator(float digitalDifference, Canvas canvas) {        if (mCircleSweepAngle >= 360) {            String success = "成功";            Rect bounds = new Rect();            mTextPaint.getTextBounds(success, 0, success.length(), bounds);            float startX = mCircleRadius - bounds.right / 2;            Paint.FontMetricsInt fontMetricsInt = mTextPaint.getFontMetricsInt();            int dy = (fontMetricsInt.top - fontMetricsInt.bottom) / 2 - fontMetricsInt.top;            float baseLine = mCircleRadius + dy;            canvas.drawText(success, startX + digitalDifference, baseLine + digitalDifference, mTextPaint);        }    }    private void drawInnerCircle(float digitalDifference, Canvas canvas) {        RectF circleRectF = new RectF(mLoadingRoundWidth + mSpacingOfCircles + digitalDifference, mLoadingRoundWidth + mSpacingOfCircles + digitalDifference,                (mCircleRadius * 2 - (mLoadingRoundWidth + mSpacingOfCircles)) + digitalDifference, (mCircleRadius * 2 - (mLoadingRoundWidth + mSpacingOfCircles)) + digitalDifference);        canvas.drawArc(circleRectF, mCircleStartAngle, mCircleSweepAngle, false, mInnerPaint);    }    /**     * 画外圆     *     * @param digitalDifference     * @param canvas     */    private void drawOuterCircle(float digitalDifference, Canvas canvas) {        RectF rectF = new RectF(mLoadingRoundWidth / 2 + digitalDifference, mLoadingRoundWidth / 2 + digitalDifference,                (mCircleRadius * 2 - mLoadingRoundWidth / 2) + digitalDifference, (mCircleRadius * 2 - mLoadingRoundWidth / 2) + digitalDifference);        mCirclePaint.setColor(Color.parseColor("#00d8c9"));        canvas.drawArc(rectF, mRotationAngle, RADIUS, false, mCirclePaint);        mCirclePaint.setColor(Color.parseColor("#64e27f"));        float rotationAngle = mRotationAngle + RADIUS;        canvas.drawArc(rectF, rotationAngle, RADIUS, false, mCirclePaint);    }    public void setRotationAngle(float rotationAngle) {        mRotationAngle = mRotationAngle + 3;        float angle = RADIUS * rotationAngle;        mCircleStartAngle = INITIAL_ANGLE - angle;        mCircleSweepAngle = angle * 2;        invalidate();    }    /**     * dp转px     */    public float dp2px(Context context, float dpVal) {        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,                dpVal, context.getApplicationContext().getResources().getDisplayMetrics());    }    /**     * sp转px     */    public int sp2px(Context context, float spVal) {        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,                spVal, context.getApplicationContext().getResources().getDisplayMetrics());    }}

自定义的属性如下,在values文件中创建文件attrs.xml:

                                    

activity页面的布局也是只有一个加载的view,如下:

    

MainActivity里面的代码如下:

public class MainActivity extends AppCompatActivity {    private LoadingSearchView mTestView;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        mTestView = findViewById(R.id.test_view);        mTestView.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {            // 创建一个属性动画,来启动圆的动画                ObjectAnimator animator = ObjectAnimator.ofFloat(mTestView, "rotationAngle", 1f);                animator.setInterpolator(new DecelerateInterpolator());                animator.setDuration(4000);                animator.start();            }        });    }}

更多相关文章

  1. Android底部导航栏实现(一)之BottomNavigationBar
  2. Android(安卓)Shader应用开发之雷达扫描效果
  3. Bitmap and DrawPoint
  4. Android实现圆角矩形和圆形ImageView的方式
  5. AES加解密在Android(安卓)4.2上的Encryption error
  6. 使用百度地图SDK 这是之前版本 现在的sdk v2-1-2使用方法完全改
  7. Android培训班(38)
  8. Android系统启动流程之Init说明
  9. flutter集成推送功能-小米推送集成

随机推荐

  1. Android用户界面
  2. Android适配全攻略
  3. Android 移植到 C#
  4. webview
  5. Android高仿网易新闻客户端之侧滑菜单
  6. Android MuPDF 部署
  7. Android Binder入门指南之addService详解
  8. Android,谁动了我的内存
  9. 使用U3D 实现 Android(安卓)Launcher(提
  10. android 按行读取txt文本内容