当前位置: 移动技术网 > IT编程>移动开发>Android > Android仿360市场下载按钮的实现方法

Android仿360市场下载按钮的实现方法

2019年07月24日  | 移动技术网IT编程  | 我要评论

明星走光大全,服装饰品,就是色

首先来看看效果图:

无论多复杂的动画我们都是可以分割成小单元的,然后分步来实现。这个动画大概分为收缩,准备,加载,完成几个部分。为此定义一个枚举类来描述view的状态。

public enum status { normal, start, pre, expand, load, end }

收缩动画

使用动画不断改变圆角矩形的宽度,触发重绘。代码如下:

private void initanim() {
 animation animation1 = new animation() {
 @override
 protected void applytransformation(float interpolatedtime, transformation t) {
 mcurrlength = mwidth * (1 - interpolatedtime);
 if (mcurrlength < mheight) {
  mcurrlength = mheight;
  clearanimation();
  mangleanim.start();
 }
 invalidate();
 }
 };

 animation1.setduration(mshrinkduration);
 animation1.setinterpolator(new linearinterpolator());
 animation1.setanimationlistener(new animation.animationlistener() {
 @override
 public void onanimationstart(animation animation) {
 mstatus = status.start;
 }

 @override
 public void onanimationend(animation animation) {

 }

 @override
 public void onanimationrepeat(animation animation) {

 }
 });
 mshrinkanim = animation1;
 ...
}

ondraw中绘制:

if (mstatus == status.start || mstatus == status.normal) {
 float left = (mwidth - mcurrlength) / 2f;
 float right = (mwidth + mcurrlength) / 2f;
 float r = mheight / 2f;
 canvas.drawroundrect(new rectf(left, 0, right, mheight), r, r, mbgpaint);
 if (mstatus == status.normal) {
 paint.fontmetrics fm = mtextpaint.getfontmetrics();
 float y = mheight / 2 + (fm.descent - fm.ascent) / 2 - fm.descent;
 canvas.drawtext("下载", mwidth / 2, y, mtextpaint);
 }
 }

准备动画

此时旋转动画,是通过canvas绘制背景圆和三个小圆,然后不断旋转画布来实现的,具体求圆心坐标和角度动画我们直接看代码:

valueanimator animator = valueanimator.offloat(0, 1);
 animator.addupdatelistener(new valueanimator.animatorupdatelistener() {
 @override
 public void onanimationupdate(valueanimator animation) {
 mangle += mpreanimspeed;
 invalidate();
 }
 });
 animator.addlistener(new animator.animatorlistener() {
 @override
 public void onanimationstart(animator animation) {
 mstatus = status.pre;
 }

 @override
 public void onanimationend(animator animation) {
 mangleanim.cancel();
 startanimation(mtranslateanim);
 }

 @override
 public void onanimationcancel(animator animation) {

 }

 @override
 public void onanimationrepeat(animator animation) {

 }
 });

 animator.setduration(mpreanimduration);
 animator.setinterpolator(new linearinterpolator());
 mangleanim = animator;

ondraw中绘制代码:

if (mstatus == status.pre) {
 canvas.drawcircle(mwidth / 2f, mheight / 2f, mheight / 2f, mbgpaint);
 canvas.save();
 mtextpaint.setstyle(paint.style.fill);
 canvas.rotate(mangle, mwidth / 2, mheight / 2);
 //大圆的圆心 半径
 float cx = mwidth / 2f;
 float cy = mheight / 2f;
 float radius = mheight / 2 / 3f;
 canvas.drawcircle(cx, cy, radius, mtextpaint);
 //上方小圆的参数
 float rr = radius / 2f;
 float cyy = mheight / 2 - (radius + rr / 3);
 canvas.drawcircle(cx, cyy, rr, mtextpaint);
 //左下小圆参数
 float cxx = (float) (cx - math.sqrt(2) / 2f * (radius + rr / 3f));
 cyy = (float) (mheight / 2 + math.sqrt(2) / 2f * (radius + rr / 3f));
 canvas.drawcircle(cxx, cyy, rr, mtextpaint);
 //右下小圆参数
 cxx = (float) (cx + math.sqrt(2) / 2f * (radius + rr / 3f));
 canvas.drawcircle(cxx, cyy, rr, mtextpaint);
 canvas.restore();
 }

展开动画

展开动画也是不断改变view的宽度并重绘圆角矩形,同时需要对准备动画的状态进行向右位移。

animation animator1 = new animation() {
 @override
 protected void applytransformation(float interpolatedtime, transformation t) {
 mcurrlength = mheight + (mwidth - mheight) * interpolatedtime;
 mtranslationx = (mwidth - mheight) / 2 * interpolatedtime;
 invalidate();
 }
 };
 animator1.setanimationlistener(new animation.animationlistener() {
 @override
 public void onanimationstart(animation animation) {
 mstatus = status.expand;
 }

 @override
 public void onanimationend(animation animation) {
 clearanimation();
 mloadangleanim.start();
 mmovepointanim.start();
 }

 @override
 public void onanimationrepeat(animation animation) {

 }
 });
 animator1.setduration(mexpandanimduration);
 animator1.setinterpolator(new linearinterpolator());
 mtranslateanim = animator1;

ondraw中绘制代码

if (mstatus == status.expand) {
 float left = (mwidth - mcurrlength) / 2f;
 float right = (mwidth + mcurrlength) / 2f;
 float r = mheight / 2f;
 canvas.drawroundrect(new rectf(left, 0, right, mheight), r, r, mbgpaint);
 canvas.save();
 mtextpaint.setstyle(paint.style.fill);
 canvas.translate(mtranslationx, 0);
 //大圆的圆心 半径
 float cx = mwidth / 2f;
 float cy = mheight / 2f;
 float radius = mheight / 2 / 3f;
 canvas.drawcircle(cx, cy, radius, mtextpaint);
 //上方小圆的参数
 float rr = radius / 2f;
 float cyy = mheight / 2 - (radius + rr / 3);
 canvas.drawcircle(cx, cyy, rr, mtextpaint);
 //左下小圆参数
 float cxx = (float) (cx - math.sqrt(2) / 2f * (radius + rr / 3f));
 cyy = (float) (mheight / 2 + math.sqrt(2) / 2f * (radius + rr / 3f));
 canvas.drawcircle(cxx, cyy, rr, mtextpaint);
 //右下小圆参数
 cxx = (float) (cx + math.sqrt(2) / 2f * (radius + rr / 3f));
 canvas.drawcircle(cxx, cyy, rr, mtextpaint);
 canvas.restore();
 }

加载动画

加载动画分三部分,右侧的旋转动画,正弦轨迹运动的小球动画,进度更新的动画。正弦动画要求出正弦函数的周期,y轴偏移量,x轴偏移量。

valueanimator animator2 = valueanimator.offloat(0, 1);
 animator2.addupdatelistener(new valueanimator.animatorupdatelistener() {
 @override
 public void onanimationupdate(valueanimator animation) {
 mloadangle += mloadrotateanimspeed;
 invalidate();
 }
 });
 animator2.addlistener(new animator.animatorlistener() {
 @override
 public void onanimationstart(animator animation) {
 mstatus = status.load;
 }

 @override
 public void onanimationend(animator animation) {
 mloadangleanim.cancel();
 }

 @override
 public void onanimationcancel(animator animation) {

 }

 @override
 public void onanimationrepeat(animator animation) {

 }
 });
 animator2.setduration(integer.max_value);
 animator2.setinterpolator(new linearinterpolator());
 mloadangleanim = animator2;

ondraw中绘制代码:

if (mstatus == status.load || mstatus == status.end) {
 float left = (mwidth - mcurrlength) / 2f;
 float right = (mwidth + mcurrlength) / 2f;
 float r = mheight / 2f;
 mbgpaint.setcolor(mprogresscolor);
 canvas.drawroundrect(new rectf(left, 0, right, mheight), r, r, mbgpaint);
 if (mprogress != 100) {
 for (int i = 0; i < mfourmovepoints.length; i++) {
  if (mfourmovepoints[i].isdraw)
  canvas.drawcircle(mfourmovepoints[i].movex, mfourmovepoints[i].movey, mfourmovepoints[i].radius, mtextpaint);
 }
 }
 float progressright = mprogress * mwidth / 100f;
 mbgpaint.setcolor(mbgcolor);
 canvas.save();
 canvas.cliprect(0, 0, progressright, mheight);
 canvas.drawroundrect(new rectf(left, 0, right, mheight), r, r, mbgpaint);
 canvas.restore();

 if (mprogress != 100) {
 canvas.drawcircle(mwidth - mheight / 2, mheight / 2, mheight / 2, mbgpaint);
 canvas.save();
 mtextpaint.setstyle(paint.style.fill);
 canvas.rotate(mloadangle, mwidth - mheight / 2, mheight / 2);
 canvas.drawcircle(mwidth - mheight + 30, getcentery(mwidth - mheight + 30, 5), 5, mtextpaint);
 canvas.drawcircle(mwidth - mheight + 45, getcentery(mwidth - mheight + 45, 8), 8, mtextpaint);
 canvas.drawcircle(mwidth - mheight + 68, getcentery(mwidth - mheight + 68, 11), 11, mtextpaint);
 canvas.drawcircle(mwidth - mheight + 98, getcentery(mwidth - mheight + 98, 14), 14, mtextpaint);
 canvas.restore();
 }

 paint.fontmetrics fm = mtextpaint.getfontmetrics();
 float y = mheight / 2 + (fm.descent - fm.ascent) / 2 - fm.descent;
 canvas.drawtext(mprogress + "%", mwidth / 2, y, mtextpaint);
 }

项目主页:

本地下载:

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对移动技术网的支持。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网