package com.scwang.smart.refresh.header;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.Animation;
import android.view.animation.Transformation;
import com.scwang.smart.refresh.header.storehouse.StoreHouseBarItem;
import com.scwang.smart.refresh.header.storehouse.StoreHousePath;
import com.scwang.smart.refresh.layout.api.RefreshHeader;
import com.scwang.smart.refresh.layout.api.RefreshKernel;
import com.scwang.smart.refresh.layout.api.RefreshLayout;
import com.scwang.smart.refresh.layout.simple.SimpleComponent;
import com.scwang.smart.refresh.layout.util.SmartUtil;
import com.scwang.smartrefresh.header.R;
import java.util.ArrayList;
import java.util.List;
/**
* StoreHouseHeader
* Created by scwang on 2017/5/31.
* from https://github.com/liaohuqiu/android-Ultra-Pull-To-Refresh
*/
@SuppressWarnings({"unused", "UnusedReturnValue", "SameParameterValue"})
public class StoreHouseHeader extends SimpleComponent implements RefreshHeader {
//
public List mItemList = new ArrayList<>();
protected float mScale = 1;
protected int mLineWidth = -1;
protected int mDropHeight = -1;
protected int mHorizontalRandomness = -1;
protected static final float mInternalAnimationFactor = 0.7f;
protected float mProgress = 0;
protected int mDrawZoneWidth = 0;
protected int mDrawZoneHeight = 0;
protected int mOffsetX = 0;
protected int mOffsetY = 0;
protected static final float mBarDarkAlpha = 0.4f;
protected static final float mFromAlpha = 1.0f;
protected static final float mToAlpha = 0.4f;
protected int mLoadingAniDuration = 1000;
protected int mLoadingAniSegDuration = 1000;
protected static final int mLoadingAniItemDuration = 400;
protected int mTextColor = Color.WHITE;
protected int mBackgroundColor = 0;
protected boolean mIsInLoading = false;
protected boolean mEnableFadeAnimation = false;
protected Matrix mMatrix = new Matrix();
protected RefreshKernel mRefreshKernel;
protected AniController mAniController = new AniController();
protected Transformation mTransformation = new Transformation();
//
//
public StoreHouseHeader(Context context) {
this(context, null);
}
public StoreHouseHeader(Context context, AttributeSet attrs) {
super(context, attrs, 0);
mLineWidth = SmartUtil.dp2px(1);
mDropHeight = SmartUtil.dp2px(40);
mHorizontalRandomness = Resources.getSystem().getDisplayMetrics().widthPixels / 2;
mBackgroundColor = 0xff333333;
setTextColor(0xffcccccc);
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.StoreHouseHeader);
mLineWidth = ta.getDimensionPixelOffset(R.styleable.StoreHouseHeader_srlLineWidth, mLineWidth);
mDropHeight = ta.getDimensionPixelOffset(R.styleable.StoreHouseHeader_srlDropHeight, mDropHeight);
mEnableFadeAnimation = ta.getBoolean(R.styleable.StoreHouseHeader_srlEnableFadeAnimation, mEnableFadeAnimation);
mLineWidth = ta.getDimensionPixelOffset(R.styleable.StoreHouseHeader_shhLineWidth, mLineWidth);
mDropHeight = ta.getDimensionPixelOffset(R.styleable.StoreHouseHeader_shhDropHeight, mDropHeight);
mEnableFadeAnimation = ta.getBoolean(R.styleable.StoreHouseHeader_shhEnableFadeAnimation, mEnableFadeAnimation);
if (ta.hasValue(R.styleable.StoreHouseHeader_shhText)) {
initWithString(ta.getString(R.styleable.StoreHouseHeader_shhText));
} else if (ta.hasValue(R.styleable.StoreHouseHeader_srlText)) {
initWithString(ta.getString(R.styleable.StoreHouseHeader_srlText));
} else {
initWithString("StoreHouse");
}
ta.recycle();
final View thisView = this;
thisView.setMinimumHeight(mDrawZoneHeight + SmartUtil.dp2px(40));
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final View thisView = this;
// int height = getTopOffset() + mDrawZoneHeight + getBottomOffset();
// heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
super.setMeasuredDimension(
View.resolveSize(super.getSuggestedMinimumWidth(), widthMeasureSpec),
View.resolveSize(super.getSuggestedMinimumHeight(), heightMeasureSpec));
mOffsetX = (thisView.getMeasuredWidth() - mDrawZoneWidth) / 2;
mOffsetY = (thisView.getMeasuredHeight() - mDrawZoneHeight) / 2;//getTopOffset();
mDropHeight = thisView.getMeasuredHeight() / 2;//getTopOffset();
}
@Override
protected void dispatchDraw(Canvas canvas) {
final View thisView = this;
final int c1 = canvas.save();
final int len = mItemList.size();
final float progress = thisView.isInEditMode() ? 1 : mProgress;
for (int i = 0; i < len; i++) {
canvas.save();
StoreHouseBarItem storeHouseBarItem = mItemList.get(i);
float offsetX = mOffsetX + storeHouseBarItem.midPoint.x;
float offsetY = mOffsetY + storeHouseBarItem.midPoint.y;
if (mIsInLoading) {
storeHouseBarItem.getTransformation(thisView.getDrawingTime(), mTransformation);
canvas.translate(offsetX, offsetY);
} else {
if (progress == 0) {
storeHouseBarItem.resetPosition(mHorizontalRandomness);
continue;
}
float startPadding = (1 - mInternalAnimationFactor) * i / len;
float endPadding = 1 - mInternalAnimationFactor - startPadding;
// done
if (progress == 1 || progress >= 1 - endPadding) {
canvas.translate(offsetX, offsetY);
storeHouseBarItem.setAlpha(mBarDarkAlpha);
} else {
float realProgress;
if (progress <= startPadding) {
realProgress = 0;
} else {
realProgress = Math.min(1, (progress - startPadding) / mInternalAnimationFactor);
}
offsetX += storeHouseBarItem.translationX * (1 - realProgress);
offsetY += -mDropHeight * (1 - realProgress);
mMatrix.reset();
mMatrix.postRotate(360 * realProgress);
mMatrix.postScale(realProgress, realProgress);
mMatrix.postTranslate(offsetX, offsetY);
storeHouseBarItem.setAlpha(mBarDarkAlpha * realProgress);
canvas.concat(mMatrix);
}
}
storeHouseBarItem.draw(canvas);
canvas.restore();
}
if (mIsInLoading) {
thisView.invalidate();
}
canvas.restoreToCount(c1);
super.dispatchDraw(canvas);
}
//
//
public StoreHouseHeader setLoadingAniDuration(int duration) {
mLoadingAniDuration = duration;
mLoadingAniSegDuration = duration;
return this;
}
public StoreHouseHeader setLineWidth(int width) {
mLineWidth = width;
for (int i = 0; i < mItemList.size(); i++) {
mItemList.get(i).setLineWidth(width);
}
return this;
}
public StoreHouseHeader setTextColor(@ColorInt int color) {
mTextColor = color;
for (int i = 0; i < mItemList.size(); i++) {
mItemList.get(i).setColor(color);
}
return this;
}
public StoreHouseHeader setDropHeight(int height) {
mDropHeight = height;
return this;
}
public StoreHouseHeader initWithString(String str) {
initWithString(str, 25);
return this;
}
public StoreHouseHeader initWithString(String str, int fontSize) {
List pointList = StoreHousePath.getPath(str, fontSize * 0.01f, 14);
initWithPointList(pointList);
return this;
}
public StoreHouseHeader initWithStringArray(int id) {
final View thisView = this;
String[] points = thisView.getResources().getStringArray(id);
List pointList = new ArrayList<>();
for (String point : points) {
String[] x = point.split(",");
float[] f = new float[4];
for (int j = 0; j < 4; j++) {
f[j] = Float.parseFloat(x[j]);
}
pointList.add(f);
}
initWithPointList(pointList);
return this;
}
public StoreHouseHeader setScale(float scale) {
mScale = scale;
return this;
}
public StoreHouseHeader initWithPointList(List pointList) {
float drawWidth = 0;
float drawHeight = 0;
boolean shouldLayout = mItemList.size() > 0;
mItemList.clear();
for (int i = 0; i < pointList.size(); i++) {
float[] line = pointList.get(i);
PointF startPoint = new PointF(SmartUtil.dp2px(line[0]) * mScale, SmartUtil.dp2px(line[1]) * mScale);
PointF endPoint = new PointF(SmartUtil.dp2px(line[2]) * mScale, SmartUtil.dp2px(line[3]) * mScale);
drawWidth = Math.max(drawWidth, startPoint.x);
drawWidth = Math.max(drawWidth, endPoint.x);
drawHeight = Math.max(drawHeight, startPoint.y);
drawHeight = Math.max(drawHeight, endPoint.y);
StoreHouseBarItem item = new StoreHouseBarItem(i, startPoint, endPoint, mTextColor, mLineWidth);
item.resetPosition(mHorizontalRandomness);
mItemList.add(item);
}
mDrawZoneWidth = (int) Math.ceil(drawWidth);
mDrawZoneHeight = (int) Math.ceil(drawHeight);
if (shouldLayout) {
final View thisView = this;
thisView.requestLayout();
}
return this;
}
//
//
@Override
public void onInitialized(@NonNull RefreshKernel kernel, int height, int maxDragHeight) {
// kernel.requestDrawBackgroundForHeader(mBackgroundColor);
mRefreshKernel = kernel;
mRefreshKernel.requestDrawBackgroundFor(this, mBackgroundColor);
}
@Override
public void onMoving(boolean isDragging, float percent, int offset, int height, int maxDragHeight) {
mProgress = (percent * .8f);
final View thisView = this;
thisView.invalidate();
}
// @Override
// public void onPulling(float percent, int offset, int height, int maxDragHeight) {
// mProgress = (percent * .8f);
// invalidate();
// }
//
// @Override
// public void onReleasing(float percent, int offset, int height, int maxDragHeight) {
// onPulling(percent, offset, height, maxDragHeight);
// }
@Override
public void onReleased(@NonNull RefreshLayout layout, int height, int maxDragHeight) {
mIsInLoading = true;
mAniController.start();
final View thisView = this;
thisView.invalidate();
}
@Override
public int onFinish(@NonNull RefreshLayout layout, boolean success) {
mIsInLoading = false;
mAniController.stop();
if (success && mEnableFadeAnimation) {
final View thisView = this;
thisView.startAnimation(new Animation() {{
super.setDuration(250);
super.setInterpolator(new AccelerateInterpolator());
}
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
final View thisView = StoreHouseHeader.this;
mProgress = (1 - interpolatedTime);
thisView.invalidate();
if (interpolatedTime == 1) {
for (int i = 0; i < mItemList.size(); i++) {
mItemList.get(i).resetPosition(mHorizontalRandomness);
}
}
}
});
return 250;
} else {
for (int i = 0; i < mItemList.size(); i++) {
mItemList.get(i).resetPosition(mHorizontalRandomness);
}
}
return 0;
}
/**
* @param colors 对应Xml中配置的 srlPrimaryColor srlAccentColor
* @deprecated 请使用 {@link RefreshLayout#setPrimaryColorsId(int...)}
*/
@Override@Deprecated
public void setPrimaryColors(@ColorInt int ... colors) {
if (colors.length > 0) {
mBackgroundColor = colors[0];
if (mRefreshKernel != null) {
// mRefreshKernel.requestDrawBackgroundForHeader(colors[0]);
mRefreshKernel.requestDrawBackgroundFor(this, mBackgroundColor);
}
if (colors.length > 1) {
setTextColor(colors[1]);
}
}
}
//
protected class AniController implements Runnable {
int mTick = 0;
int mCountPerSeg = 0;
int mSegCount = 0;
int mInterval = 0;
boolean mRunning = true;
protected void start() {
mRunning = true;
mTick = 0;
mInterval = mLoadingAniDuration / mItemList.size();
mCountPerSeg = mLoadingAniSegDuration / mInterval;
mSegCount = mItemList.size() / mCountPerSeg + 1;
run();
}
@Override
public void run() {
int pos = mTick % mCountPerSeg;
for (int i = 0; i < mSegCount; i++) {
int index = i * mCountPerSeg + pos;
if (index > mTick) {
continue;
}
index = index % mItemList.size();
StoreHouseBarItem item = mItemList.get(index);
item.setFillAfter(false);
item.setFillEnabled(true);
item.setFillBefore(false);
item.setDuration(mLoadingAniItemDuration);
item.start(mFromAlpha, mToAlpha);
}
mTick++;
if (mRunning && mRefreshKernel != null) {
final View refreshView = mRefreshKernel.getRefreshLayout().getLayout();
refreshView.postDelayed(this, mInterval);
}
}
protected void stop() {
mRunning = false;
final View thisView = StoreHouseHeader.this;
thisView.removeCallbacks(this);
}
}
}