美文网首页安卓Android UI的收集Android
Android仿支付宝支付验证按钮

Android仿支付宝支付验证按钮

作者: 淋雨仔 | 来源:发表于2016-09-09 19:25 被阅读1524次

支付宝之前更新的时候,支付验证时的按钮动画让我有种惊喜的感觉。
前几天突然心血来潮,打算自己做一个出来。
恩,下面是github地址和效果图。
其实真机上的动画速度会比较快 = =!

https://github.com/Linyuzai/Demo4RequestButton

request_button.gif

先介绍下用法吧

<com.linyuzai.requestbutton.RequestButton    
  android:id="@+id/end2"
  android:layout_width="match_parent"
  android:layout_height="50dp"
  android:layout_marginBottom="5dp"
  android:background="@drawable/bg" 
  icon:request_icon_size="2dp"
  icon:request_icon_spacing="25dp"
  icon:request_icon_style="tick_end_circle"
  icon:request_speed_multiplier="1.8"
  icon:text_color="@android:color/white"   
  icon:text_default="default"    
  icon:text_failure="failure"    
  icon:text_progress="progress"    
  icon:text_success="success" />

下面是所有的属性

<declare-styleable name="RequestButton">    
  <attr name="request_icon_spacing" format="dimension" />   
  <attr name="request_icon_color" format="color" />
  <attr name="request_icon_size" format="dimension" />  
  <attr name="request_icon_style" format="enum">
    <enum name="tick_start_circle" value="0" />   
    <enum name="tick_half_circle" value="1" />   
    <enum name="tick_end_circle" value="2" />   
  </attr> 
  <attr name="request_speed_multiplier" format="float" /> 
  <attr name="text_default" format="string" />  
  <attr name="text_progress" format="string" /> 
  <attr name="text_success" format="string" />    
  <attr name="text_failure" format="string" />    
  <attr name="text_color" format="color" />    
  <attr name="text_size" format="dimension" />    
  <attr name="text_width" format="dimension" />
</declare-styleable>

然后简单说明一下,嫌我啰嗦的请跳过

Attrs Introduction
request_icon_spacing icon和文本之间的间隔
默认0px
request_icon_color icon的颜色
默认白色
request_icon_size 画笔Paint的width
默认5px
request_icon_style 1.tick_start_circle
最后的画圈和打钩一起进行
2.tick_half_circle
最后的画圈画到一半开始打钩
3.tick_end_circle
最后的画圈画完之后再打钩
默认tick_start_circle
request_speed_multiplier 动画画圈和打钩的速度乘数
0.5-2.0,默认1.8
text_default 按钮默认文本
默认“default”
text_progress 请求时文本
默认“progress”
text_success 成功时文本
默认“success”
text_failure 失败时文本
默认“failure”
text_color 文本字体颜色
默认黑色
text_size 文本字体尺寸
默认20px
text_width 文本宽度
默认wrap_content
end2.setOnRequestCallback(new OnRequestCallback() {    
    @Override
    public boolean beforeRequest() {
        return true;
    }
    @Override    
    public void onRequest() {        
        Toast.makeText(MainActivity.this, "request", Toast.LENGTH_SHORT).show();    
    }    
    @Override    
    public void onFinish(boolean isSuccess) {
        Toast.makeText(MainActivity.this, "finish", Toast.LENGTH_SHORT).show();    
    }
});

不需要自己设置OnClickListener,beforeRequest()返回true开始请求,返回false不进行请求。在onRequest()里进行请求,成功或失败后手动调用requestSuccess()或者requestFailure(),等到icon画完就会回调到onFinish()

end2.requestSuccess();
end2.requestFailure();

接下来讲一下思路,暂时忽略速度的乘数
首先要画progress的时候,我定义了两个progress

public static final float CIRCLE_PROGRESS_MAX = 100f;
private float firstProgress;
private float secondProgress;

设置进度为100,假设进度为50时增量为1,那么加速度为0.02
第一条progress由快到慢,进度为firstProgress += 2-0.02*progress
第二条progress由慢到快,进度为secondProgress += 0.02*progress
等到画完一个圆再重置各个progress

float startAngle = 360f * secondProgress * speedMultiplier / CIRCLE_PROGRESS_MAX;
float sweepAngle = 360f * speedMultiplier * (firstProgress - secondProgress) / CIRCLE_PROGRESS_MAX;
canvas.drawArc(rectF, -90f + startAngle, sweepAngle, false, paint);
if (progress > CIRCLE_PROGRESS_MAX + 1f) {    
    progress = 0f;    
    firstProgress = 0f;    
    secondProgress = 0f;

第一部分算完成了
接下来是打钩之前的那个圆
这个更简单

float startCircleAngle = 360f * speedMultiplier * firstProgress / CIRCLE_PROGRESS_MAX;
canvas.drawArc(rectF, -90f, startCircleAngle, false, paint);

最后是画勾
我先定义了两个类

class Point {    
    float x;    
    float y;    
    public Point(float x, float y) {        
        this.x = x;        
        this.y = y;    
    }
}
class Line {    
    Point startPoint;    
    Point endPoint;    
    float k;    
    float b;    
    public Line(Point startPoint, Point endPoint) {        
        this.startPoint = startPoint;        
        this.endPoint = endPoint;        
        k = (endPoint.y - startPoint.y) / (endPoint.x - startPoint.x);    
        b = startPoint.y - k * startPoint.x;    
    }    
    public float getY(float x) {        
        return k * x + b;    
    }
}

接着就可以得到两条线段
勾的两条线段的长度比为1:2,斜率为-1和1
将整个控件分成10*10
第一条占0.15,就是一格半,第二条占0.3,就是三格,总共占0.45,四格半
然后微微的调整一下,在x,y轴上平移到本人还看得过去为止 = =!

firstLine = new Line(new Point(width * 0.28f, height * 0.53f), new Point(width * 0.43f, height * 0.68f));
secondLine = new Line(new Point(width * 0.43f, height * 0.68f), new Point(width * 0.73f, height * 0.38f));

我也将总共的进度设为100,那么第一条线段的进度为33.3,第二条为66.6
并且每次的增量为

lineProgressIncrease = width * 0.45f / 100f;

所以按照x求出y,得到终点,就可以画出所要的线段了,lineX及x坐标,并且之前说道忽略speedMultiplier,所以先用1代替

lineX = firstLine.startPoint.x;
lineProgress += speedMultiplier;
lineX += lineProgressIncrease * speedMultiplier;
canvas.drawLine(firstLine.startPoint.x, firstLine.startPoint.y, lineX, firstLine.getY(lineX), paint);

当lineProgress>33.3的时候

canvas.drawLine(firstLine.startPoint.x, firstLine.startPoint.y, firstLine.endPoint.x, firstLine.endPoint.y, paint);
canvas.drawLine(secondLine.startPoint.x, secondLine.startPoint.y, lineX, secondLine.getY(lineX), paint);

左边的icon画完了,接下来就简单了,把icon和TextView组合起来
你们肯定会想text要居中会用RelativeLayout,不过我用的是LinearLayout
好把提醒一下,weight属性


小弟初来乍到,希望各位大神能赏个脸
嗯,纯手打,发现写这玩意儿并不比敲代码简单
不过能够从头到尾review一遍,还是有帮助的
如果有什么bug或者更好的建议,随时欢迎

相关文章

网友评论

    本文标题:Android仿支付宝支付验证按钮

    本文链接:https://www.haomeiwen.com/subject/plmeettx.html