/**
* Copyright 2015 bingoogolapple
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.cheng.animationstudy.customview.bagrefresh;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
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.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.view.View;
import com.cheng.animationstudy.R;
/**
* 作者:王浩 邮件:bingoogolapple@gmail.com
* 创建时间:15/5/21 10:43
* 描述:慕课网下拉刷新风格控件
*/
public class BGAMoocStyleRefreshView extends View {
private PorterDuffXfermode mXfermode;
/**
* 用来画临时图像的画笔
*/
private Paint mPaint;
/**
* 用来画临时图像的画布
*/
private Canvas mCanvas;
/**
* 原始的图片
*/
private Bitmap mOriginalBitmap;
/**
* 原始的图片宽度
*/
private int mOriginalBitmapWidth;
/**
* 原始的图片高度
*/
private int mOriginalBitmapHeight;
/**
* 最终生成的图片
*/
private Bitmap mUltimateBitmap;
/**
* 贝塞尔曲线路径
*/
private Path mBezierPath;
/**
* 贝塞尔曲线控制点x
*/
private float mBezierControlX;
/**
* 贝塞尔曲线控制点y
*/
private float mBezierControlY;
/**
* 贝塞尔曲线原始的控制点y
*/
private float mBezierControlOriginalY;
/**
* 当前波纹的y值
*/
private float mWaveY;
/**
* 波纹原始的y值
*/
private float mWaveOriginalY;
/**
* 贝塞尔曲线控制点x是否增加
*/
private boolean mIsBezierControlXIncrease;
/**
* 是否正在刷新
*/
private boolean mIsRefreshing = false;
/**
* 最终生成图片的填充颜色
*/
private int mUltimateColor;
public BGAMoocStyleRefreshView(Context context) {
this(context, null);
}
public BGAMoocStyleRefreshView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public BGAMoocStyleRefreshView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initAttrs(context, attrs);
initPaint();
initCanvas();
}
private void initAttrs(Context context, AttributeSet attrs) {
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.BGAMoocStyleRefreshView);
BitmapDrawable originalBitmap = (BitmapDrawable) typedArray.getDrawable(R.styleable.BGAMoocStyleRefreshView_mv_originalImg);
if (originalBitmap == null) {
throw new RuntimeException(BGAMoocStyleRefreshView.class.getSimpleName() + "必须设置原始图片");
}
mOriginalBitmap = originalBitmap.getBitmap();
mUltimateColor = typedArray.getColor(R.styleable.BGAMoocStyleRefreshView_mv_ultimateColor, Color.rgb(27, 128, 255));
typedArray.recycle();
}
private void initPaint() {
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(mUltimateColor);
}
public void setUltimateColor(int ultimateColor) {
mUltimateColor = ultimateColor;
if (mPaint == null) {
initPaint();
}
mPaint.setColor(mUltimateColor);
}
private void initCanvas() {
mOriginalBitmapWidth = mOriginalBitmap.getWidth();
mOriginalBitmapHeight = mOriginalBitmap.getHeight();
// 初始状态值
mWaveOriginalY = mOriginalBitmapHeight;
mWaveY = 1.2f * mWaveOriginalY;
mBezierControlOriginalY = 1.25f * mWaveOriginalY;
mBezierControlY = mBezierControlOriginalY;
mXfermode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);
mBezierPath = new Path();
mCanvas = new Canvas();
mUltimateBitmap = Bitmap.createBitmap(mOriginalBitmapWidth, mOriginalBitmapHeight, Config.ARGB_8888);
mCanvas.setBitmap(mUltimateBitmap);
}
public void setOriginalBitmap(Bitmap originalBitmap) {
mOriginalBitmap = originalBitmap;
initCanvas();
}
@Override
protected void onDraw(Canvas canvas) {
drawUltimateBitmap();
// 将目标图绘制在当前画布上,起点为左边距,上边距的交点
canvas.drawBitmap(mUltimateBitmap, getPaddingLeft(), getPaddingTop(), null);
if (mIsRefreshing) {
invalidate();
}
}
/**
* 绘制最终的图片
*/
private void drawUltimateBitmap() {
mBezierPath.reset();
mUltimateBitmap.eraseColor(Color.parseColor("#00ffffff"));
if (mBezierControlX >= mOriginalBitmapWidth + 1 / 2 * mOriginalBitmapWidth) {
mIsBezierControlXIncrease = false;
} else if (mBezierControlX <= -1 / 2 * mOriginalBitmapWidth) {
mIsBezierControlXIncrease = true;
}
mBezierControlX = mIsBezierControlXIncrease ? mBezierControlX + 10 : mBezierControlX - 10;
if (mBezierControlY >= 0) {
mBezierControlY -= 2;
mWaveY -= 2;
} else {
mWaveY = mWaveOriginalY;
mBezierControlY = mBezierControlOriginalY;
}
mBezierPath.moveTo(0, mWaveY);
mBezierPath.cubicTo(mBezierControlX / 2, mWaveY - (mBezierControlY - mWaveY), (mBezierControlX + mOriginalBitmapWidth) / 2, mBezierControlY, mOriginalBitmapWidth, mWaveY);
mBezierPath.lineTo(mOriginalBitmapWidth, mOriginalBitmapHeight);
mBezierPath.lineTo(0, mOriginalBitmapHeight);
mBezierPath.close();
mCanvas.drawBitmap(mOriginalBitmap, 0, 0, mPaint);
mPaint.setXfermode(mXfermode);
mCanvas.drawPath(mBezierPath, mPaint);
mPaint.setXfermode(null);
}
public void startRefreshing() {
mIsRefreshing = true;
reset();
}
public void stopRefreshing() {
mIsRefreshing = false;
reset();
}
private void reset() {
mWaveY = mWaveOriginalY;
mBezierControlY = mBezierControlOriginalY;
mBezierControlX = 0;
postInvalidate();
}
@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 + getPaddingLeft() + getPaddingRight();
} else {
width = mOriginalBitmapWidth + getPaddingLeft() + getPaddingRight();
if (widthMode == MeasureSpec.AT_MOST) {
width = Math.min(width, widthSize);
}
}
if (heightMode == MeasureSpec.EXACTLY) {
height = heightSize + getPaddingTop() + getPaddingBottom();
} else {
height = mOriginalBitmapHeight + getPaddingTop() + getPaddingBottom();
if (heightMode == MeasureSpec.AT_MOST) {
height = Math.min(height, heightSize);
}
}
setMeasuredDimension(width, height);
}
}