From 59788fd658f2c48dbedab228ad235e6813d9b5df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=8A=B2=E9=B9=8F?= Date: Wed, 29 Jun 2022 15:06:18 +0800 Subject: [PATCH] fix scrollable false prevent scrollToPosition --- .../shader/flowlayout/FlowLayoutNode.java | 35 +++++++++++++++++ .../java/pub/doric/shader/list/ListNode.java | 34 ++++++++++++++++ .../pub/doric/shader/slider/SliderNode.java | 39 +++++++++++++++++++ doric-demo/src/SliderDemo.ts | 24 ++++++++++++ 4 files changed, 132 insertions(+) diff --git a/doric-android/doric/src/main/java/pub/doric/shader/flowlayout/FlowLayoutNode.java b/doric-android/doric/src/main/java/pub/doric/shader/flowlayout/FlowLayoutNode.java index c791fbec..7e791f32 100644 --- a/doric-android/doric/src/main/java/pub/doric/shader/flowlayout/FlowLayoutNode.java +++ b/doric-android/doric/src/main/java/pub/doric/shader/flowlayout/FlowLayoutNode.java @@ -15,11 +15,13 @@ */ package pub.doric.shader.flowlayout; +import android.content.Context; import android.graphics.Rect; import android.text.TextUtils; import android.view.View; import androidx.annotation.NonNull; +import androidx.recyclerview.widget.LinearSmoothScroller; import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.StaggeredGridLayoutManager; @@ -82,6 +84,17 @@ public class FlowLayoutNode extends SuperNode implements IDoricScr } return super.canScrollVertically(); } + + @Override + public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) { + if (scrollable) { + super.smoothScrollToPosition(recyclerView, state, position); + } else { + DoricLinearSmoothScroller linearSmoothScroller = new DoricLinearSmoothScroller(recyclerView.getContext()); + linearSmoothScroller.setTargetPosition(position); + startSmoothScroll(linearSmoothScroller); + } + } }; private int columnSpace = 0; private int rowSpace = 0; @@ -395,4 +408,26 @@ public class FlowLayoutNode extends SuperNode implements IDoricScr onScrollEndFuncId = null; flowAdapter.renderItemFuncId = null; } + + private static class DoricLinearSmoothScroller extends LinearSmoothScroller { + + public DoricLinearSmoothScroller(Context context) { + super(context); + } + + @Override + public int calculateDyToMakeVisible(View view, int snapPreference) { + final RecyclerView.LayoutManager layoutManager = getLayoutManager(); + if (layoutManager == null) { + return 0; + } + final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) + view.getLayoutParams(); + final int top = layoutManager.getDecoratedTop(view) - params.topMargin; + final int bottom = layoutManager.getDecoratedBottom(view) + params.bottomMargin; + final int start = layoutManager.getPaddingTop(); + final int end = layoutManager.getHeight() - layoutManager.getPaddingBottom(); + return calculateDtToFit(top, bottom, start, end, snapPreference); + } + } } diff --git a/doric-android/doric/src/main/java/pub/doric/shader/list/ListNode.java b/doric-android/doric/src/main/java/pub/doric/shader/list/ListNode.java index 46ff57d3..4df3f197 100644 --- a/doric-android/doric/src/main/java/pub/doric/shader/list/ListNode.java +++ b/doric-android/doric/src/main/java/pub/doric/shader/list/ListNode.java @@ -16,6 +16,7 @@ package pub.doric.shader.list; import android.annotation.SuppressLint; +import android.content.Context; import android.text.TextUtils; import android.util.SparseArray; import android.view.GestureDetector; @@ -26,6 +27,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.recyclerview.widget.ItemTouchHelper; import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.LinearSmoothScroller; import androidx.recyclerview.widget.RecyclerView; import com.github.pengfeizhou.jscore.JSDecoder; @@ -136,6 +138,17 @@ public class ListNode extends SuperNode implements IDoricScrollabl } return super.canScrollVertically(); } + + @Override + public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) { + if (scrollable) { + super.smoothScrollToPosition(recyclerView, state, position); + } else { + DoricLinearSmoothScroller linearSmoothScroller = new DoricLinearSmoothScroller(recyclerView.getContext()); + linearSmoothScroller.setTargetPosition(position); + startSmoothScroll(linearSmoothScroller); + } + } }); recyclerView.setAdapter(this.listAdapter); recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @@ -537,4 +550,25 @@ public class ListNode extends SuperNode implements IDoricScrollabl void onMoved(int fromPos, int toPos); } + private static class DoricLinearSmoothScroller extends LinearSmoothScroller { + + public DoricLinearSmoothScroller(Context context) { + super(context); + } + + @Override + public int calculateDyToMakeVisible(View view, int snapPreference) { + final RecyclerView.LayoutManager layoutManager = getLayoutManager(); + if (layoutManager == null) { + return 0; + } + final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) + view.getLayoutParams(); + final int top = layoutManager.getDecoratedTop(view) - params.topMargin; + final int bottom = layoutManager.getDecoratedBottom(view) + params.bottomMargin; + final int start = layoutManager.getPaddingTop(); + final int end = layoutManager.getHeight() - layoutManager.getPaddingBottom(); + return calculateDtToFit(top, bottom, start, end, snapPreference); + } + } } diff --git a/doric-android/doric/src/main/java/pub/doric/shader/slider/SliderNode.java b/doric-android/doric/src/main/java/pub/doric/shader/slider/SliderNode.java index a20502c8..af86c619 100644 --- a/doric-android/doric/src/main/java/pub/doric/shader/slider/SliderNode.java +++ b/doric-android/doric/src/main/java/pub/doric/shader/slider/SliderNode.java @@ -15,11 +15,14 @@ */ package pub.doric.shader.slider; +import android.annotation.SuppressLint; +import android.content.Context; import android.text.TextUtils; import android.view.View; import androidx.annotation.NonNull; import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.LinearSmoothScroller; import androidx.recyclerview.widget.PagerSnapHelper; import androidx.recyclerview.widget.RecyclerView; @@ -58,6 +61,7 @@ public class SliderNode extends SuperNode { protected RecyclerView build() { RecyclerView recyclerView = new RecyclerView(getContext()); + final LinearLayoutManager layoutManager = new LinearLayoutManager(getContext()) { @Override public boolean canScrollHorizontally() { @@ -66,7 +70,19 @@ public class SliderNode extends SuperNode { } return super.canScrollHorizontally(); } + + @Override + public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) { + if (scrollable) { + super.smoothScrollToPosition(recyclerView, state, position); + } else { + DoricLinearSmoothScroller linearSmoothScroller = new DoricLinearSmoothScroller(recyclerView.getContext()); + linearSmoothScroller.setTargetPosition(position); + startSmoothScroll(linearSmoothScroller); + } + } }; + layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); recyclerView.setLayoutManager(layoutManager); final PagerSnapHelper snapHelper = new PagerSnapHelper(); @@ -165,6 +181,7 @@ public class SliderNode extends SuperNode { if (jsObject.propertySet().size() > 1 || !jsObject.propertySet().contains("subviews")) { if (mView != null) { mView.post(new Runnable() { + @SuppressLint("NotifyDataSetChanged") @Override public void run() { slideAdapter.itemCount = itemCount; @@ -257,4 +274,26 @@ public class SliderNode extends SuperNode { onPageSlidedFuncId = null; renderPageFuncId = null; } + + private static class DoricLinearSmoothScroller extends LinearSmoothScroller { + + public DoricLinearSmoothScroller(Context context) { + super(context); + } + + @Override + public int calculateDxToMakeVisible(View view, int snapPreference) { + final RecyclerView.LayoutManager layoutManager = getLayoutManager(); + if (layoutManager == null) { + return 0; + } + final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) + view.getLayoutParams(); + final int left = layoutManager.getDecoratedLeft(view) - params.leftMargin; + final int right = layoutManager.getDecoratedRight(view) + params.rightMargin; + final int start = layoutManager.getPaddingLeft(); + final int end = layoutManager.getWidth() - layoutManager.getPaddingRight(); + return calculateDtToFit(left, right, start, end, snapPreference); + } + } } diff --git a/doric-demo/src/SliderDemo.ts b/doric-demo/src/SliderDemo.ts index 67424e7f..961dd05c 100644 --- a/doric-demo/src/SliderDemo.ts +++ b/doric-demo/src/SliderDemo.ts @@ -99,6 +99,30 @@ class SliderPanel extends Panel { space: 10, backgroundColor: Color.RED, }), + hlayout([ + text({ + text: "Scrollable", + layoutConfig: { + widthSpec: LayoutSpec.FIT, + heightSpec: LayoutSpec.JUST, + }, + textSize: 20, + textColor: Color.BLACK, + textAlignment: gravity().center(), + height: 50, + }), + switchView({ + state: true, + onSwitch: (state) => { + pager.scrollable = state + }, + }), + ], { + layoutConfig: layoutConfig().most().configHeight(LayoutSpec.FIT), + gravity: gravity().center(), + space: 10, + backgroundColor: Color.RED, + }), hlayout([ text({ text: "Bounces",