標籤:下拉重新整理 慕課網 圖形混合模式 貝茲路徑 自訂view
之前看到一種下拉重新整理的效果,與以往的下拉效果都不一樣,大多數下拉重新整理都是一個圓形進度條在旋轉,而這個下拉重新整理則是一個不斷填充的效果。本以為這是個自訂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();// 以上畫貝茲路徑代碼參考自愛哥部落格// http://blog.csdn.net/aigestudio/article/details/41960507mCanvas.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的模式,進行對應的邏輯處理}}
整個實現過程還是相對簡單的,基本上注釋都講的很清楚了,這裡也不再重複了,文章中涉及到的兩個知識點(圖形的混合模式和貝茲路徑)的相關內容參考下面兩篇文章
圖形混合模式 http://blog.csdn.net/aigestudio/article/details/41316141
貝茲路徑 http://blog.csdn.net/aigestudio/article/details/41960507
都是愛哥的文章,個人覺得寫得很細。
慕課網app下拉重新整理表徵圖填充效果的實現