Skip to content

Commit 0a1ee0e

Browse files
authored
feat:Add onScrollBeginDrag and BeginRefresh properties and native implementation (#10)
1 parent 7150b47 commit 0a1ee0e

10 files changed

+124
-14
lines changed

harmony/spring_scrollview/src/main/cpp/EventEmitters.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,5 +99,13 @@ void RNCSpringScrollViewEventEmitter::onContentSizeChange(OnContentSizeChange ev
9999
return payload;
100100
});
101101
}
102+
103+
void RNCSpringScrollViewEventEmitter::onScrollBeginDrag() const {
104+
dispatchEvent("scrollBeginDrag", [](jsi::Runtime &runtime) {
105+
auto payload = jsi::Object(runtime);
106+
return payload;
107+
});
108+
}
109+
102110
} // namespace react
103111
} // namespace facebook

harmony/spring_scrollview/src/main/cpp/EventEmitters.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ class JSI_EXPORT RNCSpringScrollViewEventEmitter : public ViewEventEmitter {
6666
void onScroll(OnScroll value) const;
6767
void onSizeChange(OnSizeChange value) const;
6868
void onContentSizeChange(OnContentSizeChange value) const;
69+
void onScrollBeginDrag() const;
6970
};
7071
} // namespace react
7172
} // namespace facebook

harmony/spring_scrollview/src/main/cpp/SpringScrollViewComponentInstance.cpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -280,15 +280,14 @@ void SpringScrollViewComponentInstance::handleCommand(std::string const &command
280280
this->getLocalRootArkUINode().endLoading();
281281
this->firstLoad = false;
282282
} else if (commandName == "10002") {
283+
if (args[0] == nullptr) {
284+
this->getLocalRootArkUINode().scrollTo(0, args[1].asDouble(), args[2].asBool());
285+
return;
286+
}
283287
this->getLocalRootArkUINode().scrollTo(args[0].asDouble(), args[1].asDouble(), args[2].asBool());
284288
}
285289
}
286290

287-
void SpringScrollViewComponentInstance::setLayout(facebook::react::LayoutMetrics layoutMetrics) {
288-
CppComponentInstance::setLayout(layoutMetrics);
289-
DLOG(INFO) << "SpringScrollViewComponentInstance setLayout w:" << layoutMetrics.frame.size.width
290-
<< " h:" << layoutMetrics.frame.size.height;
291-
}
292291

293292
facebook::react::Size SpringScrollViewComponentInstance::getLayoutSize() { return this->m_layoutMetrics.frame.size; }
294293

@@ -315,4 +314,10 @@ void SpringScrollViewComponentInstance::finalizeUpdates() {
315314
DLOG(INFO) << "SpringScrollViewComponentInstance finalizeUpdates";
316315
this->getLocalRootArkUINode().init();
317316
}
317+
318+
void SpringScrollViewComponentInstance::onScrollBeginDrag() {
319+
DLOG(INFO) << "onScrollBeginDrag";
320+
m_eventEmitter->onScrollBeginDrag();
321+
};
322+
318323
} // namespace rnoh

harmony/spring_scrollview/src/main/cpp/SpringScrollViewComponentInstance.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,12 +78,13 @@ class SpringScrollViewComponentInstance : public CppComponentInstance<facebook::
7878
void callArkTSScrollYStart(float from, float to, long duration) override;
7979
void callArkTSAnimationCancel() override;
8080
void handleCommand(std::string const &commandName, folly::dynamic const &args) override;
81-
void setLayout(facebook::react::LayoutMetrics layoutMetrics) override;
8281
facebook::react::Size getLayoutSize() override;
8382
void onStateChanged(SharedConcreteState const &state) override;
8483
bool isHandlingTouches() const override;
8584
void setSwiperStatus(bool swiperStatus) override;
8685
void finalizeUpdates() override;
86+
void onScrollBeginDrag() override;
87+
8788
};
8889
} // namespace rnoh
8990
#endif // HARMONY_SpringScrollViewCOMPONENTINSTANCE_H

harmony/spring_scrollview/src/main/cpp/SpringScrollViewJSIBinder.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ class SpringScrollViewJSIBinder : public ViewComponentJSIBinder {
5555
events.setProperty(rt, "topMomentumScrollBegin", createDirectEvent(rt, "onMomentumScrollBegin"));
5656
events.setProperty(rt, "topMomentumScrollEnd", createDirectEvent(rt, "onMomentumScrollEnd"));
5757
events.setProperty(rt, "topScroll", createDirectEvent(rt, "onScroll"));
58+
events.setProperty(rt, "topScrollBeginDrag", createDirectEvent(rt, "onScrollBeginDrag"));
5859
return events;
5960
}
6061
};

harmony/spring_scrollview/src/main/cpp/SpringScrollViewNode.cpp

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,10 @@ void SpringScrollViewNode::onMove(ArkUI_GestureEvent *evt) {
155155
drag(lastPoint.x - x, lastPoint.y - y);
156156
lastPoint.x = x;
157157
lastPoint.y = y;
158+
if (this->m_scrollNodeDelegate && !this->scrollBeginDrag) {
159+
this->scrollBeginDrag = true;
160+
this->m_scrollNodeDelegate->onScrollBeginDrag();
161+
}
158162
}
159163

160164
void SpringScrollViewNode::onDown(ArkUI_GestureEvent *evt) {
@@ -199,6 +203,7 @@ void SpringScrollViewNode::onDown(ArkUI_GestureEvent *evt) {
199203
}
200204

201205
void SpringScrollViewNode::onUp(ArkUI_GestureEvent *evt) {
206+
this->scrollBeginDrag = false;
202207
if(!isMove) return;
203208
this->onMove(evt);
204209
dragging = false;
@@ -547,7 +552,7 @@ float SpringScrollViewNode::getXDampingCoefficient() {
547552
}
548553

549554
void SpringScrollViewNode ::setContentOffset(float x, float y) {
550-
if(this->isDestory) return;
555+
if(this->isDestory || !m_stackArkUINodeHandle || !m_scrollNodeDelegate) return;
551556
this->contentOffset.x = x;
552557
this->contentOffset.y = y;
553558
this->recordEventModel = std::make_shared<SpringScrollViewEvent>(5);
@@ -653,6 +658,12 @@ void SpringScrollViewNode ::endRefresh() {
653658
}
654659

655660
void SpringScrollViewNode ::scrollTo(float x, float y, bool animated) {
661+
this->setRecordEventModel();
662+
if(x == BEGIN_REFRESH){
663+
m_scrollNodeDelegate->callArkTSScrollYStart(0, y, 500);
664+
this->beginRefresh();
665+
return;
666+
}
656667
if( x == DISMINATE_KEYBOARD_SHOW_HIDE && this->recordKeyBoardShow) return;
657668
if(y == DISMINATE_KEYBOARD_SHOW_HIDE){
658669
this->recordKeyBoardShow = false;
@@ -911,4 +922,54 @@ void SpringScrollViewNode::setChildWidth(float width) {
911922

912923
void SpringScrollViewNode::setContentHeight(float height) { this->contentHeight = height; }
913924

925+
void SpringScrollViewNode::beginRefresh() {
926+
this->scrollBeginDrag = false;
927+
dragging = false;
928+
float vy = 0.020;
929+
draggingDirection = "";
930+
if (!momentumScrolling) {
931+
momentumScrolling = true;
932+
this->m_scrollNodeDelegate->onMomentumScrollBegin();
933+
}
934+
refreshStatus = "refreshing";
935+
contentInsets.top = refreshHeaderHeight;
936+
this->recordEventModel = std::make_shared<SpringScrollViewEvent>(5);
937+
this->recordEventModel->setNodeHandle(m_stackArkUINodeHandle);
938+
this->recordEventModel->setEventSpringScrollViewNodeDelegate(this->m_scrollNodeDelegate);
939+
this->recordEventModel->setRefreshStatus(refreshStatus);
940+
this->recordEventModel->setLoadingStatus(loadingStatus);
941+
this->recordEventModel->setEventBounces(bounces);
942+
this->recordEventModel->setEventContentOffset(contentOffset);
943+
this->recordEventModel->setEventSize(size);
944+
this->recordEventModel->setEventContentSize(contentSize);
945+
this->recordEventModel->setEventContentInsets(contentInsets);
946+
this->recordEventModel->setEventBeginPoint(beginPoint);
947+
this->recordEventModel->setEventLastPoint(lastPoint);
948+
this->recordEventModel->setEventMomentumScrolling(momentumScrolling);
949+
auto baseEvent = std::static_pointer_cast<EventBus::Event>(this->recordEventModel);
950+
EventBus::EventBus::getInstance()->setEvent(baseEvent);
951+
this->beginOuterAnimation(vy);
952+
}
953+
954+
955+
void SpringScrollViewNode::setRecordEventModel() {
956+
auto recordEvent = std::static_pointer_cast<SpringScrollViewEvent>(EventBus::EventBus::getInstance()->getEvent());
957+
this->contentOffset = recordEvent->getEventContentOffset();
958+
this->recordEventModel = std::make_shared<SpringScrollViewEvent>(5);
959+
this->recordEventModel->setNodeHandle(m_stackArkUINodeHandle);
960+
this->recordEventModel->setEventSpringScrollViewNodeDelegate(this->m_scrollNodeDelegate);
961+
this->recordEventModel->setRefreshStatus(refreshStatus);
962+
this->recordEventModel->setLoadingStatus(loadingStatus);
963+
this->recordEventModel->setEventBounces(bounces);
964+
this->recordEventModel->setEventContentOffset(contentOffset);
965+
this->recordEventModel->setEventSize(size);
966+
this->recordEventModel->setEventContentSize(contentSize);
967+
this->recordEventModel->setEventContentInsets(contentInsets);
968+
this->recordEventModel->setEventBeginPoint(beginPoint);
969+
this->recordEventModel->setEventLastPoint(lastPoint);
970+
this->recordEventModel->setEventMomentumScrolling(momentumScrolling);
971+
auto baseEvent = std::static_pointer_cast<EventBus::Event>(this->recordEventModel);
972+
EventBus::EventBus::getInstance()->setEvent(baseEvent);
973+
}
974+
914975
} // namespace rnoh

harmony/spring_scrollview/src/main/cpp/SpringScrollViewNode.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ class SpringScrollViewNodeDelegate {
6262
virtual void callArkTSAnimationCancel(){};
6363
virtual facebook::react::Size getLayoutSize(){};
6464
virtual void setSwiperStatus(bool swiperStatus){};
65+
virtual void onScrollBeginDrag(){};
6566
};
6667

6768
class SpringScrollViewNode : public ArkUINode, public EventBus::EventHandler<SpringScrollViewEvent> {
@@ -143,6 +144,8 @@ class SpringScrollViewNode : public ArkUINode, public EventBus::EventHandler<Spr
143144
bool recordKeyBoardShow = false;
144145
std::chrono::high_resolution_clock::time_point keyboardHideLastTime;
145146
const int DISMINATE_KEYBOARD_SHOW_HIDE = 99999;
147+
const int BEGIN_REFRESH = 10000;
148+
bool scrollBeginDrag = false;
146149
bool cancelAllAnimations();
147150
void onMove(ArkUI_GestureEvent *evt);
148151
void onDown(ArkUI_GestureEvent *evt);
@@ -181,5 +184,7 @@ class SpringScrollViewNode : public ArkUINode, public EventBus::EventHandler<Spr
181184
void beginInnerAnimation(float initialVelocity);
182185
void beginReboundAnimation();
183186
void beginHorizontalReboundAnimation();
187+
void beginRefresh();
188+
void setRecordEventModel();
184189
};
185190
} // namespace rnoh

src/SpringScrollView.js

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import {
2121
ViewStyle,
2222
ScrollView
2323
} from "react-native";
24-
import * as TextInputState from "react-native/lib/TextInputState";
2524
import { FooterStatus } from "./LoadingFooter";
2625
import { NormalHeader } from "./NormalHeader";
2726
import { NormalFooter } from "./NormalFooter";
@@ -48,6 +47,7 @@ export class SpringScrollView extends React.PureComponent<SpringScrollViewPropTy
4847
_loadingStatus: FooterStatus = "waiting";
4948
_indicatorAnimation;
5049
_nativeOffset;
50+
_contentOffset: Offset = { x: 0, y: 0 };
5151

5252
constructor(props: SpringScrollViewPropType) {
5353
super(props);
@@ -112,6 +112,7 @@ export class SpringScrollView extends React.PureComponent<SpringScrollViewPropTy
112112
onLayout={this._onWrapperLayoutChange}
113113
onTouchBegin={(Platform.OS === "android" || Platform.OS === "harmony") && this._onTouchBegin}
114114
onTouchStart={Platform.OS === "ios" && this._onTouchBegin}
115+
onScrollBeginDrag={this._onScrollBeginDrag}
115116
onMomentumScrollEnd={this._onMomentumScrollEnd}
116117
scrollEventThrottle={1}
117118
onNativeContentOffsetExtract={this._nativeOffset}
@@ -285,9 +286,6 @@ export class SpringScrollView extends React.PureComponent<SpringScrollViewPropTy
285286
input.current.measure((x, y, w, h, l, t) => {
286287
this._keyboardHeight = t + h - evt.endCoordinates.screenY + this.props.inputToolBarHeight;
287288
if (Platform.OS === "harmony"){
288-
if(this._keyboardHeight > 450){
289-
this._keyboardHeight = this._keyboardHeight - 50;
290-
}
291289
this._keyboardHeight > 0 && this.scroll({ x: 99999, y: this._keyboardHeight });
292290
}
293291
else {
@@ -330,6 +328,7 @@ export class SpringScrollView extends React.PureComponent<SpringScrollViewPropTy
330328
}
331329

332330
_onScroll = e => {
331+
this._contentOffset = { x, y };
333332
const {
334333
contentOffset: { x, y },
335334
refreshStatus,
@@ -516,8 +515,6 @@ export class SpringScrollView extends React.PureComponent<SpringScrollViewPropTy
516515
};
517516

518517
_onTouchBegin = () => {
519-
if (TextInputState.currentlyFocusedField())
520-
TextInputState.blurTextInput(TextInputState.currentlyFocusedField());
521518
this.props.tapToHideKeyboard && Keyboard.dismiss();
522519
this.props.onTouchBegin && this.props.onTouchBegin();
523520
};
@@ -527,6 +524,22 @@ export class SpringScrollView extends React.PureComponent<SpringScrollViewPropTy
527524
this.props.onMomentumScrollEnd && this.props.onMomentumScrollEnd();
528525
};
529526

527+
_onScrollBeginDrag = () => {
528+
if (this.props.dragToHideKeyboard) Keyboard.dismiss();
529+
this.props.onScrollBeginDrag && this.props.onScrollBeginDrag();
530+
};
531+
532+
beginRefresh() {
533+
if (!this.props.loadingFooter || this.props.loadingFooter.height <= 0)
534+
return Promise.reject(
535+
"SpringScrollView: call beginRefresh without loadingFooter or loadingFooter height"
536+
);
537+
return this.scrollTo({
538+
x: 10000,
539+
y: -this.props.loadingFooter.height - 1,
540+
});
541+
}
542+
530543
static defaultProps = {
531544
bounces: true,
532545
scrollEnabled: true,
@@ -535,6 +548,7 @@ export class SpringScrollView extends React.PureComponent<SpringScrollViewPropTy
535548
textInputRefs: [],
536549
inputToolBarHeight: 44,
537550
tapToHideKeyboard: true,
551+
dragToHideKeyboard: true,
538552
initOffset: { x: 0, y: 0 },
539553
keyboardShouldPersistTaps: "always",
540554
showsVerticalScrollIndicator: true,

src/Types.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ export interface Offset {
2121
y: number
2222
}
2323

24+
export interface Size {
25+
width: number,
26+
height: number
27+
}
28+
2429
export interface NativeContentOffset {
2530
x?: Animated.Value,
2631
y?: Animated.Value
@@ -56,6 +61,9 @@ export interface SpringScrollViewPropType extends ViewProps {
5661
textInputRefs?: any[],
5762
inputToolBarHeight?: number,
5863
tapToHideKeyboard?: boolean,
64+
pagingEnabled?: boolean,
65+
pageSize?: Size,
66+
dragToHideKeyboard?: boolean,
5967
onTouchBegin?: () => any,
6068
onTouchEnd?: () => any,
6169
onTouchFinish?: () => any,
@@ -66,5 +74,6 @@ export interface SpringScrollViewPropType extends ViewProps {
6674
keyboardShouldPersistTaps?: "always"|"never"|"handled",
6775
onNativeContentOffsetExtract?: NativeContentOffset,
6876
onSizeChange?: ({ width: number, height: number }) => any,
69-
onContentSizeChange?: ({ width: number, height: number }) => any
77+
onContentSizeChange?: ({ width: number, height: number }) => any,
78+
onScrollBeginDrag?: () => any
7079
}

src/index.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,9 @@ declare module "react-native-spring-scrollview" {
103103
textInputRefs?: any[];
104104
inputToolBarHeight?: number;
105105
tapToHideKeyboard?: boolean;
106+
pagingEnabled?: boolean;
107+
pageSize?: Size;
108+
dragToHideKeyboard?: boolean;
106109
onTouchBegin?: () => any;
107110
onTouchEnd?: () => any;
108111
onTouchFinish?: () => any;
@@ -113,6 +116,7 @@ declare module "react-native-spring-scrollview" {
113116
onNativeContentOffsetExtract?: NativeContentOffset;
114117
onSizeChange?: (size:Size) => any;
115118
onContentSizeChange?: (size: Size) => any;
119+
onScrollBeginDrag?: () => any;
116120
}
117121
export class SpringScrollView extends React.PureComponent<SpringScrollViewPropType> {
118122
scrollTo(offset: Offset, animated?: boolean): Promise<void>;
@@ -121,5 +125,6 @@ declare module "react-native-spring-scrollview" {
121125
scrollToEnd(animated?: boolean): Promise<void>;
122126
endRefresh(): void;
123127
endLoading(): void;
128+
beginRefresh(): Promise<any>;
124129
}
125130
}

0 commit comments

Comments
 (0)