QMUIRVDraggableScrollBar add support for QMUIStickySectionLayout

This commit is contained in:
cgspine
2020-02-13 12:36:27 +08:00
parent ffae758c2e
commit 05074366bf
3 changed files with 124 additions and 25 deletions
@@ -1,10 +1,12 @@
package com.qmuiteam.qmui.recyclerView;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.view.MotionEvent;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -18,14 +20,16 @@ import com.qmuiteam.qmui.skin.QMUISkinHelper;
import com.qmuiteam.qmui.skin.QMUISkinManager;
import com.qmuiteam.qmui.util.QMUILangHelper;
import com.qmuiteam.qmui.util.QMUIResHelper;
import com.qmuiteam.qmui.widget.section.QMUIStickySectionLayout;
public class QMUIRVDraggableScrollBar extends RecyclerView.ItemDecoration implements IQMUISkinHandlerDecoration {
public class QMUIRVDraggableScrollBar extends RecyclerView.ItemDecoration implements IQMUISkinHandlerDecoration, QMUIStickySectionLayout.DrawDecoration {
private int[] STATE_PRESSED = new int[]{android.R.attr.state_pressed};
private int[] STATE_NORMAL = new int[]{};
private static final long DEFAULT_KEE_SHOW_DURATION = 800L;
private static final long DEFAULT_TRANSITION_DURATION = 100L;
RecyclerView mRecyclerView;
QMUIStickySectionLayout mStickySectionLayout;
private final int mStartMargin;
private final int mEndMargin;
private final int mInwardOffset;
@@ -72,9 +76,7 @@ public class QMUIRVDraggableScrollBar extends RecyclerView.ItemDecoration implem
mTargetAlpha = 0;
mBeginAlpha = mCurrentAlpha;
mStartTransitionTime = System.currentTimeMillis();
if (mRecyclerView != null) {
mRecyclerView.invalidate();
}
invalidate();
}
};
@@ -152,9 +154,7 @@ public class QMUIRVDraggableScrollBar extends RecyclerView.ItemDecoration implem
mStartTransitionTime = System.currentTimeMillis();
mBeginAlpha = mCurrentAlpha;
mTargetAlpha = 255;
if (mRecyclerView != null) {
mRecyclerView.invalidate();
}
invalidate();
} else if (newState == RecyclerView.SCROLL_STATE_IDLE) {
recyclerView.postDelayed(mFadeScrollBarAction, mKeepShownTime);
}
@@ -167,6 +167,14 @@ public class QMUIRVDraggableScrollBar extends RecyclerView.ItemDecoration implem
mCallback = callback;
}
private void invalidate(){
if(mStickySectionLayout != null){
mStickySectionLayout.invalidate();
} else if (mRecyclerView != null) {
mRecyclerView.invalidate();
}
}
public void setScrollBarDrawable(@Nullable Drawable scrollBarDrawable) {
mScrollBarDrawable = scrollBarDrawable;
if (scrollBarDrawable != null) {
@@ -174,8 +182,8 @@ public class QMUIRVDraggableScrollBar extends RecyclerView.ItemDecoration implem
}
if (mRecyclerView != null) {
QMUISkinHelper.refreshRVItemDecoration(mRecyclerView, this);
mRecyclerView.invalidate();
}
invalidate();
}
public void setScrollBarSkinRes(int scrollBarSkinRes) {
@@ -183,6 +191,7 @@ public class QMUIRVDraggableScrollBar extends RecyclerView.ItemDecoration implem
if (mRecyclerView != null) {
QMUISkinHelper.refreshRVItemDecoration(mRecyclerView, this);
}
invalidate();
}
public void setScrollBarSkinTintColorRes(int colorRes) {
@@ -190,6 +199,7 @@ public class QMUIRVDraggableScrollBar extends RecyclerView.ItemDecoration implem
if (mRecyclerView != null) {
QMUISkinHelper.refreshRVItemDecoration(mRecyclerView, this);
}
invalidate();
}
public void setDraggable(boolean draggable) {
@@ -216,9 +226,7 @@ public class QMUIRVDraggableScrollBar extends RecyclerView.ItemDecoration implem
mCurrentAlpha = 0;
}
}
if (mRecyclerView != null) {
mRecyclerView.invalidate();
}
invalidate();
}
}
@@ -226,7 +234,7 @@ public class QMUIRVDraggableScrollBar extends RecyclerView.ItemDecoration implem
return mEnableScrollBarFadeInOut;
}
public void attachToRecyclerView(@Nullable RecyclerView recyclerView) {
private void commonAttachToRecyclerView(@Nullable RecyclerView recyclerView){
if (mRecyclerView == recyclerView) {
return; // nothing to do
}
@@ -240,6 +248,28 @@ public class QMUIRVDraggableScrollBar extends RecyclerView.ItemDecoration implem
}
}
public void attachToRecyclerView(@Nullable RecyclerView recyclerView) {
if(mStickySectionLayout != null){
mStickySectionLayout.removeDrawDecoration(this);
mStickySectionLayout = null;
}
commonAttachToRecyclerView(recyclerView);
}
public void attachToStickSectionLayout(@Nullable QMUIStickySectionLayout stickySectionLayout){
if(mStickySectionLayout == stickySectionLayout){
return; // nothing to do
}
if(mStickySectionLayout != null){
mStickySectionLayout.removeDrawDecoration(this);
}
mStickySectionLayout = stickySectionLayout;
if(stickySectionLayout != null){
stickySectionLayout.addDrawDecoration(this);
commonAttachToRecyclerView(stickySectionLayout.getRecyclerView());
}
}
private void setupCallbacks() {
mRecyclerView.addItemDecoration(this);
mRecyclerView.addOnItemTouchListener(mOnItemTouchListener);
@@ -263,8 +293,8 @@ public class QMUIRVDraggableScrollBar extends RecyclerView.ItemDecoration implem
}
if (mRecyclerView != null) {
mRecyclerView.removeCallbacks(mFadeScrollBarAction);
mRecyclerView.invalidate();
}
invalidate();
}
private void endDrag() {
@@ -275,9 +305,7 @@ public class QMUIRVDraggableScrollBar extends RecyclerView.ItemDecoration implem
if (mCallback != null) {
mCallback.onDragEnd();
}
if (mRecyclerView != null) {
mRecyclerView.invalidate();
}
invalidate();
}
private void onDragging(RecyclerView recyclerView, Drawable drawable, int x, int y) {
@@ -309,14 +337,31 @@ public class QMUIRVDraggableScrollBar extends RecyclerView.ItemDecoration implem
recyclerView.scrollBy(delta, 0);
}
}
recyclerView.invalidate();
invalidate();
}
@Override
public void onDrawOver(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
super.onDrawOver(c, parent, state);
Drawable drawable = ensureScrollBar(parent);
if(mStickySectionLayout == null){
drawScrollBar(c, parent);
}
}
@Override
public void onDraw(@NonNull Canvas c, @NonNull QMUIStickySectionLayout parent) {
}
@Override
public void onDrawOver(@NonNull Canvas c, @NonNull QMUIStickySectionLayout parent) {
if(mRecyclerView != null){
drawScrollBar(c, mRecyclerView);
}
}
private void drawScrollBar(@NonNull Canvas c, @NonNull RecyclerView recyclerView){
Drawable drawable = ensureScrollBar(recyclerView.getContext());
if (drawable == null) {
return;
}
@@ -330,16 +375,16 @@ public class QMUIRVDraggableScrollBar extends RecyclerView.ItemDecoration implem
mBeginAlpha = -1;
} else {
mCurrentAlpha = (int) (mBeginAlpha + (mTargetAlpha - mBeginAlpha) * transitionTime * 1f / duration);
parent.postInvalidateOnAnimation();
recyclerView.postInvalidateOnAnimation();
}
}
drawable.setAlpha(mCurrentAlpha);
if (!mIsInDragging) {
mPercent = calculatePercent(parent);
mPercent = calculatePercent(recyclerView);
}
setScrollBarBounds(parent, drawable);
setScrollBarBounds(recyclerView, drawable);
drawable.draw(c);
}
@@ -385,10 +430,10 @@ public class QMUIRVDraggableScrollBar extends RecyclerView.ItemDecoration implem
return getCurrentOffset(recyclerView) * 1f / getScrollRange(recyclerView);
}
public Drawable ensureScrollBar(RecyclerView recyclerView) {
public Drawable ensureScrollBar(Context context) {
if (mScrollBarDrawable == null) {
setScrollBarDrawable(
ContextCompat.getDrawable(recyclerView.getContext(), R.drawable.qmui_icon_scroll_bar));
ContextCompat.getDrawable(context, R.drawable.qmui_icon_scroll_bar));
}
return mScrollBarDrawable;
}
@@ -406,7 +451,7 @@ public class QMUIRVDraggableScrollBar extends RecyclerView.ItemDecoration implem
QMUIResHelper.getAttrColorStateList(
recyclerView.getContext(), theme, mScrollBarSkinTintColorRes));
}
recyclerView.invalidate();
invalidate();
}
interface Callback {
@@ -21,18 +21,26 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import com.qmuiteam.qmui.layout.QMUIFrameLayout;
import java.util.ArrayList;
import java.util.List;
public class QMUIStickySectionLayout extends QMUIFrameLayout implements QMUIStickySectionAdapter.ViewCallback {
private RecyclerView mRecyclerView;
private QMUIFrameLayout mStickySectionWrapView;
private QMUIStickySectionItemDecoration mStickySectionItemDecoration;
private int mStickySectionViewHeight = -1;
private List<DrawDecoration> mDrawDecorations;
/**
* if scrollToPosition happened before mStickySectionWrapView finished layout,
* the target item may be covered by mStickySectionWrapView, so we delay to
@@ -68,6 +76,20 @@ public class QMUIStickySectionLayout extends QMUIFrameLayout implements QMUIStic
});
}
public void addDrawDecoration(@NonNull DrawDecoration drawDecoration){
if(mDrawDecorations == null){
mDrawDecorations = new ArrayList<>();
}
mDrawDecorations.add(drawDecoration);
}
public void removeDrawDecoration(@NonNull DrawDecoration drawDecoration){
if(mDrawDecorations == null || mDrawDecorations.isEmpty()){
return;
}
mDrawDecorations.remove(drawDecoration);
}
public void configStickySectionWrapView(StickySectionWrapViewConfig stickySectionWrapViewConfig) {
if (stickySectionWrapViewConfig != null) {
stickySectionWrapViewConfig.config(mStickySectionWrapView);
@@ -235,4 +257,32 @@ public class QMUIStickySectionLayout extends QMUIFrameLayout implements QMUIStic
public interface StickySectionWrapViewConfig {
void config(QMUIFrameLayout stickySectionWrapView);
}
@Override
protected void dispatchDraw(Canvas canvas) {
if(mDrawDecorations != null){
for(DrawDecoration drawDecoration: mDrawDecorations){
drawDecoration.onDraw(canvas, this);
}
}
super.dispatchDraw(canvas);
if(mDrawDecorations != null){
for(DrawDecoration drawDecoration: mDrawDecorations){
drawDecoration.onDrawOver(canvas, this);
}
}
}
@Override
public void onDescendantInvalidated(@NonNull View child, @NonNull View target) {
super.onDescendantInvalidated(child, target);
if(target == mRecyclerView && mDrawDecorations != null && !mDrawDecorations.isEmpty()){
invalidate();
}
}
public interface DrawDecoration {
void onDraw(@NonNull Canvas c, @NonNull QMUIStickySectionLayout parent);
void onDrawOver(@NonNull Canvas c, @NonNull QMUIStickySectionLayout parent);
}
}
@@ -23,6 +23,7 @@ import android.view.LayoutInflater;
import android.view.View;
import android.widget.Toast;
import com.qmuiteam.qmui.recyclerView.QMUIRVDraggableScrollBar;
import com.qmuiteam.qmui.widget.QMUITopBarLayout;
import com.qmuiteam.qmui.widget.dialog.QMUIBottomSheet;
import com.qmuiteam.qmui.widget.pullRefreshLayout.QMUIPullRefreshLayout;
@@ -109,6 +110,9 @@ public abstract class QDBaseSectionLayoutFragment extends BaseFragment {
protected void initStickyLayout() {
mLayoutManager = createLayoutManager();
mSectionLayout.setLayoutManager(mLayoutManager);
QMUIRVDraggableScrollBar scrollBar = new QMUIRVDraggableScrollBar(0, 0, 0);
scrollBar.setEnableScrollBarFadeInOut(false);
scrollBar.attachToStickSectionLayout(mSectionLayout);
}
private void initData() {