当前位置:网站首页>Download control 1 of custom control (downloadview1)
Download control 1 of custom control (downloadview1)
2022-06-29 10:16:00 【Mr beast no beast】
Some time ago, I saw two cool download buttons in the dry goods concentration camp :

Unfortunately, it's next door iOS The children of , What do I do , I like it too ,emmm, Some , I can only imitate and realize it myself . Let's start with the first one ( The second wave effect is not yet available ).
1 Get ready
public class DownloadView1 extends View {
private Paint mPaint;
private float radius = 150; // Circle radius
public DownloadView1(Context context) {
this(context, null);
}
public DownloadView1(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public DownloadView1(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mPaint = new Paint();
mPaint.setStrokeWidth(radius / 10);
mPaint.setStrokeCap(Paint.Cap.ROUND);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setBackgroundColor(Color.rgb(10, 39, 46));
}
}2 Draw circles and arrows
public class DownloadView1 extends View {
private Paint mPaint;
private Path mPath;
private float radius = 150; // Circle radius
private float lineLength = radius / 2; // The length of the vertical line in the middle of the downloaded logo
private float arrowTurningPointY = radius / 2; // Download the logo below the turning point of the arrow Y Axis coordinates
private float arrowLength = radius / 2; // The length of the downloaded logo after the arrow becomes a horizontal line
public DownloadView1(Context context) {
this(context, null);
}
public DownloadView1(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public DownloadView1(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mPaint = new Paint();
mPaint.setStrokeWidth(radius / 10);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPath = new Path();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setBackgroundColor(Color.rgb(10, 39, 46));
}
@Override
protected void onDraw(Canvas canvas) {
mPaint.setColor(Color.rgb(10, 39, 46));
mPaint.setStyle(Paint.Style.FILL);
mPaint.setAntiAlias(true);
canvas.drawCircle(getMeasuredWidth() / 2, getMeasuredHeight() / 2, radius, mPaint);
mPaint.setColor(Color.rgb(37, 66, 73));
mPaint.setStyle(Paint.Style.STROKE);
canvas.drawCircle(getMeasuredWidth() / 2, getMeasuredHeight() / 2, radius, mPaint);
mPaint.setColor(Color.rgb(255, 255, 255));
mPaint.setStyle(Paint.Style.STROKE);
canvas.drawLine(getMeasuredWidth() / 2, getMeasuredHeight() / 2 - lineLength
, getMeasuredWidth() / 2, getMeasuredHeight() / 2 + lineLength
, mPaint);
mPaint.setColor(Color.rgb(255, 255, 255));
mPaint.setStyle(Paint.Style.STROKE);
mPath.reset();
mPath.moveTo(getMeasuredWidth() / 2 - arrowLength, getMeasuredHeight() / 2);
mPath.lineTo(getMeasuredWidth() / 2, getMeasuredHeight() / 2 + arrowTurningPointY);
mPath.lineTo(getMeasuredWidth() / 2 + arrowLength, getMeasuredHeight() / 2);
canvas.drawPath(mPath, mPaint);
}
}
3 The download arrow vertical line shrinks to a point
// Draw the download arrow
mPaint.setColor(Color.rgb(255, 255, 255));
mPaint.setStyle(Paint.Style.STROKE);
if (lineLength == 0) {
// When the vertical line of the download arrow shrinks to a dot, you should draw a dot
canvas.drawPoint(getMeasuredWidth() / 2, linePointY, mPaint);
} else {
// Otherwise you should draw a line
canvas.drawLine(getMeasuredWidth() / 2, getMeasuredHeight() / 2 - lineLength
, getMeasuredWidth() / 2, getMeasuredHeight() / 2 + lineLength
, mPaint);
}private void startAnimation() {
// Each animation has a different duration
lineLengthAnimator.setDuration(500);
// Add animation monitor , In fact, it is always redrawn
lineLengthAnimator.addUpdateListener(mAnimatorUpdateListener);
// Set the playback order of the animation
AnimatorSet mAnimatorSet = new AnimatorSet();
mAnimatorSet.play(lineLengthAnimator);
mAnimatorSet.start();
} private ValueAnimator.AnimatorUpdateListener mAnimatorUpdateListener = new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
invalidate();
}
};
4 The arrow part of the download arrow becomes a horizontal line , At the same time, the dot of the vertical line moves up
private void startAnimation() {
// Download the animation that the arrow vertical line shrinks to a point
ObjectAnimator lineLengthAnimator = ObjectAnimator.ofFloat(this, "lineLength", radius / 2, 0);
// Download the animation after the arrow vertical line shrinks into a dot 1( The arrow of the download arrow becomes a horizontal line )
ObjectAnimator arrowTurningPointYAnimator1 = ObjectAnimator.ofFloat(this, "arrowTurningPointY", radius / 2, 0);
// Download the animation after the arrow vertical line shrinks into a dot 2( Download the arrow shaking effect of the arrow )
ObjectAnimator arrowTurningPointYAnimator2 = ObjectAnimator.ofFloat(this, "arrowTurningPointY", 0, radius / 4, 0);
// Download the arrow vertical line after shrinking into a dot Y Animation of axis coordinate change
ObjectAnimator linePointYAnimator = ObjectAnimator.ofFloat(this, "linePointY", getMeasuredHeight() / 2, getMeasuredHeight() / 2 - radius);
// Each animation has a different duration
lineLengthAnimator.setDuration(500);
arrowTurningPointYAnimator1.setDuration(500);
arrowTurningPointYAnimator2.setDuration(500);
linePointYAnimator.setDuration(500);
// Add animation monitor , In fact, it is always redrawn
lineLengthAnimator.addUpdateListener(mAnimatorUpdateListener);
arrowTurningPointYAnimator1.addUpdateListener(mAnimatorUpdateListener);
arrowTurningPointYAnimator2.addUpdateListener(mAnimatorUpdateListener);
linePointYAnimator.addUpdateListener(mAnimatorUpdateListener);
// Set the playback order of the animation
AnimatorSet mAnimatorSet = new AnimatorSet();
mAnimatorSet.play(arrowTurningPointYAnimator1).after(lineLengthAnimator);
mAnimatorSet.play(arrowTurningPointYAnimator2).after(arrowTurningPointYAnimator1);
mAnimatorSet.play(linePointYAnimator).after(arrowTurningPointYAnimator1);
mAnimatorSet.start();
}
5 Draw two semicircles , The horizontal line that the download arrow becomes shrinks into a dot
// Draw two semicircles
mPaint.setColor(Color.rgb(255, 255, 255));
mPaint.setStyle(Paint.Style.STROKE);
canvas.drawArc(mRectF, -90, sweepAngle, false, mPaint);
canvas.drawArc(mRectF, -90, 0 - sweepAngle, false, mPaint); mPaint.setColor(Color.rgb(255, 255, 255));
mPaint.setStyle(Paint.Style.STROKE);
if (arrowLength == 0) {
// When the arrow part of the download arrow shrinks to a dot, you should draw a dot
canvas.drawPoint(getMeasuredWidth() / 2, tickTurningPointY, mPaint);
drawOk = true;
} else {
// Otherwise, you should draw arrows
mPath.reset();
mPath.moveTo(getMeasuredWidth() / 2 - arrowLength, getMeasuredHeight() / 2);
mPath.lineTo(getMeasuredWidth() / 2, getMeasuredHeight() / 2 + arrowTurningPointY);
mPath.lineTo(getMeasuredWidth() / 2 + arrowLength, getMeasuredHeight() / 2);
canvas.drawPath(mPath, mPaint);
} private void startAnimation() {
// Download the animation that the arrow vertical line shrinks to a point
ObjectAnimator lineLengthAnimator = ObjectAnimator.ofFloat(this, "lineLength", radius / 2, 0);
// Download the animation after the arrow vertical line shrinks into a dot 1( The arrow of the download arrow becomes a horizontal line )
ObjectAnimator arrowTurningPointYAnimator1 = ObjectAnimator.ofFloat(this, "arrowTurningPointY", radius / 2, 0);
// Download the animation after the arrow vertical line shrinks into a dot 2( Download the arrow shaking effect of the arrow )
ObjectAnimator arrowTurningPointYAnimator2 = ObjectAnimator.ofFloat(this, "arrowTurningPointY", 0, radius / 4, 0);
// Download the arrow vertical line after shrinking into a dot Y Animation of axis coordinate change
ObjectAnimator linePointYAnimator = ObjectAnimator.ofFloat(this, "linePointY", getMeasuredHeight() / 2, getMeasuredHeight() / 2 - radius);
// Animation of drawing a semicircle
ObjectAnimator sweepAngleAnimator = ObjectAnimator.ofFloat(this, "sweepAngle", 0, 180);
// Download the animation of the arrow shrinking into points after the arrow becomes a horizontal line
ObjectAnimator arrowLengthAnimator = ObjectAnimator.ofFloat(this, "arrowLength", radius / 2, 0);
// Each animation has a different duration
lineLengthAnimator.setDuration(500);
arrowTurningPointYAnimator1.setDuration(500);
arrowTurningPointYAnimator2.setDuration(500);
linePointYAnimator.setDuration(500);
sweepAngleAnimator.setDuration(3000);
arrowLengthAnimator.setDuration(3000);
// Add animation monitor , In fact, it is always redrawn
lineLengthAnimator.addUpdateListener(mAnimatorUpdateListener);
arrowTurningPointYAnimator1.addUpdateListener(mAnimatorUpdateListener);
arrowTurningPointYAnimator2.addUpdateListener(mAnimatorUpdateListener);
linePointYAnimator.addUpdateListener(mAnimatorUpdateListener);
sweepAngleAnimator.addUpdateListener(mAnimatorUpdateListener);
arrowLengthAnimator.addUpdateListener(mAnimatorUpdateListener);
// Set the playback order of the animation
AnimatorSet mAnimatorSet = new AnimatorSet();
mAnimatorSet.play(arrowTurningPointYAnimator1).after(lineLengthAnimator);
mAnimatorSet.play(arrowTurningPointYAnimator2).after(arrowTurningPointYAnimator1);
mAnimatorSet.play(linePointYAnimator).after(arrowTurningPointYAnimator1);
mAnimatorSet.play(arrowLengthAnimator).after(arrowTurningPointYAnimator2);
mAnimatorSet.play(sweepAngleAnimator).after(arrowTurningPointYAnimator2);
mAnimatorSet.start();
}
6 Cross check

mPath.moveTo((float) (getMeasuredWidth() / 2 - (Math.sin(45) * tickLength / 3))
, (float) (tickTurningPointY - (Math.cos(45) * tickLength / 3)));
mPath.lineTo(getMeasuredWidth() / 2, tickTurningPointY);
mPath.lineTo((float) (getMeasuredWidth() / 2 + (Math.sin(45) * tickLength / 3*2))
, (float) (tickTurningPointY - (Math.cos(45) * tickLength / 3*2)));
mPath.moveTo((float) (getMeasuredWidth() / 2 - (Math.sin(45) * tickLength / 3))
, (float) (tickTurningPointY - (Math.cos(45) * tickLength / 3)-radius/4));
mPath.lineTo(getMeasuredWidth() / 2, tickTurningPointY-radius/4);
mPath.lineTo((float) (getMeasuredWidth() / 2 + (Math.sin(45) * tickLength / 3))
, (float) (tickTurningPointY - (Math.cos(45) * tickLength / 3*2)-radius/4));Then add animation , The code is not posted , Look at the final overall code . The final overall effect is as follows :

7 summary
8 Source code
/**
* Description:
* Created by Mr. beast
* Created on 2017/9/4
*/
public class DownloadView1 extends View {
private Paint mPaint;
private Path mPath;
private float radius = 150; // Circle radius
private float lineLength = radius / 2; // The length of the vertical line in the middle of the downloaded logo
private float arrowTurningPointY = radius / 2; // Download the logo below the turning point of the arrow Y Axis coordinates
private float linePointY; // The vertical line in the middle of the downloaded logo shrinks to the point after the point Y coordinate ,onMeasured() method
private RectF mRectF;
private float sweepAngle = 0; // The angle of the arc on both sides
private float arrowLength = radius / 2; // The length of the downloaded logo after the arrow becomes a horizontal line
private float tickTurningPointY; // Couplet Y coordinate ,onMeasured() method
private float tickLength = 0; // The total length of the hook ;
private boolean drawOk; // Whether the mark position of the last hook should be drawn
public DownloadView1(Context context) {
this(context, null);
}
public DownloadView1(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public DownloadView1(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mPaint = new Paint();
mPaint.setStrokeWidth(radius / 10);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPath = new Path();
setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
startAnimation();
}
});
}
public void setLineLength(float lineLength) {
this.lineLength = lineLength;
}
public void setArrowTurningPointY(float arrowTurningPointY) {
this.arrowTurningPointY = arrowTurningPointY;
}
public void setLinePointY(float linePointY) {
this.linePointY = linePointY;
}
public void setSweepAngle(float sweepAngle) {
this.sweepAngle = sweepAngle;
}
public void setArrowLength(float arrowLength) {
this.arrowLength = arrowLength;
}
public void setTickTurningPointY(float tickTurningPointY) {
this.tickTurningPointY = tickTurningPointY;
}
public void setTickLength(float tickLength) {
this.tickLength = tickLength;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setBackgroundColor(Color.rgb(10, 39, 46));
linePointY = getMeasuredHeight() / 2;
tickTurningPointY = getMeasuredHeight() / 2;
mRectF = new RectF(getMeasuredWidth() / 2 - radius
, getMeasuredHeight() / 2 - radius
, getMeasuredWidth() / 2 + radius
, getMeasuredHeight() / 2 + radius);
}
@Override
protected void onDraw(Canvas canvas) {
// Draw the whole circle
mPaint.setColor(Color.rgb(10, 39, 46));
mPaint.setStyle(Paint.Style.FILL);
mPaint.setAntiAlias(true);
canvas.drawCircle(getMeasuredWidth() / 2, getMeasuredHeight() / 2, radius, mPaint);
// Draw a circle
mPaint.setColor(Color.rgb(37, 66, 73));
mPaint.setStyle(Paint.Style.STROKE);
canvas.drawCircle(getMeasuredWidth() / 2, getMeasuredHeight() / 2, radius, mPaint);
// Draw two semicircles
mPaint.setColor(Color.rgb(255, 255, 255));
mPaint.setStyle(Paint.Style.STROKE);
canvas.drawArc(mRectF, -90, sweepAngle, false, mPaint);
canvas.drawArc(mRectF, -90, 0 - sweepAngle, false, mPaint);
// Decide what to draw according to whether it should be checked
if (drawOk) {
// Cross check
mPaint.setColor(Color.rgb(98, 178, 117));
mPaint.setStyle(Paint.Style.STROKE);
mPath.reset();
mPath.moveTo((float) (getMeasuredWidth() / 2 - (Math.sin(45) * tickLength / 3))
, (float) (tickTurningPointY - (Math.cos(45) * tickLength / 3)-radius/4));
mPath.lineTo(getMeasuredWidth() / 2, tickTurningPointY-radius/4);
mPath.lineTo((float) (getMeasuredWidth() / 2 + (Math.sin(45) * tickLength / 3))
, (float) (tickTurningPointY - (Math.cos(45) * tickLength / 3*2)-radius/4));
canvas.drawPath(mPath, mPaint);
} else {
// Draw the download arrow
mPaint.setColor(Color.rgb(255, 255, 255));
mPaint.setStyle(Paint.Style.STROKE);
if (lineLength == 0) {
// When the vertical line of the download arrow shrinks to a dot, you should draw a dot
canvas.drawPoint(getMeasuredWidth() / 2, linePointY, mPaint);
} else {
// Otherwise you should draw a line
canvas.drawLine(getMeasuredWidth() / 2, getMeasuredHeight() / 2 - lineLength
, getMeasuredWidth() / 2, getMeasuredHeight() / 2 + lineLength
, mPaint);
}
mPaint.setColor(Color.rgb(255, 255, 255));
mPaint.setStyle(Paint.Style.STROKE);
if (arrowLength == 0) {
// When the arrow part of the download arrow shrinks to a dot, you should draw a dot
canvas.drawPoint(getMeasuredWidth() / 2, tickTurningPointY, mPaint);
drawOk = true;
} else {
// Otherwise, you should draw arrows
mPath.reset();
mPath.moveTo(getMeasuredWidth() / 2 - arrowLength, getMeasuredHeight() / 2);
mPath.lineTo(getMeasuredWidth() / 2, getMeasuredHeight() / 2 + arrowTurningPointY);
mPath.lineTo(getMeasuredWidth() / 2 + arrowLength, getMeasuredHeight() / 2);
canvas.drawPath(mPath, mPaint);
}
}
}
private void startAnimation() {
// Download the animation that the arrow vertical line shrinks to a point
ObjectAnimator lineLengthAnimator = ObjectAnimator.ofFloat(this, "lineLength", radius / 2, 0);
// Download the animation after the arrow vertical line shrinks into a dot 1( The arrow of the download arrow becomes a horizontal line )
ObjectAnimator arrowTurningPointYAnimator1 = ObjectAnimator.ofFloat(this, "arrowTurningPointY", radius / 2, 0);
// Download the animation after the arrow vertical line shrinks into a dot 2( Download the arrow shaking effect of the arrow )
ObjectAnimator arrowTurningPointYAnimator2 = ObjectAnimator.ofFloat(this, "arrowTurningPointY", 0, radius / 4, 0);
// Download the arrow vertical line after shrinking into a dot Y Animation of axis coordinate change
ObjectAnimator linePointYAnimator = ObjectAnimator.ofFloat(this, "linePointY", getMeasuredHeight() / 2, getMeasuredHeight() / 2 - radius);
// Animation of drawing a semicircle
ObjectAnimator sweepAngleAnimator = ObjectAnimator.ofFloat(this, "sweepAngle", 0, 180);
// Download the animation of the arrow shrinking into points after the arrow becomes a horizontal line
ObjectAnimator arrowLengthAnimator = ObjectAnimator.ofFloat(this, "arrowLength", radius / 2, 0);
// The turning point of the checkmark is Y Animation of axis coordinate change
ObjectAnimator tickTurningPointYAnimator = ObjectAnimator.ofFloat(this, "tickTurningPointY", getMeasuredHeight() / 2, getMeasuredHeight() / 2 + radius / 2);
// Animation of the change in the total length of the tick
ObjectAnimator tickLengthAnimator = ObjectAnimator.ofFloat(this, "tickLength", 0, radius);
// Each animation has a different duration
lineLengthAnimator.setDuration(500);
arrowTurningPointYAnimator1.setDuration(500);
arrowTurningPointYAnimator2.setDuration(500);
linePointYAnimator.setDuration(500);
sweepAngleAnimator.setDuration(3000);
arrowLengthAnimator.setDuration(3000);
tickTurningPointYAnimator.setDuration(1000);
tickLengthAnimator.setDuration(1000);
// Add animation monitor , In fact, it is always redrawn
lineLengthAnimator.addUpdateListener(mAnimatorUpdateListener);
arrowTurningPointYAnimator1.addUpdateListener(mAnimatorUpdateListener);
arrowTurningPointYAnimator2.addUpdateListener(mAnimatorUpdateListener);
linePointYAnimator.addUpdateListener(mAnimatorUpdateListener);
sweepAngleAnimator.addUpdateListener(mAnimatorUpdateListener);
arrowLengthAnimator.addUpdateListener(mAnimatorUpdateListener);
tickTurningPointYAnimator.addUpdateListener(mAnimatorUpdateListener);
tickLengthAnimator.addUpdateListener(mAnimatorUpdateListener);
// Set the playback order of the animation
AnimatorSet mAnimatorSet = new AnimatorSet();
mAnimatorSet.play(arrowTurningPointYAnimator1).after(lineLengthAnimator);
mAnimatorSet.play(arrowTurningPointYAnimator2).after(arrowTurningPointYAnimator1);
mAnimatorSet.play(linePointYAnimator).after(arrowTurningPointYAnimator1);
mAnimatorSet.play(arrowLengthAnimator).after(arrowTurningPointYAnimator2);
mAnimatorSet.play(sweepAngleAnimator).after(arrowTurningPointYAnimator2);
mAnimatorSet.play(tickTurningPointYAnimator).after(sweepAngleAnimator);
mAnimatorSet.play(tickLengthAnimator).after(sweepAngleAnimator);
// Add animation set monitor , Reset each variable after completion
mAnimatorSet.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
// lineLength = radius / 2;
// arrowTurningPointY = radius / 2;
// linePointY = getMeasuredHeight() / 2;
// sweepAngle = 0;
// arrowLength = radius / 2;
// tickTurningPointY = getMeasuredHeight() / 2;
// tickLength = 0;
// drawOk = false;
// invalidate();
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
mAnimatorSet.start();
}
private ValueAnimator.AnimatorUpdateListener mAnimatorUpdateListener = new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
invalidate();
}
};
}边栏推荐
- 2019.10.23 training summary
- Setinterval, setTimeout and requestanimationframe
- L2-026 small generation (25 points)
- manacher
- If I were in Beijing, where would it be better to open an account? In addition, is it safe to open an account online now?
- L1-009 sum of N numbers (20 points)
- L2-3 is this a binary search tree- The explanation is wonderful
- 2019-11-10 training summary
- L2-025 divide and rule (25 points)
- 2019.10.6训练总结
猜你喜欢
随机推荐
Six dimensional space BFS
1099 Build A Binary Search Tree (30 分)
Flutter 基础组件之 GridView
2019.11.17训练总结
manacher
同花顺炒股软件可靠吗,安全吗?
JVM method return address
2019.10.23训练总结
Pointer functions and function pointers
点在多边形内外的判断
Flutter 基础组件之 Text
qgis制图
Power Strings【KMP循环节】
Database common interview questions (with answers)
JVM instructions for four call methods
A method of creating easy to manage and maintain thread by C language
FreeRTOS (VIII) - time management
子串分值-超详细版——最后的编程挑战
单片机集成开发环境Keil5的使用
Simulation problem of two stacks









