package com.scwang.smart.refresh.header;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import com.scwang.smart.drawable.ProgressDrawable;
import com.scwang.smart.refresh.header.material.MaterialProgressDrawable;
import com.scwang.smart.refresh.header.waterdrop.WaterDropView;
import com.scwang.smart.refresh.layout.api.RefreshHeader;
import com.scwang.smart.refresh.layout.api.RefreshLayout;
import com.scwang.smart.refresh.layout.constant.RefreshState;
import com.scwang.smart.refresh.layout.constant.SpinnerStyle;
import com.scwang.smart.refresh.layout.simple.SimpleComponent;
import com.scwang.smart.refresh.layout.util.SmartUtil;
import static android.view.View.MeasureSpec.AT_MOST;
import static android.view.View.MeasureSpec.EXACTLY;
import static android.view.View.MeasureSpec.getSize;
import static android.view.View.MeasureSpec.makeMeasureSpec;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
/**
* WaterDropHeader
* Created by scwang on 2017/5/31.
* from https://github.com/THEONE10211024/WaterDropListView
*/
public class WaterDropHeader extends SimpleComponent implements RefreshHeader {
//
protected static final float MAX_PROGRESS_ANGLE = 0.8f;
protected RefreshState mState;
protected ImageView mImageView;
protected WaterDropView mWaterDropView;
protected ProgressDrawable mProgressDrawable;
protected MaterialProgressDrawable mProgress;
//
//
public WaterDropHeader(Context context) {
this(context, null);
}
public WaterDropHeader(Context context, AttributeSet attrs) {
super(context, attrs, 0);
final ViewGroup thisGroup = this;
for (SpinnerStyle style : SpinnerStyle.values) {
if (style.scale) {
mSpinnerStyle = style;
break;
}
}
mWaterDropView = new WaterDropView(context);
mWaterDropView.updateCompleteState(0);
thisGroup.addView(mWaterDropView, MATCH_PARENT, MATCH_PARENT);
mProgressDrawable = new ProgressDrawable();
final Drawable progressDrawable = mProgressDrawable;
progressDrawable.setCallback(this);
progressDrawable.setBounds(0, 0, SmartUtil.dp2px(20), SmartUtil.dp2px(20));
mImageView = new ImageView(context);
mProgress = new MaterialProgressDrawable(mImageView);
// mProgress.setBackgroundColor(0xffffffff);
// mProgress.setAlpha(255);
mProgress.setColorSchemeColors(0xffffffff,0xff0099cc,0xffff4444,0xff669900,0xffaa66cc,0xffff8800);
mImageView.setImageDrawable(mProgress);
thisGroup.addView(mImageView, SmartUtil.dp2px(30), SmartUtil.dp2px(30));
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
final View imageView = mImageView;
final View dropView = mWaterDropView;
LayoutParams lpImage = (LayoutParams) imageView.getLayoutParams();
imageView.measure(
makeMeasureSpec(lpImage.width, EXACTLY),
makeMeasureSpec(lpImage.height, EXACTLY)
);
dropView.measure(
makeMeasureSpec(getSize(widthMeasureSpec), AT_MOST),
heightMeasureSpec
);
int maxWidth = Math.max(imageView.getMeasuredWidth(), dropView.getMeasuredWidth());
int maxHeight = Math.max(imageView.getMeasuredHeight(), dropView.getMeasuredHeight());
super.setMeasuredDimension(View.resolveSize(maxWidth, widthMeasureSpec), View.resolveSize(maxHeight, heightMeasureSpec));
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
final View thisView = this;
final View imageView = mImageView;
final View dropView = mWaterDropView;
final int measuredWidth = thisView.getMeasuredWidth();
final int widthWaterDrop = dropView.getMeasuredWidth();
final int heightWaterDrop = dropView.getMeasuredHeight();
final int leftWaterDrop = measuredWidth / 2 - widthWaterDrop / 2;
final int topWaterDrop = 0;
dropView.layout(leftWaterDrop, topWaterDrop, leftWaterDrop + widthWaterDrop, topWaterDrop + heightWaterDrop);
final int widthImage = imageView.getMeasuredWidth();
final int heightImage = imageView.getMeasuredHeight();
final int leftImage = measuredWidth / 2 - widthImage / 2;
int topImage = widthWaterDrop / 2 - widthImage / 2;
if (topImage + heightImage > dropView.getBottom() - (widthWaterDrop - widthImage) / 2) {
topImage = dropView.getBottom() - (widthWaterDrop - widthImage) / 2 - heightImage;
}
imageView.layout(leftImage, topImage, leftImage + widthImage, topImage + heightImage);
}
//
//
@Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
final View thisView = this;
final View dropView = mWaterDropView;
final Drawable progressDrawable = mProgressDrawable;
if (mState == RefreshState.Refreshing) {
canvas.save();
canvas.translate(
thisView.getWidth()/2f-progressDrawable.getBounds().width()/2f,
mWaterDropView.getMaxCircleRadius()
+dropView.getPaddingTop()
-progressDrawable.getBounds().height()/2f
);
progressDrawable.draw(canvas);
canvas.restore();
}
}
@Override
public void invalidateDrawable(@NonNull Drawable drawable) {
final View thisView = this;
thisView.invalidate();
// if (drawable == mProgressDrawable) {
// super.invalidate();
// } else {
// super.invalidateDrawable(drawable);
// }
}
//
//
@Override
public void onMoving(boolean isDragging, float percent, int offset, int height, int maxDragHeight) {
if (isDragging || (mState != RefreshState.Refreshing && mState != RefreshState.RefreshReleased)) {
final View dropView = mWaterDropView;
mWaterDropView.updateCompleteState(Math.max(offset, 0), height + maxDragHeight);
dropView.postInvalidate();
}
if (isDragging) {
float originalDragPercent = 1f * offset / height;
float dragPercent = Math.min(1f, Math.abs(originalDragPercent));
float adjustedPercent = (float) Math.max(dragPercent - .4, 0) * 5 / 3;
float extraOS = Math.abs(offset) - height;
float tensionSlingshotPercent = Math.max(0, Math.min(extraOS, (float) height * 2)
/ (float) height);
float tensionPercent = (float) ((tensionSlingshotPercent / 4) - Math.pow(
(tensionSlingshotPercent / 4), 2)) * 2f;
float strokeStart = adjustedPercent * .8f;
float rotation = (-0.25f + .4f * adjustedPercent + tensionPercent * 2) * .5f;
mProgress.showArrow(true);
mProgress.setStartEndTrim(0f, Math.min(MAX_PROGRESS_ANGLE, strokeStart));
mProgress.setArrowScale(Math.min(1f, adjustedPercent));
mProgress.setProgressRotation(rotation);
}
}
@Override
public void onStateChanged(@NonNull RefreshLayout refreshLayout, @NonNull RefreshState oldState, @NonNull RefreshState newState) {
final View dropView = mWaterDropView;
final View imageView = mImageView;
mState = newState;
switch (newState) {
case None:
dropView.setVisibility(View.VISIBLE);
imageView.setVisibility(View.VISIBLE);
break;
case PullDownToRefresh:
dropView.setVisibility(View.VISIBLE);
imageView.setVisibility(View.VISIBLE);
break;
case PullDownCanceled:
break;
case ReleaseToRefresh:
dropView.setVisibility(View.VISIBLE);
imageView.setVisibility(View.VISIBLE);
break;
case Refreshing:
break;
case RefreshFinish:
dropView.setVisibility(View.GONE);
imageView.setVisibility(View.GONE);
break;
}
}
@Override
public void onReleased(@NonNull final RefreshLayout layout, int height, int maxDragHeight) {
final View imageView = mImageView;
final View dropView = mWaterDropView;
mProgressDrawable.start();
imageView.setVisibility(GONE);
mWaterDropView.createAnimator().start();//开始回弹
dropView.animate().setDuration(150).alpha(0).setListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator animation) {
dropView.setVisibility(GONE);
dropView.setAlpha(1);
}
});
}
@Override
public int onFinish(@NonNull RefreshLayout layout, boolean success) {
mProgressDrawable.stop();
return 0;
}
/**
* @param colors 对应Xml中配置的 srlPrimaryColor srlAccentColor
* @deprecated 请使用 {@link RefreshLayout#setPrimaryColorsId(int...)}
*/
@Override@Deprecated
public void setPrimaryColors(@ColorInt int ... colors) {
if (colors.length > 0) {
mWaterDropView.setIndicatorColor(colors[0]);
}
}
//
}