Androidドロップダウンで素晴らしいアニメーションをリフレッシュ
14307 ワード
以前は、従来のドロップダウン効果とは異なり、ほとんどのドロップダウンリフレッシュは円形の進捗バーが回転していますが、このドロップダウンリフレッシュは絶えず充填されている効果です.これはカスタムViewだと思っていたが、その後、慕課網のappを逆コンパイルしてリソースを抽出したときに多くの画像を見た.それはおそらく慕課網app内部の実現はフレームアニメーションがこのような効果を達成したはずだ.この効果を見たとき、この間カスタムコントロールを習っていたので、本能的な反応はカスタムでした.まず、慕課網の効果を見てみましょう.以下の図
塗りつぶしの効果を停止するには、関数setRefreshでisRefresh変数をfalseに設定します.全体の実現過程はまだ比較的簡単で、基本的に注釈はすべてはっきり言って、ここでももう繰り返しません.文章の中で関連する2つの知識点(図形の混合モードとベッセル曲線)の関連内容は次の2つの文章の図形の混合モードを参考にします.http://blog.csdn.net/aigestudio/article/details/41316141ベッセル曲線http://blog.csdn.net/aigestudio/article/details/41960507いずれも愛兄の文章で、個人的には細かく書かれていると思います.
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;// Xfermode
private Paint paint;//
private Bitmap bitmap;//
private int width, height;//
private Path path;//
private Canvas mCanvas;//
private Bitmap bg;//
private float controlX, controlY;// , , ,
private float waveY;//
private boolean isIncrease;//
private boolean isReflesh = true;// , true
/** * @return */
public boolean isReflesh() {
return isReflesh;
}
/** * * * @param isReflesh */
public void setReflesh(boolean isReflesh) {
this.isReflesh = isReflesh;
//
postInvalidate();
}
/** * @param context */
public CustomView(Context context) {
this(context, null);
}
/** * @param context * @param attrs */
public CustomView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
/** * @param context * @param attrs * @param defStyle */
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;
// Xfermode
porterDuffXfermode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);
// path
path = new Path();
//
mCanvas = new Canvas();
// bitmap
bg = Bitmap.createBitmap(width, height, Config.ARGB_8888);
// bitmap
mCanvas.setBitmap(bg);
}
@Override
protected void onDraw(Canvas canvas) {
// , bg
drawTargetBitmap();
// , ,
canvas.drawBitmap(bg, getPaddingLeft(), getPaddingTop(), null);
if (isReflesh) {
// , boolean isReflesh , , true
invalidate();
}
}
private void drawTargetBitmap() {
// path
path.reset();
//
bg.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);
// controlX,controlY
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/41960507
mCanvas.drawBitmap(bitmap, 0, 0, paint);// logo
paint.setXfermode(porterDuffXfermode);// Xfermode
mCanvas.drawPath(path, paint);//
paint.setXfermode(null);// Xfermode
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
//
int width, height;
if (widthMode == MeasureSpec.EXACTLY) {
//
width = widthSize;
} else {
//
width = this.width + getPaddingLeft() + getPaddingRight();
;
if (widthMode == MeasureSpec.AT_MOST) {
//
width = Math.min(width, widthSize);
}
}
if (heightMode == MeasureSpec.EXACTLY) {
//
height = heightSize;
} else {
//
height = this.height + getPaddingTop() + getPaddingBottom();
;
if (heightMode == MeasureSpec.AT_MOST) {
//
height = Math.min(height, heightSize);
}
}
// logo , MeasureSpec , ,
setMeasuredDimension(width, height);
}
}
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<cn.edu.zafu.view.CustomView
android:id="@+id/cv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="20dp"
android:layout_centerInParent="true"
android:background="#0000ff"
/>
</RelativeLayout>
塗りつぶしの効果を停止するには、関数setRefreshでisRefresh変数をfalseに設定します.全体の実現過程はまだ比較的簡単で、基本的に注釈はすべてはっきり言って、ここでももう繰り返しません.文章の中で関連する2つの知識点(図形の混合モードとベッセル曲線)の関連内容は次の2つの文章の図形の混合モードを参考にします.http://blog.csdn.net/aigestudio/article/details/41316141ベッセル曲線http://blog.csdn.net/aigestudio/article/details/41960507いずれも愛兄の文章で、個人的には細かく書かれていると思います.