废话在前:

昨天打王者,队友实在是太坑了,硬是卡在了星耀3。然后关闭游戏,打开王者荣耀助手,(王者营地),结果网络波动,界面一直在加载状态中,我就在想这个加载动画怎么能实现呢?



两个小正方形左右移动,一个中间大正方形大小随着小正方形靠近而变大,疏远而变小,”加载中“后面的点变化1,2,3,4。

废话不多说,直接上实现效果

实现效果和“王者营地”的差不多,小正方形运动速度可能有些差异,但大抵一致。

实现原理也很简单, 自定义view继承 TextView,因为有文字,所以继承Text View会好些。

5个画笔, 分别绘制左正方形,右正方形,中间大正方形,文字,点。
绘制左右正方形时,
画布先旋转(remote)45度,再移动(translate)
具体代码如下:
自定义View 的 属性注册 attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources><!--王者营地加载--><declare-styleable name="WangZheLoad"><attr name="leftSmallRectColor" format="color"></attr><attr name="rightSmallRectColor" format="color"></attr><attr name="smallRectSize" format="dimension"></attr><attr name="bigRectSize" format="dimension"></attr><attr name="bigRectColor" format="color"></attr></declare-styleable>
</resources>

自定义View WangZheLoad.class

public class WangZheLoad extends androidx.appcompat.widget.AppCompatTextView {//自定义控件的属性说明private int mLeftSmallRectColor = Color.GRAY;//左侧小正方形默认颜色private int mRightSmallRectColor = Color.GRAY;//右侧小正方形默认颜色private int mBigRectColor = Color.GRAY;//中间大正方形默认颜色private int mtextcolor = Color.GRAY;//“加载中”文字默认颜色private int mPointColor = Color.BLACK;//"..."点颜色private int mSmallRectSize = 7;//小正方形默认大小private int mBigRectSize = 15;//中间大正方形默认大小private float progress = 0;//进度,根据不同的进度,左右两小正方形左右移动,以及中间大小的变换private float pp = 0.4f;//命名可能不规范,这个是大正方形边长大小变换率//画笔声明private Paint mLeftPaint;//左侧小正方形画笔private Paint mRightPaint;//右侧小正方形画笔private Paint mBigPaint;//中间大正方形画笔private Paint mTextPaint;//“加载中”文字画笔,不能写死了,有些地方可能不叫“加载中”private Paint mPointPaint;//绘制点,这个点就是加载中后面闪动的点,当然你也可以把“加载中”和点在一个画笔绘制//我分开来主要是怕需求变化,要是老板要求点要加粗、颜色为黑色,文字保持灰色,你就麻烦呀//三个基本构造函数,不多说public WangZheLoad(Context context){this(context,null);}public WangZheLoad(Context context, AttributeSet attrs){this(context,attrs,0);}public WangZheLoad(Context context,AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);//初始化init(context,attrs);}//初始化方法public void init(Context context,AttributeSet attrs){//获得自定义属性,实例化,如果控件使用者未给明,就用默认的。TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.WangZheLoad);mLeftSmallRectColor = array.getColor(R.styleable.WangZheLoad_leftSmallRectColor,mLeftSmallRectColor);mRightSmallRectColor = array.getColor(R.styleable.WangZheLoad_rightSmallRectColor,mRightSmallRectColor);mBigRectColor  = array.getColor(R.styleable.WangZheLoad_bigRectColor,mBigRectColor);mSmallRectSize = array.getDimensionPixelSize(R.styleable.WangZheLoad_smallRectSize,sp2px(mSmallRectSize));mBigRectSize = array.getDimensionPixelSize(R.styleable.WangZheLoad_bigRectSize,sp2px(mBigRectSize));//画笔初始化,对于抗锯齿,防抖动,颜色等封装成一个函数mLeftPaint = new Paint();initPaint(mLeftPaint,mLeftSmallRectColor);mRightPaint = new Paint();initPaint(mRightPaint,mRightSmallRectColor);mBigPaint = new Paint();initPaint(mBigPaint,mBigRectColor);mTextPaint = new Paint();mTextPaint.setTextSize(getTextSize());initPaint(mTextPaint,mtextcolor);mPointPaint = new Paint();mPointPaint.setTextSize(getTextSize());mPointPaint.setFakeBoldText(true);initPaint(mPointPaint,mPointColor);}//画笔初始化public void initPaint(Paint c_paint,int c_color){c_paint.setAntiAlias(true);c_paint.setColor(c_color);c_paint.setDither(true);}//sp  to  px  不多说,就是 sp转化为 px,要是控件使用者用dp怎么办,那就让他自己添加个dp转sp的函数,就你事多public int sp2px(int sp){return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, this.getResources().getDisplayMetrics());}//测量函数@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {//获得 控件总宽度和总高度的模式int widthmode = MeasureSpec.getMode(widthMeasureSpec);int heightmode = MeasureSpec.getMode(heightMeasureSpec);//控件要是填 精确的值,就拿精确的值int widthsize = MeasureSpec.getSize(widthMeasureSpec);int heightsize = MeasureSpec.getSize(heightMeasureSpec);//要是填的是 wrap_content,就默认宽度70, 高度70if (widthmode==MeasureSpec.AT_MOST||heightmode==MeasureSpec.AT_MOST){widthsize = sp2px(70)+getPaddingLeft()+getPaddingRight();heightsize = sp2px(70)+getPaddingTop()+getPaddingBottom();}setMeasuredDimension(widthsize,heightsize);}// 绘制函数@Overrideprotected void onDraw(Canvas canvas) {//画笔通过方法调用修改格式后,需要再次赋值initPaint(mLeftPaint,mLeftSmallRectColor);initPaint(mRightPaint,mRightSmallRectColor);initPaint(mBigPaint,mBigRectColor);mTextPaint.setTextSize(getTextSize());initPaint(mTextPaint,mtextcolor);mPointPaint.setTextSize(getTextSize());mPointPaint.setFakeBoldText(true);initPaint(mPointPaint,mPointColor);/*  move, 左右两正方形移动的距离, 从 最左边移动到最中间*  这个值的算法很简单,你画个图就明白了, 0.7是 根号2的一般,由于根号的值存在小数在取值乘除加减会有误差*  后面的0.73本来应该是0.7,但是误差导致小正方形移动到两边时距离不够,与默认值有差值,所以会有“闪现”的问题*  所以我试着调节,消除闪现,0.73是比较完美的,肉眼看不出问题,建议计算时使用math库*/float move = (float)((getWidth()/2 -0.7*mSmallRectSize-getPaddingLeft())*0.73);canvas.save();//保存画布//画布旋转,第一个是角度, 第二个是旋转中心点的x坐标,第三个是旋转中心的 y坐标canvas.rotate(45,getPaddingLeft()+mSmallRectSize/2,getHeight()/2);//画布平移,x方向平移距离,y方向平移距离,注意小正方形是先顺时针旋转了45度,在进行平移,顺序不能反了//小正方形的移动距离与 progress有关的canvas.translate(move *progress,- move*progress);//这样就可以绘制左边小正方形了canvas.drawRect(getPaddingLeft(),getHeight()/2-mSmallRectSize/2,mSmallRectSize+getPaddingLeft(),getHeight()/2+mSmallRectSize/2,mLeftPaint);canvas.restore();//恢复画布canvas.save();//中间大的正方形绘制,大正方形会随着小正方形的靠近而变大,疏远而变小//大正方形的旋转,这个就简单多了,因为大正方形位置不变canvas.rotate(45,getWidth()/2,getHeight()/2);//要是左边小正方形从左边运动到中间阶段,大正方形的边长大小为基础的0.4*最大边长加上另外随小正方形运动距离改变而变动的0.6if (progress>=0&&progress<1) {pp = (float) 0.6*progress+0.4f;} else if(progress>=1&&progress<2){//要是左边小正方形从中间运动到右边,正方形的边长大小也是为基础的0.4*最大边长加上另外pp=(float)((2-progress)*0.6)+0.4f;}//绘制大正方形canvas.drawRect(getWidth()/2-(mBigRectSize/2)*pp,getHeight()/2-(mBigRectSize/2)*pp,getWidth()/2+(mBigRectSize/2)*pp,getHeight()/2+(mBigRectSize/2)*pp,mBigPaint);canvas.restore();//同理绘制右边小正方形canvas.save();canvas.rotate(45,getWidth()-mSmallRectSize/2-getPaddingRight(),getHeight()/2);canvas.translate(-move*progress,move*progress);canvas.drawRect(getWidth()-mSmallRectSize-getPaddingRight(),getHeight()/2-mSmallRectSize/2,getWidth()-getPaddingRight(),getHeight()/2+mSmallRectSize/2,mRightPaint);canvas.restore();//绘制文字    通过画笔测量“加载中”文字的宽度长度Rect bounds = new Rect();mTextPaint.getTextBounds(getText().toString(),0,getText().toString().length(),bounds);//文字的x坐标int x = getWidth()/2-bounds.width()/2;//基线的获取,网上有很多关于基线的资料,都是固定的样式,没啥好说的Paint.FontMetricsInt fontMetricsInt = new Paint.FontMetricsInt();int dy = (fontMetricsInt.bottom-fontMetricsInt.top)/2-fontMetricsInt.bottom;int baseline = getHeight()/2+dy;canvas.save();//开始绘制canvas.drawText(getText().toString(),x,(float)(baseline+1.4*mBigRectSize),mTextPaint);canvas.restore();//绘制跳动的点if ((progress>=0&&progress<0.5)){canvas.drawText(".",x+bounds.width()+4,(float)(baseline+1.4*mBigRectSize),mTextPaint);}else if (progress>=0.5&&progress<1){canvas.drawText("..",x+bounds.width()+4,(float)(baseline+1.4*mBigRectSize),mPointPaint);}else if (progress>=1&&progress<1.5){canvas.drawText("...",x+bounds.width()+4,(float)(baseline+1.4*mBigRectSize),mPointPaint);}else{canvas.drawText("....",x+bounds.width()+4,(float)(baseline+1.4*mBigRectSize),mPointPaint);}}public void setProgress(float c_progress){this.progress = c_progress;invalidate();//画布刷新}//接下来就是基本的属性外界修改方法,属性的值完全自由调用方法修改public void initStyle(int c_mLeftSmallRectColor,int c_mRightSmallRectColor,int c_mBigRectColor,int c_mtextcolor,int c_mPointColor,int c_mSmallRectSize,int c_mBigRectSize){this.mLeftSmallRectColor = c_mLeftSmallRectColor;this.mRightSmallRectColor = c_mRightSmallRectColor;this.mBigRectColor = c_mBigRectColor;this.mSmallRectSize = c_mSmallRectSize;this.mtextcolor = c_mtextcolor;this.mBigRectSize = c_mBigRectSize;this.mPointColor = c_mPointColor;}
}

代码注释已经很详细了,我就不多b了

接下来就是要再Activity中使用了
activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><LinearLayoutandroid:gravity="center"android:orientation="horizontal"android:layout_width="match_parent"android:layout_height="match_parent"><com.ilikexy.zidingyiview.zidingyi.WangZheLoadandroid:id="@+id/wangzhe_view"android:layout_width="wrap_content"android:layout_height="wrap_content"android:padding="10sp"android:text="加 载 中"android:textSize="10sp"app:leftSmallRectColor="@color/colorPrimaryDark"app:rightSmallRectColor="@color/colorPrimaryDark"app:bigRectColor="@color/colorPrimaryDark"app:smallRectSize="8sp"app:bigRectSize="20sp"></com.ilikexy.zidingyiview.zidingyi.WangZheLoad></LinearLayout></LinearLayout>

MainActivity.class

public class MainActivity extends AppCompatActivity {private WangZheLoad wangzhe_view;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);init();}public void init(){wangzhe_view = (WangZheLoad)findViewById(R.id.wangzhe_view);//动画类,下面会给出这个类的定义ValueAmanitor.catoonShow1(wangzhe_view, 0, 8, 8000);}
}

动画类 ValueAmanitor

public class ValueAmanitor {public static void catoonShow1(final WangZheLoad wangZheLoad, float start, float end, int time){ValueAnimator valueAnimator = ObjectAnimator.ofFloat(start,end);valueAnimator.setDuration(time);//变化总体时间valueAnimator.setInterpolator(new LinearInterpolator());//匀速变化valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator c_animator) {float currentprogress = (Float) c_animator.getAnimatedValue();wangZheLoad.setProgress(currentprogress%2);//调用自定义view中 设置进度的方法,//取余2是为了保证progress在 0----2之间变换}});valueAnimator.start();}
}

要是任何关于这个自定义View问题或建议,那就联系本菜鸡的qq
2569658002.

Android, 自定义View实现 加载进度动画,仿app“王者营地“相关推荐

  1. Android 自定义本地图片加载库,仿微信相册

    总结一下微信的本地图片加载有以下几个特点,也是提高用户体验的关键点 1.缩略图挨个加载,一个一个加载完毕,直到屏幕所有缩略图都加载完成 2.不等当前屏的所有缩略图加载完,迅速向下滑,滑动停止时立即加载 ...

  2. html实现图片加载动画效果,HTML5+javascript实现图片加载进度动画效果

    在网上找资料的时候,看到网上有图片加载进度的效果,手痒就自己也写了一个. 图片加载完后,隐藏loading效果. 想看加载效果,请ctrel+F5强制刷新或者清理缓存. 效果预览: 0% 代码如下: ...

  3. android 自定义加载动画效果,Android 自定义View修炼-自定义加载进度动画LoadingImageView...

    一.概述 本自定义View,是加载进度动画的自定义View,继承于ImageView来实现,主要实现蒙层加载进度的加载进度效果. 支持水平左右加载和垂直上下加载四个方向,同时也支持自定义蒙层进度颜色. ...

  4. android 蒙层动画,Android酷炫加载进度动画

    一.概述 本自定义动画进度酷炫View,是加载进度动画的自定义View,继承于ImageView来实现,主要实现蒙层加载进度的加载进度效果. 支持水平左右加载和垂直上下加载四个方向,同时也支持自定义蒙 ...

  5. android dialog 自定义布局,Android自定义Dialog实现加载对话框效果

    前言 最近开发中用到许多对话框,之前都是在外面的代码中创建AlertDialog并设置自定义布局实现常见的对话框,诸如更新提示等含有取消和删除两个按钮的对话框我们可以通过代码创建一个AlertDial ...

  6. android+清除循环动画,android自定义View之(4)-一键清除动画

    android自定义View之(四)------一键清除动画 1.前言: 自己也是参考别人的一些自定义view例子,学习了一些基本的自定义view的方法.今天,我参考了一些资料,再结合自已的一些理解, ...

  7. 安卓自定义View实现加载gif图片

    开题:加载GIF的场景在安卓开发中还比较常见,网上也有一些三方法的框架会支持对gif的加载,在上篇博客为大家推荐的图片加载库Glide也支持gif的加载Glide工具类的简单封装,今天给大家分享通过自 ...

  8. 安卓自定义原户型加载进度条的实现

    最近开发公司新产品,设计师设计了一个加载进度的圆弧型界面,觉得挺不错的,先发出效果图来让大家看看 先上完成效果: 从这两张图上,我们可以大致总结出几个ui要点: 1:两层进度条,围成一个大的圆弧,并且 ...

  9. android自定义水波纹,android 自定义view-水波纹进度球

    android 进阶之路-自定义view-水波纹进度球 如果你是老司机,一看标题就会就return吧,嘻嘻. 在我们的日常开发中自定义控件还是用的挺多的,设计师或者产品为了更好的漂亮,美观,交互都会做 ...

  10. android自定义View之(四)------一键清除动画

    1.前言: 自己也是参考别人的一些自定义view例子,学习了一些基本的自定义view的方法.今天,我参考了一些资料,再结合自已的一些理解,做了一个一键清除的动画.当年,我实现这个是用了几张图片,采用F ...

最新文章

  1. mac 显示隐藏文件
  2. linux coredump配置与调试
  3. [Ubuntu] SVN常用的批量操作
  4. 存储过程中将sql语句结果赋值给变量
  5. C语言中结构体的初始化
  6. LiveVideoStackCon深圳 - 洞察多媒体技术生态趋势与机会
  7. 猫大叫,鼠速逃,人醒了
  8. SMOTE/SMOTEEN 处理不平衡数据集
  9. 继续说invoke伪指令
  10. UICollectionView reloadData后cell被隐藏
  11. ASP.NET MVC3 中的AJAX
  12. 简述计算机进行远程桌面管理操作过程,服务器应用之“远程桌面连接”(操作篇)...
  13. 【Java】Java多线程神器:join使用及原理
  14. Realm Swift
  15. SQL注入—MYSQL基础语句(持续更新)附图
  16. SPI 总线3-line、4-line的定义
  17. wifi无法获取ip地址的解决方法
  18. 各应用市场(安卓)的入口整理:
  19. html做相册浏览,ul结合CSS制作网页相册滑动浏览效果
  20. IRC(Internet Relay Chat)(因特网中继聊天)协议——RFC1459文档要点总结

热门文章

  1. 程序员的那些需要反省的地方
  2. 【OpenPCDet】稀疏卷积SPConv-v1.2代码解读(1)
  3. 漏洞扫描工具OWASP ZAP的下载、安装、使用教程
  4. sqlserver 数据库 事务日志已满
  5. Android Studio 获取数字签名信息(SHA1)
  6. IIS怎么安装SSL域名证书?
  7. 我的第一个基于python的socket程序
  8. mpvue实现小程序登录和授权获取用户信息
  9. 吹风机对头发的伤害有哪些?如何挑选一款适合自己的吹风机呢?
  10. 网站设计中如何运用色彩搭配来提升页面导航性