package com.scwang.smart.refresh.header;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.view.animation.PathInterpolatorCompat;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import com.scwang.smart.refresh.header.flyrefresh.MountainSceneView;
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.util.SmartUtil;
/**
* 纸飞机和山丘
* Created by scwang on 2017/6/6.
* from https://github.com/race604/FlyRefresh
*/
public class FlyRefreshHeader extends FalsifyHeader implements RefreshHeader {
//
protected View mFlyView;
protected AnimatorSet mFlyAnimator;
protected RefreshLayout mRefreshLayout;
protected RefreshKernel mRefreshKernel;
protected MountainSceneView mSceneView;
protected int mOffset = 0;
protected float mCurrentPercent;
protected boolean mIsRefreshing = false;
protected int mMeasureHeight = 0;
//
//
public FlyRefreshHeader(Context context) {
super(context);
}
public FlyRefreshHeader(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (mMeasureHeight == 0) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mMeasureHeight = super.getMeasuredHeight();
}
super.setMeasuredDimension(
View.resolveSize(MeasureSpec.getSize(widthMeasureSpec), widthMeasureSpec),0);
}
//
//
@Override
public void onInitialized(@NonNull RefreshKernel kernel, int height, int maxDragHeight) {
if (mRefreshKernel == null) {
mRefreshKernel = kernel;
mRefreshLayout = kernel.getRefreshLayout();
mRefreshLayout.setEnableOverScrollDrag(false);
mRefreshLayout.setHeaderHeightPx(0);
mRefreshLayout.setHeaderTriggerRate(mMeasureHeight);
mRefreshLayout.setHeaderMaxDragRate(mMeasureHeight * 2.5f);
}
}
@Override
public void onMoving(boolean isDragging, float percent, int offset, int height, int maxDragHeight) {
if (isDragging || !mIsRefreshing) {
if (offset < 0) {
if (mOffset > 0) {
offset = 0;
percent = 0;
} else {
return;
}
}
mOffset = offset;
mCurrentPercent = percent;
if (mSceneView != null) {
mSceneView.updatePercent(percent);
final View sceneView = mSceneView;
sceneView.postInvalidate();
}
if (mFlyView != null) {
if (height + maxDragHeight > 0) {
mFlyView.setRotation((-45f) * offset / (height + maxDragHeight));
} else {
mFlyView.setRotation((-45f) * percent);
}
}
}
}
@Override
public void onReleased(@NonNull RefreshLayout layout, int height, int maxDragHeight) {
///* 提前关闭 下拉视图偏移 */
//mRefreshKernel.animSpinner(0); // 新版改成设置 HeaderHeight=0 来自动回到原始位置
if (mCurrentPercent > 0) {
ValueAnimator valueAnimator = ValueAnimator.ofFloat(mCurrentPercent, 0);
valueAnimator.setDuration(300);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
onMoving(true,(float) animation.getAnimatedValue(), 0, 0, 0);
}
});
valueAnimator.start();
mCurrentPercent = 0;
}
if (mFlyView != null && !mIsRefreshing) {
if (mFlyAnimator != null) {
mFlyAnimator.end();
mFlyView.clearAnimation();
}
mIsRefreshing = true;
layout.setEnableRefresh(false);
final int offDistX = ((View) mRefreshLayout).getWidth()-mFlyView.getLeft();
final int offDistY = -(mFlyView.getTop() - mOffset) * 2 / 3;
ObjectAnimator transX = ObjectAnimator.ofFloat(mFlyView, "translationX", 0, offDistX);
ObjectAnimator transY = ObjectAnimator.ofFloat(mFlyView, "translationY", 0, offDistY);
transY.setInterpolator(PathInterpolatorCompat.create(0.7f, 1f));
ObjectAnimator rotation = ObjectAnimator.ofFloat(mFlyView, "rotation", mFlyView.getRotation(), 0);
rotation.setInterpolator(new DecelerateInterpolator());
ObjectAnimator rotationX = ObjectAnimator.ofFloat(mFlyView, "rotationX", mFlyView.getRotationX(), 50);
rotationX.setInterpolator(new DecelerateInterpolator());
AnimatorSet flyUpAnim = new AnimatorSet();
flyUpAnim.setDuration(800);
flyUpAnim.playTogether(transX
,transY
,rotation
,rotationX
,ObjectAnimator.ofFloat(mFlyView, "scaleX", mFlyView.getScaleX(), 0.5f)
,ObjectAnimator.ofFloat(mFlyView, "scaleY", mFlyView.getScaleY(), 0.5f)
);
mFlyAnimator = flyUpAnim;
mFlyAnimator.start();
}
}
/**
* @param colors 对应Xml中配置的 srlPrimaryColor srlAccentColor
* @deprecated 请使用 {@link RefreshLayout#setPrimaryColorsId(int...)}
*/
@Override@Deprecated
public void setPrimaryColors(@ColorInt int ... colors) {
if (colors.length > 0) {
if (mSceneView != null) {
mSceneView.setPrimaryColor(colors[0]);
}
}
}
@Override
public int onFinish(@NonNull RefreshLayout layout, boolean success) {
if (mIsRefreshing) {
finishRefresh();
}
return super.onFinish(layout, success);
}
//
//
public void setUp(@Nullable MountainSceneView sceneView,@Nullable View flyView) {
mFlyView = flyView;
mSceneView = sceneView;
}
public void finishRefresh() {
finishRefresh(null);
}
public void finishRefresh(final AnimatorListenerAdapter listenerAdapter) {
if (mFlyView == null || !mIsRefreshing || mRefreshLayout == null) {
return;
}
if (mFlyAnimator != null) {
mFlyAnimator.end();
mFlyView.clearAnimation();
}
mIsRefreshing = false;
mRefreshLayout.finishRefresh(0);
final int offDistX = -mFlyView.getRight();
final int offDistY = -SmartUtil.dp2px(10);
AnimatorSet flyDownAnim = new AnimatorSet();
flyDownAnim.setDuration(800);
ObjectAnimator transX1 = ObjectAnimator.ofFloat(mFlyView, "translationX", mFlyView.getTranslationX(), offDistX);
ObjectAnimator transY1 = ObjectAnimator.ofFloat(mFlyView, "translationY", mFlyView.getTranslationY(), offDistY);
transY1.setInterpolator(PathInterpolatorCompat.create(0.1f, 1f));
ObjectAnimator rotation1 = ObjectAnimator.ofFloat(mFlyView, "rotation", mFlyView.getRotation(), 0);
ObjectAnimator rotationX1 = ObjectAnimator.ofFloat(mFlyView, "rotationX", mFlyView.getRotationX(), 30);
rotation1.setInterpolator(new AccelerateInterpolator());
flyDownAnim.playTogether(transX1, transY1
, rotation1
, rotationX1
, ObjectAnimator.ofFloat(mFlyView, "scaleX", mFlyView.getScaleX(), 0.9f)
, ObjectAnimator.ofFloat(mFlyView, "scaleY", mFlyView.getScaleY(), 0.9f)
);
flyDownAnim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
if (mFlyView != null) {
mFlyView.setRotationY(180);
}
}
});
AnimatorSet flyInAnim = new AnimatorSet();
flyInAnim.setDuration(800);
flyInAnim.setInterpolator(new DecelerateInterpolator());
ObjectAnimator tranX2 = ObjectAnimator.ofFloat(mFlyView, "translationX", offDistX, 0);
ObjectAnimator tranY2 = ObjectAnimator.ofFloat(mFlyView, "translationY", offDistY, 0);
ObjectAnimator rotationX2 = ObjectAnimator.ofFloat(mFlyView, "rotationX", 30, 0);
flyInAnim.playTogether(tranX2, tranY2
, rotationX2
, ObjectAnimator.ofFloat(mFlyView, "scaleX", 0.9f, 1f)
, ObjectAnimator.ofFloat(mFlyView, "scaleY", 0.9f, 1f)
);
flyInAnim.setStartDelay(100);
flyInAnim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
if (mFlyView != null) {
mFlyView.setRotationY(0);
}
}
@Override
public void onAnimationEnd(Animator animation) {
if (mRefreshLayout != null) {
mRefreshLayout.setEnableRefresh(true);
}
if (listenerAdapter != null) {
listenerAdapter.onAnimationEnd(animation);
}
}
});
mFlyAnimator = new AnimatorSet();
mFlyAnimator.playSequentially(flyDownAnim, flyInAnim);
mFlyAnimator.start();
}
//
}