Fabric: ScrollView events

Summary: Note: Some features are not suported yet, e.g. event throttling.

Reviewed By: fkgozali

Differential Revision: D8082771

fbshipit-source-id: d60f6e9011283aeee7aff77dc9178e99f06deb5c
This commit is contained in:
Valentin Shergin 2018-05-22 15:48:27 -07:00 committed by Facebook Github Bot
parent 20645681d1
commit 21189be7cb
6 changed files with 188 additions and 4 deletions

View File

@ -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"
@ -44,6 +45,8 @@ using namespace facebook::react;
return self;
}
#pragma mark - ComponentViewProtocol
- (void)updateProps:(SharedProps)props oldProps:(SharedProps)oldProps
{
[super updateProps:props oldProps:oldProps];
@ -104,8 +107,6 @@ using namespace facebook::react;
_scrollView.contentSize = contentSize;
}
#pragma mark - ComponentViewProtocol
- (void)mountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView
index:(NSInteger)index
{
@ -119,4 +120,62 @@ using namespace facebook::react;
[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

View File

@ -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};
}
@ -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};
}

View File

@ -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

View File

@ -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

View File

@ -33,7 +33,7 @@ void ScrollViewShadowNode::updateLocalData() {
#pragma mark - LayoutableShadowNode
void ScrollViewShadowNode::layout(LayoutContext layoutContext) {
ConcreteViewShadowNode<ScrollViewProps>::layout(layoutContext);
ConcreteViewShadowNode::layout(layoutContext);
updateLocalData();
}

View File

@ -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>
@ -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: