Android实现两圆点之间来回移动加载进度

 更新时间:2020年06月19日 11:39:54   作者:kincai  
这篇文章主要为大家详细介绍了Android实现两圆点之间来回移动加载进度,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

本文实例为大家分享了Android实现两圆点之间来回移动加载进度的具体代码,供大家参考,具体内容如下

一、前言

最近喜欢上自定义控件,喜欢实现一些简约有趣的控件,也好巩固下以前学得知识和不断的学习新知识,程序员嘛,活到老学到老。

这篇文章接着上一篇文章:Android_自定义控件之水平圆点加载进度条,类似的实现方式,都是些比较简单的view绘制。

二、实现

先看下实现的效果吧:

说下实现思路:圆点x轴会有个位移变化量,当位移达到圆点直径+圆点间距之和就回改变方向(改变方向就是通过变化量值不断增加和不断减少来实现),可能写的有点模糊,接下来看代码:

package com.kincai.testcustomview_dotalternatelyprogress;
 
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
 
/**
 * Copyright (C) 2015 The KINCAI Open Source Project
 * .
 * Create By KINCAI
 * .
 * Time 2017-06-16 21:44
 * .
 * Desc 两个源点来回移动
 */
 
public class DotAlternatelyView extends View {
 private final String TAG = this.getClass().getSimpleName();
 private Paint mPaint = new Paint();
 /**
  * 可视为左边圆点颜色值
  */
 private int mLeftColor;
 /**
  * 可视为右边圆点颜色值
  */
 private int mRightColor;
 /**
  * 圆点半径
  */
 private int mDotRadius;
 /**
  * 圆点间距
  */
 private int mDotSpacing;
 /**
  * 圆点位移量
  */
 private float mMoveDistance;
 /**
  * 圆点移动率
  */
 private float mMoveRate;
 /**
  * 以刚开始左边圆点为准 向右移
  */
 private final int DOT_STATUS_RIGHT = 0X101;
 /**
  * 以刚开始左边圆点为准 圆点移动方向-向左移
  */
 private final int DOT_STATUS_LEFT = 0X102;
 /**
  * 以刚开始左边圆点为准,圆点移动方向
  */
 private int mDotChangeStatus = DOT_STATUS_RIGHT;
 /**
  * 圆点透明度变化最大(也就是透明度在255-mAlphaChangeTotal到255之间)
  */
 private int mAlphaChangeTotal = 130;
 /**
  * 透明度变化率
  */
 private float mAlphaChangeRate;
 /**
  * 透明度改变量
  */
 private float mAlphaChange;
 
 public DotAlternatelyView(Context context) {
  this(context, null);
 }
 
 public DotAlternatelyView(Context context, @Nullable AttributeSet attrs) {
  this(context, attrs, 0);
 }
 
 public DotAlternatelyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
  super(context, attrs, defStyleAttr);
  TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.DotAlternatelyView, defStyleAttr, 0);
  initAttributes(typedArray);
  typedArray.recycle();
  init();
 }
 
 private void initAttributes(TypedArray Attributes) {
  mLeftColor = Attributes.getColor(R.styleable.DotAlternatelyView_dot_dark_color, ContextCompat.getColor(getContext(), R.color.colorPrimary));
  mRightColor = Attributes.getColor(R.styleable.DotAlternatelyView_dot_light_color, ContextCompat.getColor(getContext(), R.color.colorAccent));
  mDotRadius = Attributes.getDimensionPixelSize(R.styleable.DotAlternatelyView_dot_radius, DensityUtils.dp2px(getContext(), 3));
  mDotSpacing = Attributes.getDimensionPixelSize(R.styleable.DotAlternatelyView_dot_spacing, DensityUtils.dp2px(getContext(), 6));
  mMoveRate = Attributes.getFloat(R.styleable.DotAlternatelyView_dot_move_rate, 1.2f);
 }
 
 /**
  * 初始化
  */
 private void init() {
  //移动总距离/移动率 = alpha总变化/x
  //x = 移动率 * alpha总变化 / 移动总距离
  mAlphaChangeRate = mMoveRate * mAlphaChangeTotal / (mDotRadius * 2 + mDotSpacing);
  mPaint.setColor(mLeftColor);
  mPaint.setAntiAlias(true);
  mPaint.setStyle(Paint.Style.FILL);
  Log.e(TAG, " aaaa " + mAlphaChangeRate);
 }
 
 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  //测量宽高
  int widthMode = MeasureSpec.getMode(widthMeasureSpec);
  int widthSize = MeasureSpec.getSize(widthMeasureSpec);
  int heightMode = MeasureSpec.getMode(heightMeasureSpec);
  int heightSize = MeasureSpec.getSize(heightMeasureSpec);
  int width;
  int height;
 
  if (widthMode == MeasureSpec.EXACTLY) {
   width = widthSize;
   Log.e(TAG, "onMeasure MeasureSpec.EXACTLY widthSize=" + widthSize);
  } else {
   //指定最小宽度所有圆点加上间距的宽度, 以最小半径加上间距算总和再加上最左边和最右边变大后的距离
   width = (mDotRadius * 2) * 2 + mDotSpacing;
   Log.e(TAG, "onMeasure no MeasureSpec.EXACTLY widthSize=" + widthSize + " width=" + width);
   if (widthMode == MeasureSpec.AT_MOST) {
    width = Math.min(width, widthSize);
    Log.e(TAG, "onMeasure MeasureSpec.AT_MOST width=" + width);
   }
 
  }
 
  if (heightMode == MeasureSpec.EXACTLY) {
   height = heightSize;
   Log.e(TAG, "onMeasure MeasureSpec.EXACTLY heightSize=" + heightSize);
  } else {
   height = mDotRadius * 2;
   Log.e(TAG, "onMeasure no MeasureSpec.EXACTLY heightSize=" + heightSize + " height=" + height);
   if (heightMode == MeasureSpec.AT_MOST) {
    height = Math.min(height, heightSize);
    Log.e(TAG, "onMeasure MeasureSpec.AT_MOST height=" + height);
   }
 
  }
  setMeasuredDimension(width, height);
 }
 
 @Override
 protected void onDraw(Canvas canvas) {
  //左边圆点起点x轴
  int startPointX = getWidth() / 2 - (2 * mDotRadius * 2 + mDotSpacing) / 2 + mDotRadius;
  //左边圆点起点y轴
  int startPointY = getHeight() / 2;
  //向右移 位移要增加对应透明度变化量也需要增加 反之都需要减小
  if (mDotChangeStatus == DOT_STATUS_RIGHT) {
   mMoveDistance += mMoveRate;
   mAlphaChange += mAlphaChangeRate;
  } else {
   mAlphaChange -= mAlphaChangeRate;
   mMoveDistance -= mMoveRate;
  }
  Log.e(TAG, "mAlphaChange " + mAlphaChange);
  //当移动到最右 那么需要改变方向 反过来
  if (mMoveDistance >= mDotRadius * 2 + mDotSpacing && mDotChangeStatus == DOT_STATUS_RIGHT) {
   mDotChangeStatus = DOT_STATUS_LEFT;
   mMoveDistance = mDotRadius * 2 + mDotSpacing;
   mAlphaChange = mAlphaChangeTotal;
  } else if (mMoveDistance <= 0 && mDotChangeStatus == DOT_STATUS_LEFT) { //当移动到最座 那么需要改变方向 反过来
   mDotChangeStatus = DOT_STATUS_RIGHT;
   mMoveDistance = 0f;
   mAlphaChange = 0f;
  }
 
  //因为两个圆点可能会给定不同的颜色来显示 所以提供两种颜色设置mLeftColor和mRightColor
  mPaint.setColor(mLeftColor);
  mPaint.setAlpha((int) (255 - mAlphaChange));
  canvas.drawCircle(startPointX + mMoveDistance, startPointY, mDotRadius, mPaint);
  mPaint.setColor(mRightColor);
  mPaint.setAlpha((int) (255 - mAlphaChange));
  canvas.drawCircle(startPointX + mDotRadius * 2 - mMoveDistance + mDotSpacing, startPointY, mDotRadius, mPaint);
 
  invalidate();
 }
}

要是不容易理解的话,下载源码运行再对着源码看会容易理解

源码下载github:Android移动加载进度

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • Android中Intent传递对象的3种方式详解

    Android中Intent传递对象的3种方式详解

    这篇文章给大家介绍了Android中Intent传递对象的3种方式,分别是Serializable 方式、Parcelable 方式以及JSON 方式,有需要的朋友们可以一起参考借鉴,下面来一起看看吧。
    2016-09-09
  • Android编程实现的短信编辑器功能示例

    Android编程实现的短信编辑器功能示例

    这篇文章主要介绍了Android编程实现的短信编辑器功能,涉及Android权限控制、界面布局及短信功能相关操作技巧,需要的朋友可以参考下
    2017-08-08
  • android开发框架afinal使用方法小结

    android开发框架afinal使用方法小结

    这篇文章主要为大家详细总结了android开发框架afinal使用方法,注解功能、文件上传下载功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-11-11
  • Android Canvas绘制文字横纵向对齐

    Android Canvas绘制文字横纵向对齐

    这篇文章主要介绍了Android Canvas绘制文字横纵向对齐,Align属性决定了使用该画笔时,相较于绘制点的水平对称方式,分别是LEFT、CENTER、RIGHT,更多相关内容需要的小伙伴可以参考下面文章详细内容
    2022-06-06
  • Android编程创建桌面快捷方式的常用方法小结【2种方法】

    Android编程创建桌面快捷方式的常用方法小结【2种方法】

    这篇文章主要介绍了Android编程创建桌面快捷方式的常用方法,结合实例形式总结分析了2种常见的实现方法与相关操作技巧,需要的朋友可以参考下
    2017-02-02
  • Android事件冲突解决悬浮窗拖拽处理方案

    Android事件冲突解决悬浮窗拖拽处理方案

    这篇文章主要为大家介绍了Android事件冲突解决悬浮窗拖拽处理方案,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-03-03
  • Android开发中Widget的生命周期实例分析

    Android开发中Widget的生命周期实例分析

    这篇文章主要介绍了Android开发中Widget的生命周期,结合实例形式分析了Android开发中Widget生命周期所涉及的常用方法与使用技巧,代码备有详尽的注释便于理解,需要的朋友可以参考下
    2016-02-02
  • Android仿QQ分组实现二级菜单展示

    Android仿QQ分组实现二级菜单展示

    这篇文章主要为大家详细介绍了Android仿QQ分组实现二级菜单展示,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-09-09
  • Android自定义流式布局实现淘宝搜索记录

    Android自定义流式布局实现淘宝搜索记录

    这篇文章主要为大家详细介绍了Android自定义流式布局实现淘宝搜索记录,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-10-10
  • Android创建悬浮窗的完整步骤

    Android创建悬浮窗的完整步骤

    这篇文章主要给大家介绍了关于Android创建悬浮窗的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-05-05

最新评论