android模仿支付宝生活圈下拉加载控件TriangleLoadingView

来源:互联网 发布:云计算服务的应用例子 编辑:程序博客网 时间:2024/04/28 15:32

前言

之前看到支付宝做的loading的效果感觉很棒的UI设计,于是就来模仿一个,模仿的效果一般。

支付宝的loading的效果朋友们可以自己看看,这里就不放出来了,下面是loading的模样


正题

先上一张模仿之后的效果图


现在开始我的模仿的一个想法和,首先是要对于这个形状进行模仿,由于是一个六边形,其中包含六个三角形

对于三角形的绘制,由于三角形里面还有一层扇形,同时三角形属于圆角三角形,所以必须注意各个点的绘制。弧形绘制的时候采用的赛贝尔曲线绘制的,渐变利用linearGradient,主要的方法是利用path进行路径绘制,图形如下:


初始化顶点主要方法是在TriangleLoadingView.java里面的方法中进行的,只要确定了六个顶点,那么其余的点都好计算。

protected void initTopPoints(int x, int y) {        topPoints = new int[TRIANGLE_NUM][2];        topPoints[0][0] = x - DISTANCE / 2;        topPoints[0][1] = y;        topPoints[1][0] = (int) (topPoints[0][0] - LENGTH * SIN60) - DISTANCE;        topPoints[1][1] = topPoints[0][1] + LENGTH / 2 + DISTANCE;        topPoints[2][0] = topPoints[1][0] + DISTANCE;        topPoints[2][1] = topPoints[1][1] + LENGTH + DISTANCE;        topPoints[3][0] = topPoints[0][0] + DISTANCE + DISTANCE / 2;        topPoints[3][1] = topPoints[0][1] + LENGTH * 2 + DISTANCE * 2;        topPoints[4][0] = (int) (topPoints[2][0] + 2 * LENGTH * SIN60) + 2 * DISTANCE;        topPoints[4][1] = topPoints[2][1] - DISTANCE;        topPoints[5][0] = (int) (topPoints[1][0] + 2 * LENGTH * SIN60) + 2 * DISTANCE + DISTANCE / 2;        topPoints[5][1] = topPoints[1][1] - DISTANCE;    }

在Triangle.java里面实现了绘制三角形的方法,主要计算四个点(三个顶点加一个扇形的角点)由于考虑到不能不断的计算移动或旋转时候的位置点,所以,采用的解决方法是,在六个主要顶点绘制相同大小方向角度的三角形,然后通过canvas.rotate的方式来进行绘制,这样绘制的效果更佳。主要方法是drawSelf()这个方法

public class Triangle{    public final static float TAN30 = 0.5773f;    public final static int SHIFT = -TriangleLoadingView.HEIGHT_DEFAULT;    private int dev = SHIFT;    private int ax;    private int ay;    private int bx;    private int by;    private int cx;    private int cy;    private int dx;    private int dy;    private int bgColor, topColor;    private Path path;    private int length = 40;    private int rotateDegree;    private int rate = 3;    private LinearGradient linearGradient;    public Triangle(int bx, int by, int rotateDegree, int topColor, int bgColor) {        this.length = TriangleLoadingView.LENGTH;        this.rate = 3 * length / 40;        this.ax = bx - length;        this.ay = by;        this.bx = bx;        this.by = by;        this.cx = bx;        this.cy = (int) (by + length * TAN30);        this.dx = bx - (cy - by);        this.dy = (int) (by + (cy - by) * TAN30);        this.bgColor = bgColor;        this.topColor = topColor;        this.rotateDegree = rotateDegree;        path = new Path();        linearGradient = new LinearGradient(bx, by, dx, dy, topColor, bgColor, Shader.TileMode.CLAMP);    }    public void drawSelf(Canvas canvas, Paint paint){        paint.setColor(bgColor);        path.moveTo(ax + rate, ay);        path.lineTo(bx - rate, by);        path.quadTo(bx, by, cx, by + rate);        path.lineTo(cx, cy - rate);        path.quadTo(cx, cy, cx - rate, cy - rate * TAN30);        path.quadTo(ax, ay, ax + rate, ay);        path.close();        canvas.save();        canvas.translate(0, dev);        canvas.rotate(rotateDegree, bx, by);        canvas.drawPath(path, paint);        path.reset();        path.moveTo(cx, cy - rate);        path.lineTo(cx, by + rate / 2);        path.quadTo(cx - length * TAN30 * TAN30, by, cx - length * TAN30 * TriangleLoadingView.SIN60, cy - length * TAN30 * 0.5f);        path.lineTo(cx - rate, cy - rate * TAN30);        path.quadTo(cx, cy, cx, cy - rate);        path.close();        paint.setShader(linearGradient);        paint.setColor(Color.GRAY);        canvas.drawPath(path, paint);        canvas.restore();        paint.setShader(null);    }    public void moveVertically(int des){        dev = des;    }    public void moveUp(){        dev -= 3;    }}
完成了图形的模样之后,接着是三角形的移动,移动主要是根据你的滑动距离来进行的,在Triangle绘制的时候让Canvas.translate()一个偏移量,这样就可以达到一个移动的效果,同时又不用改变三角形的所有点的坐标。接着就是一些边缘的判断和一些特殊情况的处理。

在这个项目进行当中遇到的一个问题就对于一个View的一个default大小应该怎么设置的问题,如果对于View的初始化有一定的了解,那么相信这个问题应该是不难解决的,主要的方法在于重写onMeasure()这个方法,然后使得View具有默认的大小。

@Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        // TODO Auto-generated method stub        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        int width = measureDimension(WIDTH_DEFAULT, widthMeasureSpec);        int height = measureDimension(HEIGHT_DEFAULT, heightMeasureSpec);        setMeasuredDimension(width, height);    }    public int measureDimension(int defaultSize, int measureSpec) {        int result;        int specMode = MeasureSpec.getMode(measureSpec);        int specSize = MeasureSpec.getSize(measureSpec);        if (specMode == MeasureSpec.EXACTLY) {            result = specSize;        } else {            result = defaultSize;   //UNSPECIFIED            if (specMode == MeasureSpec.AT_MOST) {                result = Math.min(result, specSize);            }        }        return result;    }

如果对于这个项目有兴趣,也想了解下里面的实现的话,可以下载下源码,源码在github上



1 0