android模仿支付宝生活圈下拉加载控件TriangleLoadingView
2015-11-17 00:18
537 查看
前言
之前看到支付宝做的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上
相关文章推荐
- 开始认真学习Android了
- Android之Sqlite性能优化
- hotfix 微信收货地址在安卓上返回签名失败的bug
- 一个很酷的加载loading效果
- Android 沉浸式状态栏 状态栏透明应用布局全屏显示
- Android中进程与线程基础知识
- Android 通过接口传值
- Co-Debugging JNI with Android Studio and Visual Studio
- Android 显示时间
- Android应用都有哪些,具体实现用到的知识
- Android 从strings.xml文件中随机获取单个数组值
- Android  xml Animation  Drawable 画图
- FaceBook微光闪烁---第三方开源--shimmer-android
- Android实战技巧之四十七:不用预览拍照与图片缩放剪裁
- android webview javascript api扩展, armeabi-v7 armeabi,兼谈SDK及其开发者的品行
- Android屏幕适配全攻略(最权威的官方适配指导)
- 安卓位置服务简介
- android 之 下拉刷新PullToRefresh
- Android系统常用隐藏命令大全
- Android 开源库StickyListHeadersListView来实现ListView列表分组效果