Skip to content

Commit

Permalink
Fabric: ScrollView events
Browse files Browse the repository at this point in the history
Summary: Note: Some features are not suported yet, e.g. event throttling.

Reviewed By: fkgozali

Differential Revision: D8082771

fbshipit-source-id: d60f6e9011283aeee7aff77dc9178e99f06deb5c
  • Loading branch information
shergin authored and facebook-github-bot committed May 22, 2018
1 parent 2064568 commit 21189be
Show file tree
Hide file tree
Showing 6 changed files with 188 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#import <fabric/graphics/Geometry.h>
#import <fabric/scrollview/ScrollViewLocalData.h>
#import <fabric/scrollview/ScrollViewProps.h>
#import <fabric/scrollview/ScrollViewEventHandlers.h>

#import "RCTConversions.h"
#import "RCTEnhancedScrollView.h"
Expand Down Expand Up @@ -44,6 +45,8 @@ - (instancetype)initWithFrame:(CGRect)frame
return self;
}

#pragma mark - ComponentViewProtocol

- (void)updateProps:(SharedProps)props oldProps:(SharedProps)oldProps
{
[super updateProps:props oldProps:oldProps];
Expand Down Expand Up @@ -104,8 +107,6 @@ - (void)updateLocalData:(SharedLocalData)localData
_scrollView.contentSize = contentSize;
}

#pragma mark - ComponentViewProtocol

- (void)mountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView
index:(NSInteger)index
{
Expand All @@ -119,4 +120,62 @@ - (void)unmountChildComponentView:(UIView<RCTComponentViewProtocol> *)childCompo
[childComponentView removeFromSuperview];
}

- (ScrollViewMetrics)_scrollViewMetrics
{
ScrollViewMetrics metrics;
metrics.contentSize = RCTSizeFromCGSize(_scrollView.contentSize);
metrics.contentOffset = RCTPointFromCGPoint(_scrollView.contentOffset);
metrics.contentInset = RCTEdgeInsetsFromUIEdgeInsets(_scrollView.contentInset);
metrics.containerSize = RCTSizeFromCGSize(_scrollView.bounds.size);
metrics.zoomScale = _scrollView.zoomScale;
return metrics;
}

#pragma mark - UIScrollViewDelegate

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
std::static_pointer_cast<const ScrollViewEventHandlers>(_eventHandlers)->onScroll([self _scrollViewMetrics]);
}

- (void)scrollViewDidZoom:(UIScrollView *)scrollView
{
std::static_pointer_cast<const ScrollViewEventHandlers>(_eventHandlers)->onScroll([self _scrollViewMetrics]);
}

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
std::static_pointer_cast<const ScrollViewEventHandlers>(_eventHandlers)->onScrollBeginDrag([self _scrollViewMetrics]);
}

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
{
std::static_pointer_cast<const ScrollViewEventHandlers>(_eventHandlers)->onScrollEndDrag([self _scrollViewMetrics]);
}

- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView
{
std::static_pointer_cast<const ScrollViewEventHandlers>(_eventHandlers)->onMomentumScrollBegin([self _scrollViewMetrics]);
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
std::static_pointer_cast<const ScrollViewEventHandlers>(_eventHandlers)->onMomentumScrollEnd([self _scrollViewMetrics]);
}

- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
{
std::static_pointer_cast<const ScrollViewEventHandlers>(_eventHandlers)->onMomentumScrollEnd([self _scrollViewMetrics]);
}

- (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(nullable UIView *)view
{
std::static_pointer_cast<const ScrollViewEventHandlers>(_eventHandlers)->onScrollBeginDrag([self _scrollViewMetrics]);
}

- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(nullable UIView *)view atScale:(CGFloat)scale
{
std::static_pointer_cast<const ScrollViewEventHandlers>(_eventHandlers)->onScrollEndDrag([self _scrollViewMetrics]);
}

@end
8 changes: 8 additions & 0 deletions React/Fabric/RCTConversions.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ inline CGRect RCTCGRectFromRect(facebook::react::Rect rect) {
return {RCTCGPointFromPoint(rect.origin), RCTCGSizeFromSize(rect.size)};
}

inline UIEdgeInsets RCTUIEdgeInsetsFromEdgeInsets(facebook::react::EdgeInsets edgeInsets) {
return {edgeInsets.top, edgeInsets.left, edgeInsets.bottom, edgeInsets.right};
}

inline facebook::react::Point RCTPointFromCGPoint(CGPoint point) {
return {point.x, point.y};
}
Expand All @@ -32,3 +36,7 @@ inline facebook::react::Size RCTSizeFromCGSize(CGSize size) {
inline facebook::react::Rect RCTRectFromCGRect(CGRect rect) {
return {RCTPointFromCGPoint(rect.origin), RCTSizeFromCGSize(rect.size)};
}

inline facebook::react::EdgeInsets RCTEdgeInsetsFromUIEdgeInsets(UIEdgeInsets edgeInsets) {
return {edgeInsets.top, edgeInsets.left, edgeInsets.bottom, edgeInsets.right};
}
64 changes: 64 additions & 0 deletions ReactCommon/fabric/scrollview/ScrollViewEventHandlers.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#include "ScrollViewEventHandlers.h"

namespace facebook {
namespace react {

void ScrollViewEventHandlers::onScroll(const ScrollViewMetrics &scrollViewMetrics) const {
dispatchScrollViewEvent("scroll", scrollViewMetrics);
}

void ScrollViewEventHandlers::onScrollBeginDrag(const ScrollViewMetrics &scrollViewMetrics) const {
dispatchScrollViewEvent("scrollBeginDrag", scrollViewMetrics);
}

void ScrollViewEventHandlers::onScrollEndDrag(const ScrollViewMetrics &scrollViewMetrics) const {
dispatchScrollViewEvent("scrollEndDrag", scrollViewMetrics);
}

void ScrollViewEventHandlers::onMomentumScrollBegin(const ScrollViewMetrics &scrollViewMetrics) const {
dispatchScrollViewEvent("momentumScrollBegin", scrollViewMetrics);
}

void ScrollViewEventHandlers::onMomentumScrollEnd(const ScrollViewMetrics &scrollViewMetrics) const {
dispatchScrollViewEvent("momentumScrollEnd", scrollViewMetrics);
}

void ScrollViewEventHandlers::dispatchScrollViewEvent(const std::string &name, const ScrollViewMetrics &scrollViewMetrics, const folly::dynamic &payload) const {
folly::dynamic compoundPayload = folly::dynamic::object();

compoundPayload["contentOffset"] = folly::dynamic::object
("x", scrollViewMetrics.contentOffset.x)
("y", scrollViewMetrics.contentOffset.y);

compoundPayload["contentInset"] = folly::dynamic::object
("top", scrollViewMetrics.contentInset.top)
("left", scrollViewMetrics.contentInset.left)
("bottom", scrollViewMetrics.contentInset.bottom)
("right", scrollViewMetrics.contentInset.right);

compoundPayload["contentSize"] = folly::dynamic::object
("width", scrollViewMetrics.contentSize.width)
("height", scrollViewMetrics.contentSize.height);

compoundPayload["layoutMeasurement"] = folly::dynamic::object
("width", scrollViewMetrics.containerSize.width)
("height", scrollViewMetrics.containerSize.height);

compoundPayload["zoomScale"] = scrollViewMetrics.zoomScale;

if (!payload.isNull()) {
compoundPayload.merge_patch(payload);
}

dispatchEvent(name, compoundPayload);
}

} // namespace react
} // namespace facebook
52 changes: 52 additions & 0 deletions ReactCommon/fabric/scrollview/ScrollViewEventHandlers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once

#include <memory>

#include <fabric/graphics/Geometry.h>
#include <fabric/core/EventHandlers.h>
#include <fabric/view/ViewEventHandlers.h>

#include <folly/dynamic.h>

namespace facebook {
namespace react {

class ScrollViewMetrics {
public:
Size contentSize;
Point contentOffset;
EdgeInsets contentInset;
Size containerSize;
Float zoomScale;
};

class ScrollViewEventHandlers;

using SharedScrollViewEventHandlers = std::shared_ptr<const ScrollViewEventHandlers>;

class ScrollViewEventHandlers:
public ViewEventHandlers {

public:

using ViewEventHandlers::ViewEventHandlers;

void onScroll(const ScrollViewMetrics &scrollViewMetrics) const;
void onScrollBeginDrag(const ScrollViewMetrics &scrollViewMetrics) const;
void onScrollEndDrag(const ScrollViewMetrics &scrollViewMetrics) const;
void onMomentumScrollBegin(const ScrollViewMetrics &scrollViewMetrics) const;
void onMomentumScrollEnd(const ScrollViewMetrics &scrollViewMetrics) const;

private:

void dispatchScrollViewEvent(const std::string &name, const ScrollViewMetrics &scrollViewMetrics, const folly::dynamic &payload = {}) const;
};

} // namespace react
} // namespace facebook
2 changes: 1 addition & 1 deletion ReactCommon/fabric/scrollview/ScrollViewShadowNode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ void ScrollViewShadowNode::updateLocalData() {
#pragma mark - LayoutableShadowNode

void ScrollViewShadowNode::layout(LayoutContext layoutContext) {
ConcreteViewShadowNode<ScrollViewProps>::layout(layoutContext);
ConcreteViewShadowNode::layout(layoutContext);
updateLocalData();
}

Expand Down
3 changes: 2 additions & 1 deletion ReactCommon/fabric/scrollview/ScrollViewShadowNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <memory>

#include <fabric/core/LayoutContext.h>
#include <fabric/scrollview/ScrollViewEventHandlers.h>
#include <fabric/scrollview/ScrollViewProps.h>
#include <fabric/view/ConcreteViewShadowNode.h>

Expand All @@ -24,7 +25,7 @@ using SharedScrollViewShadowNode = std::shared_ptr<const ScrollViewShadowNode>;
* `ShadowNode` for <ScrollView> component.
*/
class ScrollViewShadowNode final:
public ConcreteViewShadowNode<ScrollViewProps> {
public ConcreteViewShadowNode<ScrollViewProps, ScrollViewEventHandlers> {

public:

Expand Down

0 comments on commit 21189be

Please sign in to comment.