Skip to content

Commit

Permalink
optimize
Browse files Browse the repository at this point in the history
  • Loading branch information
1993hzw committed Mar 5, 2019
1 parent 5bda58d commit e284c66
Show file tree
Hide file tree
Showing 11 changed files with 197 additions and 210 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public void onOffsetChanged(View child, int offset) {
});

HorizontalRecyclerViewFragment.initHorizontal(view.findViewById(R.id.horizontal_view));

// VerticalRecyclerViewFragment.initVerticalOverScroll(view.findViewById(R.id.vertical_view));
return view;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;

import cn.forward.overscroll.IOffsetChangeListener;
import cn.forward.overscroll.IOverScrollView;
Expand All @@ -23,10 +24,12 @@ public class VerticalRecyclerViewFragment extends Fragment {
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {


View view = inflater.inflate(R.layout.layout_recyclerview_vertical, container, false);
initVerticalOverScroll(view);
return view;
}

public static void initVerticalOverScroll(View view) {
final View iconHeaderView = view.findViewById(R.id.icon_header);
final View iconFooterView = view.findViewById(R.id.icon_footer);

Expand Down Expand Up @@ -62,7 +65,7 @@ public void onOffsetChanged(View child, int offset) {


RecyclerView recyclerView = view.findViewById(R.id.overscroll_view);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false));
recyclerView.setLayoutManager(new LinearLayoutManager(recyclerView.getContext(), LinearLayoutManager.VERTICAL, false));
recyclerView.setAdapter(new RecyclerView.Adapter() {
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Expand All @@ -73,12 +76,19 @@ public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType
}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
TextView textView = holder.itemView.findViewById(R.id.text);
textView.setText("" + (1+position));
textView.setText("" + (1 + position));

View container = holder.itemView.findViewById(R.id.container);
container.setBackgroundColor(COLORS[position % COLORS.length]);

container.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(holder.itemView.getContext(), "" + (position + 1), Toast.LENGTH_SHORT).show();
}
});
}

@Override
Expand All @@ -87,6 +97,5 @@ public int getItemCount() {
}
});

return view;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import android.support.v4.math.MathUtils;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
Expand All @@ -17,7 +18,7 @@
*
* @author ziwei huang
*/
public abstract class BaseOverScrollBehavior extends CoordinatorLayout.Behavior<View> {
public abstract class BaseOverScrollBehavior extends CoordinatorLayout.Behavior<View> implements IOverScroll {

private static final int MAX_BOUNCE_BACK_DURATION_MS = 300;
private static final int MIN_BOUNCE_BACK_DURATION_MS = 150;
Expand All @@ -43,8 +44,12 @@ public abstract boolean onStartNestedScroll(CoordinatorLayout parent, View child

@Override
public void onNestedScrollAccepted(@NonNull CoordinatorLayout coordinatorLayout, @NonNull View child, @NonNull View directTargetChild, @NonNull View target, int axes, int type) {
if (child != target) {
return;
}

if (type == ViewCompat.TYPE_TOUCH) {
stopSpringBack();
stopSpringBack(child);
}

if (type == ViewCompat.TYPE_TOUCH) {
Expand All @@ -71,19 +76,23 @@ public abstract void onNestedPreScroll(CoordinatorLayout coordinatorLayout, View
*/
protected int onNestedPreScrollInner(CoordinatorLayout coordinatorLayout, View child,
View target, int distance, int type) {
if (child != target) {
return 0;
}

IOverScrollCallback overscrollListener = (IOverScrollCallback) child;

if (distance != 0) {
int min, max;
if (distance < 0) { // We're scrolling to end
if (!overscrollListener.canScroll(child, getOffset(child), mDirectionToEnd)) {
if (!overscrollListener.canScroll(this, child, mDirectionToEnd)) {
return 0;
}

min = getOffset(child);
max = 0;
} else { // We're scrolling to start
if (!overscrollListener.canScroll(child, getOffset(child), mDirectionToStart)) {
if (!overscrollListener.canScroll(this, child, mDirectionToStart)) {
return 0;
}

Expand All @@ -106,48 +115,53 @@ public abstract void onNestedScroll(CoordinatorLayout coordinatorLayout, View ch
protected void onNestedScrollInner(CoordinatorLayout coordinatorLayout, View child,
View target, int distanceConsumed, int distanceUnconsumed,
int type) {
if (child != target) {
return;
}

IOverScrollCallback overscrollListener = (IOverScrollCallback) child;

if (distanceUnconsumed != 0) {
if (distanceUnconsumed != 0) { // fix nested scroll bugs
coordinatorLayout.requestDisallowInterceptTouchEvent(true);
}

if (distanceUnconsumed < 0) {
// If the scrolling view is scrolling to end but not consuming, it's probably be at
// the top of it's content

if (!overscrollListener.canScroll(child, getOffset(child), mDirectionToEnd)) {
if (!overscrollListener.canScroll(this, child, mDirectionToEnd)) {
return;
}

if (type == ViewCompat.TYPE_TOUCH) {
scroll(child, distanceUnconsumed, 0, getMaxOffset(child));
} else { // fling
if ((mOverScroller.computeScrollOffset()
&& Math.abs(mOverScroller.getCurrVelocity()) < Math.abs(overscrollListener.getMinFlingVelocity(child, getOffset(child), mDirectionToEnd))) // too slow
|| getOffset(child) >= overscrollListener.getMaxFlingOffset(child, getOffset(child), mDirectionToEnd)) { // reach edge
if ((mOverScroller != null && mOverScroller.computeScrollOffset()
&& Math.abs(mOverScroller.getCurrVelocity()) < Math.abs(overscrollListener.getMinFlingVelocity(this, child, mDirectionToEnd))) // too slow
||
getOffset(child) >= overscrollListener.getMaxFlingOffset(this, child, mDirectionToEnd)) { // reach edge
ViewCompat.stopNestedScroll(target, ViewCompat.TYPE_NON_TOUCH);
} else {
scroll(child, distanceUnconsumed, // slow down
getOffset(child), overscrollListener.getMaxFlingOffset(child, getOffset(child), mDirectionToEnd));
scroll(child, distanceUnconsumed,
getOffset(child), overscrollListener.getMaxFlingOffset(this, child, mDirectionToEnd));
}
}

} else if (distanceUnconsumed > 0) {
if (!overscrollListener.canScroll(child, getOffset(child), mDirectionToStart)) {
if (!overscrollListener.canScroll(this, child, mDirectionToStart)) {
return;
}

if (type == ViewCompat.TYPE_TOUCH) {
scroll(child, distanceUnconsumed, getMinOffset(child), 0);
} else { // fling
if ((mOverScroller.computeScrollOffset()
&& Math.abs(mOverScroller.getCurrVelocity()) < overscrollListener.getMinFlingVelocity(child, getOffset(child), mDirectionToStart)) // too slow
|| getOffset(child) <= overscrollListener.getMaxFlingOffset(child, getOffset(child), mDirectionToStart)) { // reach edge
if ((mOverScroller != null && mOverScroller.computeScrollOffset()
&& Math.abs(mOverScroller.getCurrVelocity()) < overscrollListener.getMinFlingVelocity(this, child, mDirectionToStart)) // too slow
|| getOffset(child) <= overscrollListener.getMaxFlingOffset(this, child, mDirectionToStart)) { // reach edge
ViewCompat.stopNestedScroll(target, ViewCompat.TYPE_NON_TOUCH);
} else {
scroll(child, distanceUnconsumed, // slow down
overscrollListener.getMaxFlingOffset(child, getOffset(child), mDirectionToStart), getOffset(child));
overscrollListener.getMaxFlingOffset(this, child, mDirectionToStart), getOffset(child));
}
}
}
Expand All @@ -157,29 +171,44 @@ protected void onNestedScrollInner(CoordinatorLayout coordinatorLayout, View chi
public abstract boolean onNestedPreFling(CoordinatorLayout coordinatorLayout, View child, View target, float velocityX, float velocityY);

protected boolean onNestedPreFlingInner(CoordinatorLayout coordinatorLayout, View child, View target, float velocity) {
if (child == target) {
if (mOverScroller == null) {
mOverScroller = new OverScroller(coordinatorLayout.getContext());
}
/* velocityX = 0, velocityY = velocity
or
velocityX = velocity, velocityY = 0
*/
mOverScroller.fling(0, 0, 0, (int) velocity, 0, 0, Integer.MIN_VALUE, Integer.MAX_VALUE);
if (child != target) {
return false;
}

if (getOffset(child) != 0) { // 越界后不能产生惯性滑动,否则造成越界过程中child内部同时也发生滑动
// No fling can occur after crossing the boundary, otherwise the fling of the child will also occur during the crossing process.
ViewCompat.stopNestedScroll(target, ViewCompat.TYPE_NON_TOUCH);
return true; // must true
}

if (mOverScroller == null) {
mOverScroller = new OverScroller(coordinatorLayout.getContext());
}
/* velocityX = 0, velocityY = velocity
or
velocityX = velocity, velocityY = 0
*/
mOverScroller.fling(0, 0, 0, (int) velocity, 0, 0, Integer.MIN_VALUE, Integer.MAX_VALUE);

return false;
}

@Override
public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, View child,
View target, int type) {
if (child != target) {
return;
}

if (type == ViewCompat.TYPE_TOUCH) { // touching
if (getOffset(child) != 0) { // and out of bound
ViewCompat.stopNestedScroll(target, ViewCompat.TYPE_NON_TOUCH);
ViewCompat.stopNestedScroll(child, ViewCompat.TYPE_NON_TOUCH);
springBack(child);
}
} else {
springBack(child);
if (getOffset(child) != 0) {
springBack(child);
}
}
}

Expand All @@ -189,7 +218,7 @@ public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, View child,
private final int computerWithDampingFactor(View child, int distance) {
IOverScrollCallback overscroll = (IOverScrollCallback) child;
int direction = distance > 0 ? mDirectionToStart : mDirectionToEnd;
float factor = overscroll.getDampingFactor(child, getOffset(child), direction);
float factor = overscroll.getDampingFactor(this, child, direction);
if (factor == 0) {
factor = 1;
}
Expand Down Expand Up @@ -227,16 +256,20 @@ private int computerOffset(View child, int newOffset, int minOffset, int maxOffs
return consumed;
}

public void stopSpringBack() {
if (mSpringBackAnimator == null) {
return;
@Override
public void stopSpringBack(View child) {
if (mSpringBackAnimator != null) {
if (mSpringBackAnimator.isRunning()) {
mSpringBackAnimator.cancel();
}
}

if (mSpringBackAnimator.isRunning()) {
mSpringBackAnimator.cancel();
}
IOverScrollCallback overScrollCallback = (IOverScrollCallback) child;
overScrollCallback.onStopSpringingBack(this, child);

}

@Override
public void springBack(final View child) {
IOverScrollCallback overScroll = (IOverScrollCallback) child;

Expand All @@ -245,6 +278,10 @@ public void springBack(final View child) {
return;
}

if (overScroll.onSpringBack(this, child)) {
return;
}

if (mSpringBackAnimator == null) {
mSpringBackAnimator = ValueAnimator.ofInt();
}
Expand All @@ -257,7 +294,6 @@ public void springBack(final View child) {
float bounceBackDuration = (Math.abs(startOffset) * 1f / getMaxOffset(child)) * MAX_BOUNCE_BACK_DURATION_MS;
mSpringBackAnimator.setDuration(Math.max((int) bounceBackDuration, MIN_BOUNCE_BACK_DURATION_MS));
mSpringBackAnimator.setInterpolator(mSpringBackInterpolator);
overScroll.onSpringBack(child, startOffset, mSpringBackAnimator);
mSpringBackAnimator.setIntValues(startOffset, 0);
mSpringBackAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
Expand All @@ -269,18 +305,12 @@ public void onAnimationUpdate(ValueAnimator animation) {
mSpringBackAnimator.start();
}

@Override
public void setOffset(View child, int offset) {
IOverScrollCallback overscrollListener = (IOverScrollCallback) child;
updateOffset(child, offset);
overscrollListener.onOffsetChanged(child, getOffset(child));
overscrollListener.onOffsetChanged(this, child, getOffset(child));
}

protected abstract void updateOffset(View child, int offset);

public abstract int getOffset(View child);

public abstract int getMaxOffset(View child);

public abstract int getMinOffset(View child);

}
21 changes: 21 additions & 0 deletions overscroll/src/main/java/cn/forward/overscroll/IOverScroll.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package cn.forward.overscroll;

import android.view.View;

/**
* @author ziwei huang
*/
public interface IOverScroll {

public void setOffset(View child, int offset);

public int getOffset(View child);

public int getMaxOffset(View child);

public int getMinOffset(View child);

public void stopSpringBack(View child);

public void springBack(View child);
}
Loading

0 comments on commit e284c66

Please sign in to comment.