mirror of
https://github.com/Tencent/QMUI_Android.git
synced 2026-10-29 03:26:44 +08:00
1.padding support; 2.scroll info save and restore
This commit is contained in:
+1
-8
@@ -16,7 +16,7 @@
|
||||
|
||||
package com.qmuiteam.qmui.nestedScroll;
|
||||
|
||||
public interface IQMUIContinuousNestedBottomView {
|
||||
public interface IQMUIContinuousNestedBottomView extends IQMUIContinuousNestedScrollCommon {
|
||||
int HEIGHT_IS_ENOUGH_TO_SCROLL = -1;
|
||||
/**
|
||||
* consume scroll
|
||||
@@ -34,11 +34,4 @@ public interface IQMUIContinuousNestedBottomView {
|
||||
int getCurrentScroll();
|
||||
|
||||
int getScrollOffsetRange();
|
||||
|
||||
void injectScrollNotifier(OnScrollNotifier notifier);
|
||||
|
||||
interface OnScrollNotifier {
|
||||
void notify(int innerOffset, int innerRange);
|
||||
}
|
||||
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making QMUI_Android available.
|
||||
*
|
||||
* Copyright (C) 2017-2018 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
*
|
||||
* Licensed under the MIT License (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://opensource.org/licenses/MIT
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is
|
||||
* distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.qmuiteam.qmui.nestedScroll;
|
||||
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
public interface IQMUIContinuousNestedScrollCommon {
|
||||
|
||||
@Nullable
|
||||
Object saveScrollInfo();
|
||||
|
||||
void restoreScrollInfo(@Nullable Object scrollInfo);
|
||||
|
||||
void injectScrollNotifier(OnScrollNotifier notifier);
|
||||
|
||||
interface OnScrollNotifier {
|
||||
void notify(int innerOffset, int innerRange);
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
package com.qmuiteam.qmui.nestedScroll;
|
||||
|
||||
public interface IQMUIContinuousNestedTopView {
|
||||
public interface IQMUIContinuousNestedTopView extends IQMUIContinuousNestedScrollCommon {
|
||||
/**
|
||||
* consume scroll
|
||||
*
|
||||
@@ -28,10 +28,4 @@ public interface IQMUIContinuousNestedTopView {
|
||||
int getCurrentScroll();
|
||||
|
||||
int getScrollOffsetRange();
|
||||
|
||||
void injectScrollNotifier(OnScrollNotifier notifier);
|
||||
|
||||
interface OnScrollNotifier {
|
||||
void notify(int innerOffset, int innerRange);
|
||||
}
|
||||
}
|
||||
+11
-5
@@ -17,22 +17,26 @@
|
||||
package com.qmuiteam.qmui.nestedScroll;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.util.Log;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.design.widget.CoordinatorLayout;
|
||||
import android.support.v4.view.GravityCompat;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
||||
import androidx.core.view.GravityCompat;
|
||||
|
||||
public class QMUIContinuousNestedBottomAreaBehavior extends QMUIViewOffsetBehavior<View> {
|
||||
|
||||
private final Rect tempRect1 = new Rect();
|
||||
private final Rect tempRect2 = new Rect();
|
||||
|
||||
private int mTopInset = 0;
|
||||
|
||||
public void setTopInset(int topInset) {
|
||||
mTopInset = topInset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMeasureChild(@NonNull CoordinatorLayout parent, @NonNull View child, int parentWidthMeasureSpec, int widthUsed, int parentHeightMeasureSpec, int heightUsed) {
|
||||
final int childLpHeight = child.getLayoutParams().height;
|
||||
@@ -44,6 +48,8 @@ public class QMUIContinuousNestedBottomAreaBehavior extends QMUIViewOffsetBehavi
|
||||
availableHeight = parent.getHeight();
|
||||
}
|
||||
|
||||
availableHeight -= mTopInset;
|
||||
|
||||
final int heightMeasureSpec =
|
||||
View.MeasureSpec.makeMeasureSpec(
|
||||
availableHeight,
|
||||
|
||||
+26
-1
@@ -225,6 +225,32 @@ public abstract class QMUIContinuousNestedBottomDelegateLayout extends QMUIFrame
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreScrollInfo(Object scrollInfo) {
|
||||
if (scrollInfo instanceof ScrollInfo) {
|
||||
ScrollInfo si = (ScrollInfo) scrollInfo;
|
||||
mHeaderViewOffsetHelper.setTopAndBottomOffset(si.topBottomOffset);
|
||||
mContentViewOffsetHelper.setTopAndBottomOffset(si.topBottomOffset);
|
||||
((IQMUIContinuousNestedBottomView) mContentView).restoreScrollInfo(si.delegateScrollInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object saveScrollInfo() {
|
||||
return new ScrollInfo(mHeaderViewOffsetHelper.getTopAndBottomOffset(),
|
||||
((IQMUIContinuousNestedBottomView) mContentView).saveScrollInfo());
|
||||
}
|
||||
|
||||
public static class ScrollInfo {
|
||||
int topBottomOffset;
|
||||
Object delegateScrollInfo;
|
||||
|
||||
public ScrollInfo(int topBottomOffset, Object delegateScrollInfo) {
|
||||
this.topBottomOffset = topBottomOffset;
|
||||
this.delegateScrollInfo = delegateScrollInfo;
|
||||
}
|
||||
}
|
||||
|
||||
// NestedScrollingChild2
|
||||
|
||||
@Override
|
||||
@@ -641,6 +667,5 @@ public abstract class QMUIContinuousNestedBottomDelegateLayout extends QMUIFrame
|
||||
removeCallbacks(this);
|
||||
mOverScroller.abortAnimation();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+40
@@ -20,8 +20,10 @@ import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.view.ViewCompat;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
|
||||
|
||||
public class QMUIContinuousNestedBottomRecyclerView extends RecyclerView
|
||||
@@ -123,4 +125,42 @@ public class QMUIContinuousNestedBottomRecyclerView extends RecyclerView
|
||||
public int getScrollOffsetRange() {
|
||||
return Math.max(0, computeVerticalScrollRange() - getHeight());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object saveScrollInfo() {
|
||||
LayoutManager layoutManager = getLayoutManager();
|
||||
if (layoutManager instanceof LinearLayoutManager) {
|
||||
LinearLayoutManager lm = (LinearLayoutManager) layoutManager;
|
||||
if (lm.getOrientation() == LinearLayoutManager.HORIZONTAL) {
|
||||
return null;
|
||||
}
|
||||
int pos = lm.findFirstVisibleItemPosition();
|
||||
View firstView = lm.findViewByPosition(pos);
|
||||
int offset = firstView == null ? 0 : firstView.getTop();
|
||||
return new ScrollInfo(pos, offset);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreScrollInfo(Object scrollInfo) {
|
||||
if (!(scrollInfo instanceof ScrollInfo)) {
|
||||
return;
|
||||
}
|
||||
ScrollInfo sc = (ScrollInfo) scrollInfo;
|
||||
LayoutManager layoutManager = getLayoutManager();
|
||||
if (layoutManager instanceof LinearLayoutManager) {
|
||||
((LinearLayoutManager) layoutManager).scrollToPositionWithOffset(sc.scrollPosition, sc.scrollOffset);
|
||||
}
|
||||
}
|
||||
|
||||
public static class ScrollInfo {
|
||||
int scrollPosition;
|
||||
int scrollOffset;
|
||||
|
||||
public ScrollInfo(int scrollPosition, int scrollOffset) {
|
||||
this.scrollPosition = scrollPosition;
|
||||
this.scrollOffset = scrollOffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+89
-14
@@ -106,6 +106,14 @@ public class QMUIContinuousNestedScrollLayout extends CoordinatorLayout implemen
|
||||
return mBottomView;
|
||||
}
|
||||
|
||||
public QMUIContinuousNestedTopAreaBehavior getTopAreaBehavior() {
|
||||
return mTopAreaBehavior;
|
||||
}
|
||||
|
||||
public QMUIContinuousNestedBottomAreaBehavior getBottomAreaBehavior() {
|
||||
return mBottomAreaBehavior;
|
||||
}
|
||||
|
||||
public void setBottomAreaView(View bottomView, @Nullable LayoutParams layoutParams) {
|
||||
if (!(bottomView instanceof IQMUIContinuousNestedBottomView)) {
|
||||
throw new IllegalStateException("bottomView must implement from IQMUIContinuousNestedBottomView");
|
||||
@@ -117,7 +125,7 @@ public class QMUIContinuousNestedScrollLayout extends CoordinatorLayout implemen
|
||||
mBottomView.injectScrollNotifier(new IQMUIContinuousNestedBottomView.OnScrollNotifier() {
|
||||
@Override
|
||||
public void notify(int innerOffset, int innerRange) {
|
||||
dispatchBottomScroll(-mBottomAreaBehavior.getTopAndBottomOffset(), ((View) mBottomView).getHeight(),
|
||||
dispatchBottomScroll(-mBottomAreaBehavior.getTopAndBottomOffset(), getOffsetRange(),
|
||||
innerOffset, innerRange);
|
||||
}
|
||||
});
|
||||
@@ -150,21 +158,23 @@ public class QMUIContinuousNestedScrollLayout extends CoordinatorLayout implemen
|
||||
int contentHeight = mBottomView.getContentHeight();
|
||||
if (contentHeight != IQMUIContinuousNestedBottomView.HEIGHT_IS_ENOUGH_TO_SCROLL) {
|
||||
// bottomView can not scroll
|
||||
mTopAreaBehavior.setTopAndBottomOffset(getHeight() - contentHeight - ((View) mTopView).getHeight());
|
||||
mTopAreaBehavior.setTopAndBottomOffset(
|
||||
getHeight() - contentHeight - ((View) mTopView).getHeight());
|
||||
return;
|
||||
}
|
||||
mTopAreaBehavior.setTopAndBottomOffset(-((View) mTopView).getHeight());
|
||||
mTopAreaBehavior.setTopAndBottomOffset(
|
||||
-((View) mTopView).getHeight() + getHeight() - ((View) mBottomView).getHeight());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void scrollBy(int dy){
|
||||
if(dy > 0){
|
||||
if(mTopAreaBehavior != null){
|
||||
mTopAreaBehavior.scroll(this, ((View)mTopView), dy);
|
||||
public void scrollBy(int dy) {
|
||||
if (dy > 0) {
|
||||
if (mTopAreaBehavior != null) {
|
||||
mTopAreaBehavior.scroll(this, ((View) mTopView), dy);
|
||||
}
|
||||
}else if(dy < 0){
|
||||
if(mBottomView != null){
|
||||
} else if (dy < 0) {
|
||||
if (mBottomView != null) {
|
||||
mBottomView.consumeScroll(dy);
|
||||
}
|
||||
}
|
||||
@@ -189,10 +199,17 @@ public class QMUIContinuousNestedScrollLayout extends CoordinatorLayout implemen
|
||||
int contentHeight = mBottomView.getContentHeight();
|
||||
if (contentHeight != IQMUIContinuousNestedBottomView.HEIGHT_IS_ENOUGH_TO_SCROLL) {
|
||||
// bottomView can not scroll
|
||||
mTopAreaBehavior.setTopAndBottomOffset(getHeight() - contentHeight - ((View) mTopView).getHeight());
|
||||
View topView = (View) mTopView;
|
||||
if (topView.getHeight() + contentHeight < getHeight()) {
|
||||
mTopAreaBehavior.setTopAndBottomOffset(0);
|
||||
} else {
|
||||
mTopAreaBehavior.setTopAndBottomOffset(
|
||||
getHeight() - contentHeight - ((View) mTopView).getHeight());
|
||||
}
|
||||
return;
|
||||
}
|
||||
mTopAreaBehavior.setTopAndBottomOffset(-((View) mTopView).getHeight());
|
||||
mTopAreaBehavior.setTopAndBottomOffset(
|
||||
-((View) mTopView).getHeight() + getHeight() - ((View) mBottomView).getHeight());
|
||||
}
|
||||
}
|
||||
if (mBottomView != null) {
|
||||
@@ -200,22 +217,80 @@ public class QMUIContinuousNestedScrollLayout extends CoordinatorLayout implemen
|
||||
}
|
||||
}
|
||||
|
||||
private int getOffsetRange() {
|
||||
if (mTopView == null || mBottomView == null) {
|
||||
return 0;
|
||||
}
|
||||
int contentHeight = mBottomView.getContentHeight();
|
||||
if (contentHeight != IQMUIContinuousNestedBottomView.HEIGHT_IS_ENOUGH_TO_SCROLL) {
|
||||
return ((View) mTopView).getHeight() - (getHeight() - contentHeight);
|
||||
}
|
||||
return ((View) mTopView).getHeight() - (getHeight() - ((View) mBottomView).getHeight());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notify(int innerOffset, int innerRange) {
|
||||
dispatchTopScroll(-mTopAreaBehavior.getTopAndBottomOffset(), ((View) mTopView).getHeight(),
|
||||
dispatchTopScroll(-mTopAreaBehavior.getTopAndBottomOffset(), getOffsetRange(),
|
||||
innerOffset, innerRange);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTopAreaOffset(int offset) {
|
||||
dispatchTopScroll(-offset, ((View) mTopView).getHeight(),
|
||||
dispatchTopScroll(-offset, getOffsetRange(),
|
||||
mTopView.getCurrentScroll(), mTopView.getScrollOffsetRange());
|
||||
dispatchBottomScroll(-offset, ((View)mBottomView).getHeight(),
|
||||
dispatchBottomScroll(-offset, getOffsetRange(),
|
||||
mBottomView.getCurrentScroll(), mBottomView.getScrollOffsetRange());
|
||||
}
|
||||
|
||||
public ScrollInfo saveScrollInfo() {
|
||||
Object topInfo = mTopView != null ? mTopView.saveScrollInfo() : null;
|
||||
Object bottomInfo = mBottomView != null ? mBottomView.saveScrollInfo() : null;
|
||||
return new ScrollInfo(topInfo, bottomInfo, mTopAreaBehavior.getTopAndBottomOffset());
|
||||
}
|
||||
|
||||
public void restoreScrollInfo(@Nullable ScrollInfo scrollInfo) {
|
||||
if (scrollInfo == null) {
|
||||
return;
|
||||
}
|
||||
if (mTopAreaBehavior != null) {
|
||||
mTopAreaBehavior.setTopAndBottomOffset(scrollInfo.getTopBottomOffset());
|
||||
}
|
||||
if (mTopView != null) {
|
||||
mTopView.restoreScrollInfo(scrollInfo.topInfo);
|
||||
}
|
||||
|
||||
if (mBottomView != null) {
|
||||
mBottomView.restoreScrollInfo(scrollInfo.bottomInfo);
|
||||
}
|
||||
}
|
||||
|
||||
public interface OnScrollListener {
|
||||
void onTopScroll(int offset, int range, int innerOffset, int innerRange);
|
||||
|
||||
void onBottomScroll(int offset, int range, int innerOffset, int innerRange);
|
||||
}
|
||||
|
||||
public static class ScrollInfo {
|
||||
private Object topInfo;
|
||||
private Object bottomInfo;
|
||||
private int topBottomOffset;
|
||||
|
||||
public ScrollInfo(Object topInfo, Object bottomInfo, int topBottomOffset) {
|
||||
this.topInfo = topInfo;
|
||||
this.bottomInfo = bottomInfo;
|
||||
this.topBottomOffset = topBottomOffset;
|
||||
}
|
||||
|
||||
public int getTopBottomOffset() {
|
||||
return topBottomOffset;
|
||||
}
|
||||
|
||||
public Object getTopInfo() {
|
||||
return topInfo;
|
||||
}
|
||||
|
||||
public Object getBottomInfo() {
|
||||
return bottomInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-2
@@ -272,9 +272,11 @@ public class QMUIContinuousNestedTopAreaBehavior extends QMUIViewOffsetBehavior<
|
||||
// child is topView, target is bottomView
|
||||
if (target instanceof IQMUIContinuousNestedBottomView) {
|
||||
int contentHeight = ((IQMUIContinuousNestedBottomView) target).getContentHeight();
|
||||
int minOffset = -child.getHeight();
|
||||
int minOffset;
|
||||
if (contentHeight != IQMUIContinuousNestedBottomView.HEIGHT_IS_ENOUGH_TO_SCROLL) {
|
||||
minOffset = parent.getHeight() - contentHeight - child.getHeight();
|
||||
}else{
|
||||
minOffset = parent.getHeight() - child.getHeight() - target.getHeight();
|
||||
}
|
||||
if (child.getTop() - dy >= minOffset) {
|
||||
setTopAndBottomOffset(child.getTop() - dy - getLayoutTop());
|
||||
@@ -314,7 +316,7 @@ public class QMUIContinuousNestedTopAreaBehavior extends QMUIViewOffsetBehavior<
|
||||
int minBottom = parent.getHeight();
|
||||
boolean canContentScroll = true;
|
||||
if (contentHeight != IQMUIContinuousNestedBottomView.HEIGHT_IS_ENOUGH_TO_SCROLL) {
|
||||
minBottom = parent.getHeight() + parent.getHeight() - contentHeight;
|
||||
minBottom = parent.getHeight() + bottomView.getHeight() - contentHeight;
|
||||
canContentScroll = false;
|
||||
}
|
||||
if (bottomView.getBottom() - minBottom > dyUnconsumed) {
|
||||
|
||||
+58
-14
@@ -62,6 +62,7 @@ public class QMUIContinuousNestedTopDelegateLayout extends FrameLayout implement
|
||||
mChildHelper = new NestedScrollingChildHelper(this);
|
||||
|
||||
ViewCompat.setNestedScrollingEnabled(this, true);
|
||||
setClipToPadding(false);
|
||||
}
|
||||
|
||||
public void setHeaderView(@NonNull View headerView) {
|
||||
@@ -92,30 +93,36 @@ public class QMUIContinuousNestedTopDelegateLayout extends FrameLayout implement
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
int w = MeasureSpec.getSize(widthMeasureSpec);
|
||||
int h = MeasureSpec.getSize(heightMeasureSpec);
|
||||
int anchorHeight = 0;
|
||||
int anchorHeight = getPaddingTop();
|
||||
if (mHeaderView != null) {
|
||||
mHeaderView.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(h, MeasureSpec.AT_MOST));
|
||||
anchorHeight += mHeaderView.getMeasuredHeight();
|
||||
}
|
||||
if (mDelegateView != null) {
|
||||
View delegateView = (View) mDelegateView;
|
||||
delegateView.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(h, MeasureSpec.AT_MOST));
|
||||
anchorHeight += delegateView.getMeasuredHeight();
|
||||
}
|
||||
|
||||
if (mFooterView != null) {
|
||||
mFooterView.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(h, MeasureSpec.AT_MOST));
|
||||
anchorHeight += mFooterView.getMeasuredHeight();
|
||||
}
|
||||
|
||||
anchorHeight += getPaddingBottom();
|
||||
if (anchorHeight < h) {
|
||||
setMeasuredDimension(w, anchorHeight);
|
||||
} else {
|
||||
setMeasuredDimension(w, h);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
int w = right - left, h = bottom - top;
|
||||
int anchorTop = 0;
|
||||
int anchorTop = getPaddingTop();
|
||||
int viewHeight;
|
||||
if (mHeaderView != null) {
|
||||
viewHeight = mHeaderView.getMeasuredHeight();
|
||||
@@ -135,6 +142,7 @@ public class QMUIContinuousNestedTopDelegateLayout extends FrameLayout implement
|
||||
mFooterView.layout(0, anchorTop, w, anchorTop + viewHeight);
|
||||
anchorTop += viewHeight;
|
||||
}
|
||||
anchorTop += getPaddingBottom();
|
||||
|
||||
mOffsetRange = Math.max(0, anchorTop - h);
|
||||
|
||||
@@ -195,7 +203,7 @@ public class QMUIContinuousNestedTopDelegateLayout extends FrameLayout implement
|
||||
}
|
||||
return dyUnconsumed;
|
||||
} else {
|
||||
int beforeRange = mHeaderView == null ? 0 : mHeaderView.getHeight();
|
||||
int beforeRange = getPaddingTop() + (mHeaderView == null ? 0 : mHeaderView.getHeight());
|
||||
if (dyUnconsumed == Integer.MAX_VALUE) {
|
||||
offsetTo(beforeRange);
|
||||
} else if (mOffsetCurrent + dyUnconsumed <= beforeRange) {
|
||||
@@ -233,7 +241,7 @@ public class QMUIContinuousNestedTopDelegateLayout extends FrameLayout implement
|
||||
}
|
||||
return dyUnconsumed;
|
||||
}
|
||||
int afterRange = mOffsetRange - (mFooterView == null ? 0 : mFooterView.getHeight());
|
||||
int afterRange = mOffsetRange - getPaddingBottom() - (mFooterView == null ? 0 : mFooterView.getHeight());
|
||||
if (dyUnconsumed == Integer.MIN_VALUE) {
|
||||
offsetTo(afterRange);
|
||||
} else if (mOffsetCurrent + dyUnconsumed > afterRange) {
|
||||
@@ -291,6 +299,41 @@ public class QMUIContinuousNestedTopDelegateLayout extends FrameLayout implement
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object saveScrollInfo() {
|
||||
return new ScrollInfo(-mOffsetCurrent, mDelegateView == null ? null : mDelegateView.saveScrollInfo());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreScrollInfo(Object scrollInfo) {
|
||||
if (scrollInfo instanceof ScrollInfo) {
|
||||
ScrollInfo si = (ScrollInfo) scrollInfo;
|
||||
if (mHeaderViewOffsetHelper != null) {
|
||||
mHeaderViewOffsetHelper.setTopAndBottomOffset(si.topBottomOffset);
|
||||
}
|
||||
if (mDelegateViewOffsetHelper != null) {
|
||||
mDelegateViewOffsetHelper.setTopAndBottomOffset(si.topBottomOffset);
|
||||
}
|
||||
if (mFooterViewOffsetHelper != null) {
|
||||
mFooterViewOffsetHelper.setTopAndBottomOffset(si.topBottomOffset);
|
||||
}
|
||||
|
||||
if (mDelegateView != null) {
|
||||
mDelegateView.restoreScrollInfo(((ScrollInfo) scrollInfo).delegateScrollInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class ScrollInfo {
|
||||
int topBottomOffset;
|
||||
Object delegateScrollInfo;
|
||||
|
||||
public ScrollInfo(int topBottomOffset, Object delegateScrollInfo) {
|
||||
this.topBottomOffset = topBottomOffset;
|
||||
this.delegateScrollInfo = delegateScrollInfo;
|
||||
}
|
||||
}
|
||||
|
||||
// NestedScrollingChild2
|
||||
|
||||
@Override
|
||||
@@ -395,7 +438,7 @@ public class QMUIContinuousNestedTopDelegateLayout extends FrameLayout implement
|
||||
public void onNestedScroll(View target, int dxConsumed, int dyConsumed, int dxUnconsumed,
|
||||
int dyUnconsumed, int type) {
|
||||
int consumed = 0;
|
||||
if (dyUnconsumed > 0 && mFooterView != null) {
|
||||
if (dyUnconsumed > 0) {
|
||||
if (mOffsetCurrent + dyUnconsumed <= mOffsetRange) {
|
||||
consumed = dyUnconsumed;
|
||||
offsetTo(mOffsetCurrent + dyUnconsumed);
|
||||
@@ -403,7 +446,7 @@ public class QMUIContinuousNestedTopDelegateLayout extends FrameLayout implement
|
||||
consumed = mOffsetRange - mOffsetCurrent;
|
||||
offsetTo(mOffsetRange);
|
||||
}
|
||||
} else if (dyUnconsumed < 0 && mHeaderView != null) {
|
||||
} else if (dyUnconsumed < 0) {
|
||||
if (mOffsetCurrent + dyUnconsumed >= 0) {
|
||||
consumed = dyUnconsumed;
|
||||
offsetTo(mOffsetCurrent + dyUnconsumed);
|
||||
@@ -421,16 +464,17 @@ public class QMUIContinuousNestedTopDelegateLayout extends FrameLayout implement
|
||||
int type) {
|
||||
dispatchNestedPreScroll(dx, dy, consumed, null, type);
|
||||
int unconsumed = dy - consumed[1];
|
||||
if (unconsumed > 0 && mHeaderView != null) {
|
||||
if (mOffsetCurrent + unconsumed <= mHeaderView.getHeight()) {
|
||||
if (unconsumed > 0) {
|
||||
int topMargin = getPaddingTop() + (mHeaderView == null ? 0 : mHeaderView.getHeight());
|
||||
if (mOffsetCurrent + unconsumed <= topMargin) {
|
||||
offsetTo(mOffsetCurrent + unconsumed);
|
||||
consumed[1] += unconsumed;
|
||||
} else if (mOffsetCurrent < mHeaderView.getHeight()) {
|
||||
consumed[1] += mHeaderView.getHeight() - mOffsetCurrent;
|
||||
offsetTo(mHeaderView.getHeight());
|
||||
} else if (mOffsetCurrent < topMargin) {
|
||||
consumed[1] += topMargin - mOffsetCurrent;
|
||||
offsetTo(topMargin);
|
||||
}
|
||||
} else if (unconsumed < 0 && mFooterView != null) {
|
||||
int b = mOffsetRange - mFooterView.getHeight();
|
||||
} else if (unconsumed < 0) {
|
||||
int b = mOffsetRange - getPaddingBottom() - (mFooterView != null ? mFooterView.getHeight() : 0);
|
||||
if (mOffsetCurrent + unconsumed >= b) {
|
||||
offsetTo(mOffsetCurrent + unconsumed);
|
||||
consumed[1] += unconsumed;
|
||||
|
||||
+10
@@ -56,4 +56,14 @@ public class QMUIContinuousNestedTopLinearLayout extends QMUILinearLayout implem
|
||||
public void injectScrollNotifier(OnScrollNotifier notifier) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreScrollInfo(Object scrollInfo) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object saveScrollInfo() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
+40
@@ -20,8 +20,10 @@ import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.view.ViewCompat;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
|
||||
public class QMUIContinuousNestedTopRecyclerView extends RecyclerView implements IQMUIContinuousNestedTopView {
|
||||
|
||||
@@ -92,4 +94,42 @@ public class QMUIContinuousNestedTopRecyclerView extends RecyclerView implements
|
||||
super.onScrolled(dx, dy);
|
||||
mScrollNotifier.notify(getCurrentScroll(), getScrollOffsetRange());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object saveScrollInfo() {
|
||||
LayoutManager layoutManager = getLayoutManager();
|
||||
if (layoutManager instanceof LinearLayoutManager) {
|
||||
LinearLayoutManager lm = (LinearLayoutManager) layoutManager;
|
||||
if (lm.getOrientation() == LinearLayoutManager.HORIZONTAL) {
|
||||
return null;
|
||||
}
|
||||
int pos = lm.findFirstVisibleItemPosition();
|
||||
View firstView = lm.findViewByPosition(pos);
|
||||
int offset = firstView == null ? 0 : firstView.getTop();
|
||||
return new ScrollInfo(pos, offset);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreScrollInfo(Object scrollInfo) {
|
||||
if (!(scrollInfo instanceof ScrollInfo)) {
|
||||
return;
|
||||
}
|
||||
ScrollInfo sc = (ScrollInfo) scrollInfo;
|
||||
LayoutManager layoutManager = getLayoutManager();
|
||||
if (layoutManager instanceof LinearLayoutManager) {
|
||||
((LinearLayoutManager) layoutManager).scrollToPositionWithOffset(sc.scrollPosition, sc.scrollOffset);
|
||||
}
|
||||
}
|
||||
|
||||
public static class ScrollInfo {
|
||||
int scrollPosition;
|
||||
int scrollOffset;
|
||||
|
||||
public ScrollInfo(int scrollPosition, int scrollOffset) {
|
||||
this.scrollPosition = scrollPosition;
|
||||
this.scrollOffset = scrollOffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,4 +78,16 @@ public class QMUIContinuousNestedTopWebView extends QMUIWebView implements IQMUI
|
||||
mScrollNotifier.notify(getCurrentScroll(), getScrollOffsetRange());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object saveScrollInfo() {
|
||||
return getScrollY();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreScrollInfo(Object scrollInfo) {
|
||||
if (scrollInfo instanceof Integer) {
|
||||
scrollTo(0, (Integer) scrollInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@ public class QDContinuousBottomView extends QMUIContinuousNestedBottomDelegateLa
|
||||
|
||||
private MyViewPager mViewPager;
|
||||
private QMUIContinuousNestedBottomRecyclerView mCurrentItemView;
|
||||
private int mCurrentPosition = -1;
|
||||
private IQMUIContinuousNestedBottomView.OnScrollNotifier mOnScrollNotifier;
|
||||
|
||||
public QDContinuousBottomView(Context context) {
|
||||
@@ -146,6 +147,7 @@ public class QDContinuousBottomView extends QMUIContinuousNestedBottomDelegateLa
|
||||
public void setPrimaryItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
|
||||
super.setPrimaryItem(container, position, object);
|
||||
mCurrentItemView = (QMUIContinuousNestedBottomRecyclerView) object;
|
||||
mCurrentPosition = position;
|
||||
if (mOnScrollNotifier != null) {
|
||||
mCurrentItemView.injectScrollNotifier(mOnScrollNotifier);
|
||||
}
|
||||
@@ -208,5 +210,33 @@ public class QDContinuousBottomView extends QMUIContinuousNestedBottomDelegateLa
|
||||
mCurrentItemView.injectScrollNotifier(notifier);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object saveScrollInfo() {
|
||||
if (mCurrentItemView != null) {
|
||||
return new ScrollInfo(mCurrentPosition, mCurrentItemView.saveScrollInfo());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreScrollInfo(Object scrollInfo) {
|
||||
if (mCurrentItemView != null && (scrollInfo instanceof ScrollInfo)) {
|
||||
ScrollInfo si = (ScrollInfo) scrollInfo;
|
||||
if (si.currentPosition == mCurrentPosition) {
|
||||
mCurrentItemView.restoreScrollInfo(si.currentScrollInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ScrollInfo {
|
||||
int currentPosition;
|
||||
Object currentScrollInfo;
|
||||
|
||||
public ScrollInfo(int currentPosition, Object currentScrollInfo) {
|
||||
this.currentPosition = currentPosition;
|
||||
this.currentScrollInfo = currentScrollInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user