慕课网app下拉刷新图标填充效果的实现

之前看到一种下拉刷新的效果,与以往的下拉效果都不一样,大多数下拉刷新都是一个圆形进度条在旋转,而这个下拉刷新则是一个不断填充的效果。本以为这是个自定义View,后来反编译慕课网的app后提取资源的时候看到好多的图片,那大概慕课网app内部的实现应该是帧动画达到这种效果。而当我看到这种效果的时候,由于前段时间在学自定义控件,所以本能的反应则是自定义的。首先我们看下慕课网的效果。如下图

而我的也实现了一个这个图标填充的简单版。如下图

整个实现使用图形的混合模式+贝塞尔曲线,贝塞尔曲线的绘制参考自爱哥的博客 贝塞尔曲线内容

资源文件就只有下面这个图标,该图标提取自慕课网app,然后对内部的火焰进行透明处理过

既然是自定义View,那就要继承View,实现onDraw,onMeasure等方法,为了简单起见,这里将控件的宽度高度直接设置为图片的宽度和高度,,而没有去实现相应的逻辑去判断MeasureSpec的模式是哪个从而进行处理。

先贴代码

package cn.edu.zafu.view;import android.content.Context;import android.graphics.Bitmap;import android.graphics.Bitmap.Config;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Path;import android.graphics.PorterDuff;import android.graphics.PorterDuffXfermode;import android.util.AttributeSet;import android.view.View;/** * @author lizhangqu * * 2015-3-5 */public class CustomView extends View {private PorterDuffXfermode porterDuffXfermode;//Xfermodeprivate Paint paint;private Bitmap bitmap;//源图片private final int RED = 0xc9394a;//暗红色private int width, height;//控件宽高private Path path;//画贝塞尔曲线需要用到private Canvas mCanvas;//在该画布上绘制目标图片private Bitmap bg;//目标图片private float controlX, controlY;//贝塞尔曲线控制点,使用三阶贝塞尔曲线曲线,需要两个控制点,两个控制点都在该变量基础上生成private float waveY;//上升的高度private boolean isIncrease;//用于控制控制点水平移动public CustomView(Context context) {this(context, null);}public CustomView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public CustomView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);init();}private void init() {//初始化画笔paint = new Paint();paint.setAntiAlias(true);paint.setDither(true);paint.setStyle(Paint.Style.FILL);paint.setColor(Color.parseColor("#ffc9394a"));//获得资源文件bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.mooc);//设置宽高为图片的宽高width = bitmap.getWidth();height = bitmap.getHeight();//初始状态值waveY = 7 / 8F * height;controlY = 17 / 16F * height;//初始化XfermodeporterDuffXfermode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);//初始化pathpath = new Path();//初始化画布mCanvas = new Canvas();//创建bitmapbg = Bitmap.createBitmap(width, height, Config.ARGB_8888);//将新建的bitmap注入画布mCanvas.setBitmap(bg);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);drawTargetBitmap();// 画目标图,存在bg上canvas.drawBitmap(bg, 0, 0, null);//将目标图绘制在当前画布上invalidate();// 重绘,这里为了方便看效果,可以使用线程对这部分代码进行控制}private void drawTargetBitmap() {path.reset();// 重置pathbg.eraseColor(Color.parseColor("#00ffffff"));// 擦除像素// 当控制点的x坐标大于或等于终点x坐标时更改标识值if (controlX >= width + 1 / 2 * width) {isIncrease = false;}// 当控制点的x坐标小于或等于起点x坐标时更改标识值else if (controlX <= -1 / 2 * width) {isIncrease = true;}// 根据标识值判断当前的控制点x坐标是该加还是减controlX = isIncrease ? controlX + 10 : controlX – 10;if (controlY >= 0) {// 波浪上移controlY -= 1;waveY -= 1;} else {// 超出则重置位置waveY = 7 / 8F * height;controlY = 17 / 16F * height;}//贝塞尔曲线的生成path.moveTo(0, waveY);path.cubicTo(controlX / 2, waveY – (controlY – waveY),(controlX + width) / 2, controlY, width, waveY);path.lineTo(width, height);path.lineTo(0, height);//进行闭合path.close();// 以上画贝塞尔曲线代码参考自爱哥博客// mCanvas.drawBitmap(bitmap, 0, 0, paint);// 画慕课网logopaint.setXfermode(porterDuffXfermode);// 设置XfermodemCanvas.drawPath(path, paint);// 画三阶贝塞尔曲线paint.setXfermode(null);// 重置Xfermode}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {setMeasuredDimension(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));// 设置高度款第为logo宽度和高度,实际开发中应该判断MeasureSpec的模式,进行对应的逻辑处理}}

整个实现过程还是相对简单的,基本上注释都讲的很清楚了,这里也不再重复了,文章中涉及到的两个知识点(图形的混合模式和贝塞尔曲线)的相关内容参考下面两篇文章

图形混合模式

贝塞尔曲线

都是爱哥的文章,个人觉得写得很细。

经历一种身体下了地狱,眼睛进入天堂,灵魂归入故里。

慕课网app下拉刷新图标填充效果的实现

相关文章:

你感兴趣的文章:

标签云: