feat:fix SwipeLayout
This commit is contained in:
parent
a47b3682db
commit
9c6802dccf
@ -16,6 +16,7 @@
|
|||||||
package pub.doric.demo;
|
package pub.doric.demo;
|
||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.graphics.Color;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.TypedValue;
|
import android.util.TypedValue;
|
||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
@ -51,7 +52,11 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
swipeLayout.setRefreshing(false);
|
swipeLayout.setRefreshing(false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
swipeLayout.setBackgroundColor(Color.YELLOW);
|
||||||
|
swipeLayout.getRefreshView().setBackgroundColor(Color.RED);
|
||||||
|
swipeLayout.setPullDownHeight(100);
|
||||||
RecyclerView recyclerView = findViewById(R.id.root);
|
RecyclerView recyclerView = findViewById(R.id.root);
|
||||||
|
recyclerView.setBackgroundColor(Color.WHITE);
|
||||||
recyclerView.setLayoutManager(new LinearLayoutManager(this));
|
recyclerView.setLayoutManager(new LinearLayoutManager(this));
|
||||||
try {
|
try {
|
||||||
String[] demos = getAssets().list("demo");
|
String[] demos = getAssets().list("demo");
|
||||||
|
@ -5,6 +5,7 @@ import android.util.AttributeSet;
|
|||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.view.animation.Animation;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
|
|
||||||
import androidx.annotation.AttrRes;
|
import androidx.annotation.AttrRes;
|
||||||
@ -18,6 +19,7 @@ import androidx.annotation.Nullable;
|
|||||||
*/
|
*/
|
||||||
public class DoricRefreshView extends FrameLayout implements IPullable {
|
public class DoricRefreshView extends FrameLayout implements IPullable {
|
||||||
private View content;
|
private View content;
|
||||||
|
private Animation.AnimationListener mListener;
|
||||||
|
|
||||||
public DoricRefreshView(@NonNull Context context) {
|
public DoricRefreshView(@NonNull Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
@ -77,4 +79,24 @@ public class DoricRefreshView extends FrameLayout implements IPullable {
|
|||||||
((IPullable) content).setProgressRotation(rotation);
|
((IPullable) content).setProgressRotation(rotation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setAnimationListener(Animation.AnimationListener listener) {
|
||||||
|
mListener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onAnimationStart() {
|
||||||
|
super.onAnimationStart();
|
||||||
|
if (mListener != null) {
|
||||||
|
mListener.onAnimationStart(getAnimation());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onAnimationEnd() {
|
||||||
|
super.onAnimationEnd();
|
||||||
|
if (mListener != null) {
|
||||||
|
mListener.onAnimationEnd(getAnimation());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -15,13 +15,10 @@ import android.view.animation.Transformation;
|
|||||||
import android.widget.AbsListView;
|
import android.widget.AbsListView;
|
||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
|
|
||||||
import androidx.annotation.ColorInt;
|
|
||||||
import androidx.annotation.ColorRes;
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.Px;
|
import androidx.annotation.Px;
|
||||||
import androidx.annotation.VisibleForTesting;
|
import androidx.annotation.VisibleForTesting;
|
||||||
import androidx.core.content.ContextCompat;
|
|
||||||
import androidx.core.view.NestedScrollingChild;
|
import androidx.core.view.NestedScrollingChild;
|
||||||
import androidx.core.view.NestedScrollingChildHelper;
|
import androidx.core.view.NestedScrollingChildHelper;
|
||||||
import androidx.core.view.NestedScrollingParent;
|
import androidx.core.view.NestedScrollingParent;
|
||||||
@ -111,7 +108,6 @@ public class DoricSwipeLayout extends ViewGroup implements NestedScrollingParent
|
|||||||
android.R.attr.enabled
|
android.R.attr.enabled
|
||||||
};
|
};
|
||||||
|
|
||||||
CircleImageView mCircleView;
|
|
||||||
private int mCircleViewIndex = -1;
|
private int mCircleViewIndex = -1;
|
||||||
|
|
||||||
protected int mFrom;
|
protected int mFrom;
|
||||||
@ -124,27 +120,20 @@ public class DoricSwipeLayout extends ViewGroup implements NestedScrollingParent
|
|||||||
|
|
||||||
int mCustomSlingshotDistance;
|
int mCustomSlingshotDistance;
|
||||||
|
|
||||||
CircularProgressDrawable mProgress;
|
|
||||||
|
|
||||||
private Animation mScaleAnimation;
|
private Animation mScaleAnimation;
|
||||||
|
|
||||||
private Animation mScaleDownAnimation;
|
private Animation mScaleDownAnimation;
|
||||||
|
|
||||||
private Animation mAlphaStartAnimation;
|
|
||||||
|
|
||||||
private Animation mAlphaMaxAnimation;
|
|
||||||
|
|
||||||
private Animation mScaleDownToStartAnimation;
|
private Animation mScaleDownToStartAnimation;
|
||||||
|
|
||||||
boolean mNotify;
|
boolean mNotify;
|
||||||
|
|
||||||
private int mCircleDiameter;
|
|
||||||
|
|
||||||
// Whether the client has set a custom starting position;
|
// Whether the client has set a custom starting position;
|
||||||
boolean mUsingCustomStart;
|
boolean mUsingCustomStart;
|
||||||
|
|
||||||
private OnChildScrollUpCallback mChildScrollUpCallback;
|
private OnChildScrollUpCallback mChildScrollUpCallback;
|
||||||
|
|
||||||
|
private DoricRefreshView mRefreshView;
|
||||||
private AnimationListener mRefreshListener = new AnimationListener() {
|
private AnimationListener mRefreshListener = new AnimationListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onAnimationStart(Animation animation) {
|
public void onAnimationStart(Animation animation) {
|
||||||
@ -157,33 +146,30 @@ public class DoricSwipeLayout extends ViewGroup implements NestedScrollingParent
|
|||||||
@Override
|
@Override
|
||||||
public void onAnimationEnd(Animation animation) {
|
public void onAnimationEnd(Animation animation) {
|
||||||
if (mRefreshing) {
|
if (mRefreshing) {
|
||||||
// Make sure the progress view is fully visible
|
mRefreshView.startAnimation();
|
||||||
mProgress.setAlpha(MAX_ALPHA);
|
|
||||||
mProgress.start();
|
|
||||||
if (mNotify) {
|
if (mNotify) {
|
||||||
if (mListener != null) {
|
if (mListener != null) {
|
||||||
mListener.onRefresh();
|
mListener.onRefresh();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mCurrentTargetOffsetTop = mCircleView.getTop();
|
mCurrentTargetOffsetTop = mRefreshView.getTop();
|
||||||
} else {
|
} else {
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
private int mPullDownHeight = 0;
|
||||||
|
|
||||||
void reset() {
|
void reset() {
|
||||||
mCircleView.clearAnimation();
|
mRefreshView.stopAnimation();
|
||||||
mProgress.stop();
|
mRefreshView.setVisibility(View.GONE);
|
||||||
mCircleView.setVisibility(View.GONE);
|
|
||||||
setColorViewAlpha(MAX_ALPHA);
|
|
||||||
// Return the circle to its start position
|
// Return the circle to its start position
|
||||||
if (mScale) {
|
if (mScale) {
|
||||||
setAnimationProgress(0 /* animation complete and view is hidden */);
|
setAnimationProgress(0 /* animation complete and view is hidden */);
|
||||||
} else {
|
} else {
|
||||||
setTargetOffsetTopAndBottom(mOriginalOffsetTop - mCurrentTargetOffsetTop);
|
setTargetOffsetTopAndBottom(mOriginalOffsetTop - mCurrentTargetOffsetTop);
|
||||||
}
|
}
|
||||||
mCurrentTargetOffsetTop = mCircleView.getTop();
|
mCurrentTargetOffsetTop = mRefreshView.getTop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -200,11 +186,6 @@ public class DoricSwipeLayout extends ViewGroup implements NestedScrollingParent
|
|||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setColorViewAlpha(int targetAlpha) {
|
|
||||||
mCircleView.getBackground().setAlpha(targetAlpha);
|
|
||||||
mProgress.setAlpha(targetAlpha);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The refresh indicator starting and resting position is always positioned
|
* The refresh indicator starting and resting position is always positioned
|
||||||
* near the top of the refreshing content. This position is a consistent
|
* near the top of the refreshing content. This position is a consistent
|
||||||
@ -265,7 +246,7 @@ public class DoricSwipeLayout extends ViewGroup implements NestedScrollingParent
|
|||||||
public void setProgressViewEndTarget(boolean scale, int end) {
|
public void setProgressViewEndTarget(boolean scale, int end) {
|
||||||
mSpinnerOffsetEnd = end;
|
mSpinnerOffsetEnd = end;
|
||||||
mScale = scale;
|
mScale = scale;
|
||||||
mCircleView.invalidate();
|
mRefreshView.invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -279,27 +260,6 @@ public class DoricSwipeLayout extends ViewGroup implements NestedScrollingParent
|
|||||||
mCustomSlingshotDistance = slingshotDistance;
|
mCustomSlingshotDistance = slingshotDistance;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* One of DEFAULT, or LARGE.
|
|
||||||
*/
|
|
||||||
public void setSize(int size) {
|
|
||||||
if (size != CircularProgressDrawable.LARGE && size != CircularProgressDrawable.DEFAULT) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
final DisplayMetrics metrics = getResources().getDisplayMetrics();
|
|
||||||
if (size == CircularProgressDrawable.LARGE) {
|
|
||||||
mCircleDiameter = (int) (CIRCLE_DIAMETER_LARGE * metrics.density);
|
|
||||||
} else {
|
|
||||||
mCircleDiameter = (int) (CIRCLE_DIAMETER * metrics.density);
|
|
||||||
}
|
|
||||||
// force the bounds of the progress circle inside the circle view to
|
|
||||||
// update by setting it to null before updating its size and then
|
|
||||||
// re-setting it
|
|
||||||
mCircleView.setImageDrawable(null);
|
|
||||||
mProgress.setStyle(size);
|
|
||||||
mCircleView.setImageDrawable(mProgress);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple constructor to use when creating a SwipeRefreshLayout from code.
|
* Simple constructor to use when creating a SwipeRefreshLayout from code.
|
||||||
*
|
*
|
||||||
@ -327,7 +287,6 @@ public class DoricSwipeLayout extends ViewGroup implements NestedScrollingParent
|
|||||||
mDecelerateInterpolator = new DecelerateInterpolator(DECELERATE_INTERPOLATION_FACTOR);
|
mDecelerateInterpolator = new DecelerateInterpolator(DECELERATE_INTERPOLATION_FACTOR);
|
||||||
|
|
||||||
final DisplayMetrics metrics = getResources().getDisplayMetrics();
|
final DisplayMetrics metrics = getResources().getDisplayMetrics();
|
||||||
mCircleDiameter = (int) (CIRCLE_DIAMETER * metrics.density);
|
|
||||||
|
|
||||||
createProgressView();
|
createProgressView();
|
||||||
setChildrenDrawingOrderEnabled(true);
|
setChildrenDrawingOrderEnabled(true);
|
||||||
@ -339,7 +298,6 @@ public class DoricSwipeLayout extends ViewGroup implements NestedScrollingParent
|
|||||||
mNestedScrollingChildHelper = new NestedScrollingChildHelper(this);
|
mNestedScrollingChildHelper = new NestedScrollingChildHelper(this);
|
||||||
setNestedScrollingEnabled(true);
|
setNestedScrollingEnabled(true);
|
||||||
|
|
||||||
mOriginalOffsetTop = mCurrentTargetOffsetTop = -mCircleDiameter;
|
|
||||||
moveToStart(1.0f);
|
moveToStart(1.0f);
|
||||||
|
|
||||||
final TypedArray a = context.obtainStyledAttributes(attrs, LAYOUT_ATTRS);
|
final TypedArray a = context.obtainStyledAttributes(attrs, LAYOUT_ATTRS);
|
||||||
@ -347,6 +305,11 @@ public class DoricSwipeLayout extends ViewGroup implements NestedScrollingParent
|
|||||||
a.recycle();
|
a.recycle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setPullDownHeight(int height) {
|
||||||
|
mPullDownHeight = height;
|
||||||
|
mOriginalOffsetTop = mCurrentTargetOffsetTop = -height;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected int getChildDrawingOrder(int childCount, int i) {
|
protected int getChildDrawingOrder(int childCount, int i) {
|
||||||
if (mCircleViewIndex < 0) {
|
if (mCircleViewIndex < 0) {
|
||||||
@ -364,12 +327,13 @@ public class DoricSwipeLayout extends ViewGroup implements NestedScrollingParent
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void createProgressView() {
|
private void createProgressView() {
|
||||||
mCircleView = new CircleImageView(getContext(), CIRCLE_BG_LIGHT);
|
mRefreshView = new DoricRefreshView(getContext());
|
||||||
mProgress = new CircularProgressDrawable(getContext());
|
ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, 0);
|
||||||
mProgress.setStyle(CircularProgressDrawable.DEFAULT);
|
addView(mRefreshView, layoutParams);
|
||||||
mCircleView.setImageDrawable(mProgress);
|
}
|
||||||
mCircleView.setVisibility(View.GONE);
|
|
||||||
addView(mCircleView);
|
public DoricRefreshView getRefreshView() {
|
||||||
|
return mRefreshView;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -405,8 +369,7 @@ public class DoricSwipeLayout extends ViewGroup implements NestedScrollingParent
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void startScaleUpAnimation(AnimationListener listener) {
|
private void startScaleUpAnimation(AnimationListener listener) {
|
||||||
mCircleView.setVisibility(View.VISIBLE);
|
mRefreshView.setVisibility(View.VISIBLE);
|
||||||
mProgress.setAlpha(MAX_ALPHA);
|
|
||||||
mScaleAnimation = new Animation() {
|
mScaleAnimation = new Animation() {
|
||||||
@Override
|
@Override
|
||||||
public void applyTransformation(float interpolatedTime, Transformation t) {
|
public void applyTransformation(float interpolatedTime, Transformation t) {
|
||||||
@ -415,10 +378,10 @@ public class DoricSwipeLayout extends ViewGroup implements NestedScrollingParent
|
|||||||
};
|
};
|
||||||
mScaleAnimation.setDuration(mMediumAnimationDuration);
|
mScaleAnimation.setDuration(mMediumAnimationDuration);
|
||||||
if (listener != null) {
|
if (listener != null) {
|
||||||
mCircleView.setAnimationListener(listener);
|
mRefreshView.setAnimationListener(listener);
|
||||||
}
|
}
|
||||||
mCircleView.clearAnimation();
|
mRefreshView.clearAnimation();
|
||||||
mCircleView.startAnimation(mScaleAnimation);
|
mRefreshView.startAnimation(mScaleAnimation);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -427,8 +390,7 @@ public class DoricSwipeLayout extends ViewGroup implements NestedScrollingParent
|
|||||||
* @param progress
|
* @param progress
|
||||||
*/
|
*/
|
||||||
void setAnimationProgress(float progress) {
|
void setAnimationProgress(float progress) {
|
||||||
mCircleView.setScaleX(progress);
|
mRefreshView.setProgressRotation(progress);
|
||||||
mCircleView.setScaleY(progress);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setRefreshing(boolean refreshing, final boolean notify) {
|
private void setRefreshing(boolean refreshing, final boolean notify) {
|
||||||
@ -452,95 +414,9 @@ public class DoricSwipeLayout extends ViewGroup implements NestedScrollingParent
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
mScaleDownAnimation.setDuration(SCALE_DOWN_DURATION);
|
mScaleDownAnimation.setDuration(SCALE_DOWN_DURATION);
|
||||||
mCircleView.setAnimationListener(listener);
|
mRefreshView.setAnimationListener(listener);
|
||||||
mCircleView.clearAnimation();
|
mRefreshView.clearAnimation();
|
||||||
mCircleView.startAnimation(mScaleDownAnimation);
|
mRefreshView.startAnimation(mScaleDownAnimation);
|
||||||
}
|
|
||||||
|
|
||||||
private void startProgressAlphaStartAnimation() {
|
|
||||||
mAlphaStartAnimation = startAlphaAnimation(mProgress.getAlpha(), STARTING_PROGRESS_ALPHA);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void startProgressAlphaMaxAnimation() {
|
|
||||||
mAlphaMaxAnimation = startAlphaAnimation(mProgress.getAlpha(), MAX_ALPHA);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Animation startAlphaAnimation(final int startingAlpha, final int endingAlpha) {
|
|
||||||
Animation alpha = new Animation() {
|
|
||||||
@Override
|
|
||||||
public void applyTransformation(float interpolatedTime, Transformation t) {
|
|
||||||
mProgress.setAlpha(
|
|
||||||
(int) (startingAlpha + ((endingAlpha - startingAlpha) * interpolatedTime)));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
alpha.setDuration(ALPHA_ANIMATION_DURATION);
|
|
||||||
// Clear out the previous animation listeners.
|
|
||||||
mCircleView.setAnimationListener(null);
|
|
||||||
mCircleView.clearAnimation();
|
|
||||||
mCircleView.startAnimation(alpha);
|
|
||||||
return alpha;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated Use {@link #setProgressBackgroundColorSchemeResource(int)}
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public void setProgressBackgroundColor(int colorRes) {
|
|
||||||
setProgressBackgroundColorSchemeResource(colorRes);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the background color of the progress spinner disc.
|
|
||||||
*
|
|
||||||
* @param colorRes Resource id of the color.
|
|
||||||
*/
|
|
||||||
public void setProgressBackgroundColorSchemeResource(@ColorRes int colorRes) {
|
|
||||||
setProgressBackgroundColorSchemeColor(ContextCompat.getColor(getContext(), colorRes));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the background color of the progress spinner disc.
|
|
||||||
*
|
|
||||||
* @param color
|
|
||||||
*/
|
|
||||||
public void setProgressBackgroundColorSchemeColor(@ColorInt int color) {
|
|
||||||
mCircleView.setBackgroundColor(color);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated Use {@link #setColorSchemeResources(int...)}
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public void setColorScheme(@ColorRes int... colors) {
|
|
||||||
setColorSchemeResources(colors);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the color resources used in the progress animation from color resources.
|
|
||||||
* The first color will also be the color of the bar that grows in response
|
|
||||||
* to a user swipe gesture.
|
|
||||||
*
|
|
||||||
* @param colorResIds
|
|
||||||
*/
|
|
||||||
public void setColorSchemeResources(@ColorRes int... colorResIds) {
|
|
||||||
final Context context = getContext();
|
|
||||||
int[] colorRes = new int[colorResIds.length];
|
|
||||||
for (int i = 0; i < colorResIds.length; i++) {
|
|
||||||
colorRes[i] = ContextCompat.getColor(context, colorResIds[i]);
|
|
||||||
}
|
|
||||||
setColorSchemeColors(colorRes);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the colors used in the progress animation. The first
|
|
||||||
* color will also be the color of the bar that grows in response to a user
|
|
||||||
* swipe gesture.
|
|
||||||
*
|
|
||||||
* @param colors
|
|
||||||
*/
|
|
||||||
public void setColorSchemeColors(@ColorInt int... colors) {
|
|
||||||
ensureTarget();
|
|
||||||
mProgress.setColorSchemeColors(colors);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -557,7 +433,7 @@ public class DoricSwipeLayout extends ViewGroup implements NestedScrollingParent
|
|||||||
if (mTarget == null) {
|
if (mTarget == null) {
|
||||||
for (int i = 0; i < getChildCount(); i++) {
|
for (int i = 0; i < getChildCount(); i++) {
|
||||||
View child = getChildAt(i);
|
View child = getChildAt(i);
|
||||||
if (!child.equals(mCircleView)) {
|
if (!child.equals(mRefreshView)) {
|
||||||
mTarget = child;
|
mTarget = child;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -588,15 +464,15 @@ public class DoricSwipeLayout extends ViewGroup implements NestedScrollingParent
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int circleWidth = mCircleView.getMeasuredWidth();
|
int circleWidth = mRefreshView.getMeasuredWidth();
|
||||||
int circleHeight = mCircleView.getMeasuredHeight();
|
int circleHeight = mRefreshView.getMeasuredHeight();
|
||||||
|
|
||||||
mCircleView.layout((width / 2 - circleWidth / 2), mCurrentTargetOffsetTop,
|
mRefreshView.layout((width / 2 - circleWidth / 2), mCurrentTargetOffsetTop,
|
||||||
(width / 2 + circleWidth / 2), mCurrentTargetOffsetTop + circleHeight);
|
(width / 2 + circleWidth / 2), mCurrentTargetOffsetTop + circleHeight);
|
||||||
|
|
||||||
final View child = mTarget;
|
final View child = mTarget;
|
||||||
final int childLeft = getPaddingLeft();
|
final int childLeft = getPaddingLeft();
|
||||||
final int childTop = getPaddingTop() + mCircleView.getBottom();
|
final int childTop = getPaddingTop() + mRefreshView.getBottom();
|
||||||
final int childWidth = width - getPaddingLeft() - getPaddingRight();
|
final int childWidth = width - getPaddingLeft() - getPaddingRight();
|
||||||
final int childHeight = height - getPaddingTop() - getPaddingBottom();
|
final int childHeight = height - getPaddingTop() - getPaddingBottom();
|
||||||
child.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);
|
child.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);
|
||||||
@ -615,28 +491,18 @@ public class DoricSwipeLayout extends ViewGroup implements NestedScrollingParent
|
|||||||
getMeasuredWidth() - getPaddingLeft() - getPaddingRight(),
|
getMeasuredWidth() - getPaddingLeft() - getPaddingRight(),
|
||||||
MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(
|
MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(
|
||||||
getMeasuredHeight() - getPaddingTop() - getPaddingBottom(), MeasureSpec.EXACTLY));
|
getMeasuredHeight() - getPaddingTop() - getPaddingBottom(), MeasureSpec.EXACTLY));
|
||||||
mCircleView.measure(MeasureSpec.makeMeasureSpec(mCircleDiameter, MeasureSpec.EXACTLY),
|
mRefreshView.measure(MeasureSpec.makeMeasureSpec(getMeasuredWidth() - getPaddingLeft() - getPaddingRight(), MeasureSpec.EXACTLY),
|
||||||
MeasureSpec.makeMeasureSpec(mCircleDiameter, MeasureSpec.EXACTLY));
|
MeasureSpec.makeMeasureSpec(mPullDownHeight, MeasureSpec.EXACTLY));
|
||||||
mCircleViewIndex = -1;
|
mCircleViewIndex = -1;
|
||||||
// Get the index of the circleview.
|
// Get the index of the circleview.
|
||||||
for (int index = 0; index < getChildCount(); index++) {
|
for (int index = 0; index < getChildCount(); index++) {
|
||||||
if (getChildAt(index) == mCircleView) {
|
if (getChildAt(index) == mRefreshView) {
|
||||||
mCircleViewIndex = index;
|
mCircleViewIndex = index;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the diameter of the progress circle that is displayed as part of the
|
|
||||||
* swipe to refresh layout.
|
|
||||||
*
|
|
||||||
* @return Diameter in pixels of the progress circle view.
|
|
||||||
*/
|
|
||||||
public int getProgressCircleDiameter() {
|
|
||||||
return mCircleDiameter;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Whether it is possible for the child view of this layout to
|
* @return Whether it is possible for the child view of this layout to
|
||||||
* scroll up. Override this if the child view is a custom view.
|
* scroll up. Override this if the child view is a custom view.
|
||||||
@ -680,7 +546,7 @@ public class DoricSwipeLayout extends ViewGroup implements NestedScrollingParent
|
|||||||
|
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case MotionEvent.ACTION_DOWN:
|
case MotionEvent.ACTION_DOWN:
|
||||||
setTargetOffsetTopAndBottom(mOriginalOffsetTop - mCircleView.getTop());
|
setTargetOffsetTopAndBottom(mOriginalOffsetTop - mRefreshView.getTop());
|
||||||
mActivePointerId = ev.getPointerId(0);
|
mActivePointerId = ev.getPointerId(0);
|
||||||
mIsBeingDragged = false;
|
mIsBeingDragged = false;
|
||||||
|
|
||||||
@ -773,7 +639,7 @@ public class DoricSwipeLayout extends ViewGroup implements NestedScrollingParent
|
|||||||
// the circle so it isn't exposed if its blocking content is moved
|
// the circle so it isn't exposed if its blocking content is moved
|
||||||
if (mUsingCustomStart && dy > 0 && mTotalUnconsumed == 0
|
if (mUsingCustomStart && dy > 0 && mTotalUnconsumed == 0
|
||||||
&& Math.abs(dy - consumed[1]) > 0) {
|
&& Math.abs(dy - consumed[1]) > 0) {
|
||||||
mCircleView.setVisibility(View.GONE);
|
mRefreshView.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now let our nested parent consume the leftovers
|
// Now let our nested parent consume the leftovers
|
||||||
@ -889,11 +755,9 @@ public class DoricSwipeLayout extends ViewGroup implements NestedScrollingParent
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void moveSpinner(float overscrollTop) {
|
private void moveSpinner(float overscrollTop) {
|
||||||
mProgress.setArrowEnabled(true);
|
|
||||||
float originalDragPercent = overscrollTop / mTotalDragDistance;
|
float originalDragPercent = overscrollTop / mTotalDragDistance;
|
||||||
|
|
||||||
float dragPercent = Math.min(1f, Math.abs(originalDragPercent));
|
float dragPercent = Math.min(1f, Math.abs(originalDragPercent));
|
||||||
float adjustedPercent = (float) Math.max(dragPercent - .4, 0) * 5 / 3;
|
|
||||||
float extraOS = Math.abs(overscrollTop) - mTotalDragDistance;
|
float extraOS = Math.abs(overscrollTop) - mTotalDragDistance;
|
||||||
float slingshotDist = mCustomSlingshotDistance > 0
|
float slingshotDist = mCustomSlingshotDistance > 0
|
||||||
? mCustomSlingshotDistance
|
? mCustomSlingshotDistance
|
||||||
@ -908,35 +772,17 @@ public class DoricSwipeLayout extends ViewGroup implements NestedScrollingParent
|
|||||||
|
|
||||||
int targetY = mOriginalOffsetTop + (int) ((slingshotDist * dragPercent) + extraMove);
|
int targetY = mOriginalOffsetTop + (int) ((slingshotDist * dragPercent) + extraMove);
|
||||||
// where 1.0f is a full circle
|
// where 1.0f is a full circle
|
||||||
if (mCircleView.getVisibility() != View.VISIBLE) {
|
if (mRefreshView.getVisibility() != View.VISIBLE) {
|
||||||
mCircleView.setVisibility(View.VISIBLE);
|
mRefreshView.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
if (!mScale) {
|
if (!mScale) {
|
||||||
mCircleView.setScaleX(1f);
|
mRefreshView.setScaleX(1f);
|
||||||
mCircleView.setScaleY(1f);
|
mRefreshView.setScaleY(1f);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mScale) {
|
if (mScale) {
|
||||||
setAnimationProgress(Math.min(1f, overscrollTop / mTotalDragDistance));
|
setAnimationProgress(Math.min(1f, overscrollTop / mTotalDragDistance));
|
||||||
}
|
}
|
||||||
if (overscrollTop < mTotalDragDistance) {
|
|
||||||
if (mProgress.getAlpha() > STARTING_PROGRESS_ALPHA
|
|
||||||
&& !isAnimationRunning(mAlphaStartAnimation)) {
|
|
||||||
// Animate the alpha
|
|
||||||
startProgressAlphaStartAnimation();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (mProgress.getAlpha() < MAX_ALPHA && !isAnimationRunning(mAlphaMaxAnimation)) {
|
|
||||||
// Animate the alpha
|
|
||||||
startProgressAlphaMaxAnimation();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
float strokeStart = adjustedPercent * .8f;
|
|
||||||
mProgress.setStartEndTrim(0f, Math.min(MAX_PROGRESS_ANGLE, strokeStart));
|
|
||||||
mProgress.setArrowScale(Math.min(1f, adjustedPercent));
|
|
||||||
|
|
||||||
float rotation = (-0.25f + .4f * adjustedPercent + tensionPercent * 2) * .5f;
|
|
||||||
mProgress.setProgressRotation(rotation);
|
|
||||||
setTargetOffsetTopAndBottom(targetY - mCurrentTargetOffsetTop);
|
setTargetOffsetTopAndBottom(targetY - mCurrentTargetOffsetTop);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -946,7 +792,6 @@ public class DoricSwipeLayout extends ViewGroup implements NestedScrollingParent
|
|||||||
} else {
|
} else {
|
||||||
// cancel refresh
|
// cancel refresh
|
||||||
mRefreshing = false;
|
mRefreshing = false;
|
||||||
mProgress.setStartEndTrim(0f, 0f);
|
|
||||||
Animation.AnimationListener listener = null;
|
Animation.AnimationListener listener = null;
|
||||||
if (!mScale) {
|
if (!mScale) {
|
||||||
listener = new Animation.AnimationListener() {
|
listener = new Animation.AnimationListener() {
|
||||||
@ -969,7 +814,6 @@ public class DoricSwipeLayout extends ViewGroup implements NestedScrollingParent
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
animateOffsetToStartPosition(mCurrentTargetOffsetTop, listener);
|
animateOffsetToStartPosition(mCurrentTargetOffsetTop, listener);
|
||||||
mProgress.setArrowEnabled(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1057,7 +901,6 @@ public class DoricSwipeLayout extends ViewGroup implements NestedScrollingParent
|
|||||||
if (yDiff > mTouchSlop && !mIsBeingDragged) {
|
if (yDiff > mTouchSlop && !mIsBeingDragged) {
|
||||||
mInitialMotionY = mInitialDownY + mTouchSlop;
|
mInitialMotionY = mInitialDownY + mTouchSlop;
|
||||||
mIsBeingDragged = true;
|
mIsBeingDragged = true;
|
||||||
mProgress.setAlpha(STARTING_PROGRESS_ALPHA);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1067,10 +910,10 @@ public class DoricSwipeLayout extends ViewGroup implements NestedScrollingParent
|
|||||||
mAnimateToCorrectPosition.setDuration(ANIMATE_TO_TRIGGER_DURATION);
|
mAnimateToCorrectPosition.setDuration(ANIMATE_TO_TRIGGER_DURATION);
|
||||||
mAnimateToCorrectPosition.setInterpolator(mDecelerateInterpolator);
|
mAnimateToCorrectPosition.setInterpolator(mDecelerateInterpolator);
|
||||||
if (listener != null) {
|
if (listener != null) {
|
||||||
mCircleView.setAnimationListener(listener);
|
mRefreshView.setAnimationListener(listener);
|
||||||
}
|
}
|
||||||
mCircleView.clearAnimation();
|
mRefreshView.clearAnimation();
|
||||||
mCircleView.startAnimation(mAnimateToCorrectPosition);
|
mRefreshView.startAnimation(mAnimateToCorrectPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void animateOffsetToStartPosition(int from, AnimationListener listener) {
|
private void animateOffsetToStartPosition(int from, AnimationListener listener) {
|
||||||
@ -1083,10 +926,10 @@ public class DoricSwipeLayout extends ViewGroup implements NestedScrollingParent
|
|||||||
mAnimateToStartPosition.setDuration(ANIMATE_TO_START_DURATION);
|
mAnimateToStartPosition.setDuration(ANIMATE_TO_START_DURATION);
|
||||||
mAnimateToStartPosition.setInterpolator(mDecelerateInterpolator);
|
mAnimateToStartPosition.setInterpolator(mDecelerateInterpolator);
|
||||||
if (listener != null) {
|
if (listener != null) {
|
||||||
mCircleView.setAnimationListener(listener);
|
mRefreshView.setAnimationListener(listener);
|
||||||
}
|
}
|
||||||
mCircleView.clearAnimation();
|
mRefreshView.clearAnimation();
|
||||||
mCircleView.startAnimation(mAnimateToStartPosition);
|
mRefreshView.startAnimation(mAnimateToStartPosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1101,16 +944,15 @@ public class DoricSwipeLayout extends ViewGroup implements NestedScrollingParent
|
|||||||
endTarget = mSpinnerOffsetEnd;
|
endTarget = mSpinnerOffsetEnd;
|
||||||
}
|
}
|
||||||
targetTop = (mFrom + (int) ((endTarget - mFrom) * interpolatedTime));
|
targetTop = (mFrom + (int) ((endTarget - mFrom) * interpolatedTime));
|
||||||
int offset = targetTop - mCircleView.getTop();
|
int offset = targetTop - mRefreshView.getTop();
|
||||||
setTargetOffsetTopAndBottom(offset);
|
setTargetOffsetTopAndBottom(offset);
|
||||||
mProgress.setArrowScale(1 - interpolatedTime);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void moveToStart(float interpolatedTime) {
|
void moveToStart(float interpolatedTime) {
|
||||||
int targetTop = 0;
|
int targetTop = 0;
|
||||||
targetTop = (mFrom + (int) ((mOriginalOffsetTop - mFrom) * interpolatedTime));
|
targetTop = (mFrom + (int) ((mOriginalOffsetTop - mFrom) * interpolatedTime));
|
||||||
int offset = targetTop - mCircleView.getTop();
|
int offset = targetTop - mRefreshView.getTop();
|
||||||
setTargetOffsetTopAndBottom(offset);
|
setTargetOffsetTopAndBottom(offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1124,7 +966,7 @@ public class DoricSwipeLayout extends ViewGroup implements NestedScrollingParent
|
|||||||
private void startScaleDownReturnToStartAnimation(int from,
|
private void startScaleDownReturnToStartAnimation(int from,
|
||||||
Animation.AnimationListener listener) {
|
Animation.AnimationListener listener) {
|
||||||
mFrom = from;
|
mFrom = from;
|
||||||
mStartingScale = mCircleView.getScaleX();
|
mStartingScale = mRefreshView.getScaleX();
|
||||||
mScaleDownToStartAnimation = new Animation() {
|
mScaleDownToStartAnimation = new Animation() {
|
||||||
@Override
|
@Override
|
||||||
public void applyTransformation(float interpolatedTime, Transformation t) {
|
public void applyTransformation(float interpolatedTime, Transformation t) {
|
||||||
@ -1135,16 +977,16 @@ public class DoricSwipeLayout extends ViewGroup implements NestedScrollingParent
|
|||||||
};
|
};
|
||||||
mScaleDownToStartAnimation.setDuration(SCALE_DOWN_DURATION);
|
mScaleDownToStartAnimation.setDuration(SCALE_DOWN_DURATION);
|
||||||
if (listener != null) {
|
if (listener != null) {
|
||||||
mCircleView.setAnimationListener(listener);
|
mRefreshView.setAnimationListener(listener);
|
||||||
}
|
}
|
||||||
mCircleView.clearAnimation();
|
mRefreshView.clearAnimation();
|
||||||
mCircleView.startAnimation(mScaleDownToStartAnimation);
|
mRefreshView.startAnimation(mScaleDownToStartAnimation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setTargetOffsetTopAndBottom(int offset) {
|
void setTargetOffsetTopAndBottom(int offset) {
|
||||||
mCircleView.bringToFront();
|
mRefreshView.bringToFront();
|
||||||
ViewCompat.offsetTopAndBottom(mCircleView, offset);
|
ViewCompat.offsetTopAndBottom(mRefreshView, offset);
|
||||||
mCurrentTargetOffsetTop = mCircleView.getTop();
|
mCurrentTargetOffsetTop = mRefreshView.getTop();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onSecondaryPointerUp(MotionEvent ev) {
|
private void onSecondaryPointerUp(MotionEvent ev) {
|
||||||
|
Reference in New Issue
Block a user