@Override protected void addEventEmitters(final ThemedReactContext reactContext, final ReactToolbar view) { final EventDispatcher mEventDispatcher = reactContext.getNativeModule(UIManagerModule.class) .getEventDispatcher(); view.setNavigationOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { mEventDispatcher.dispatchEvent( new ToolbarClickEvent(view.getId(), -1)); } }); view.setOnMenuItemClickListener( new ReactToolbar.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem menuItem) { mEventDispatcher.dispatchEvent( new ToolbarClickEvent( view.getId(), menuItem.getOrder())); return true; } }); }
private void dispatchCancelEvent(MotionEvent androidEvent, EventDispatcher eventDispatcher) { // This means the gesture has already ended, via some other CANCEL or UP event. This is not // expected to happen very often as it would mean some child View has decided to intercept the // touch stream and start a native gesture only upon receiving the UP/CANCEL event. if (mTargetTag == -1) { FLog.w( ReactConstants.TAG, "Can't cancel already finished gesture. Is a child View trying to start a gesture from " + "an UP/CANCEL event?"); return; } Assertions.assertCondition( !mChildIsHandlingNativeGesture, "Expected to not have already sent a cancel for this gesture"); Assertions.assertNotNull(eventDispatcher).dispatchEvent( TouchEvent.obtain( mTargetTag, TouchEventType.CANCEL, androidEvent, mGestureStartTime, mTargetCoordinates[0], mTargetCoordinates[1], mTouchEventCoalescingKeyHelper)); }
@Override protected void addEventEmitters(final ThemedReactContext reactContext, final ReactToolbar view) { final EventDispatcher mEventDispatcher = reactContext.getNativeModule(UIManagerModule.class) .getEventDispatcher(); view.setNavigationOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { mEventDispatcher.dispatchEvent( new ToolbarClickEvent(view.getId(), SystemClock.nanoTime(), -1)); } }); view.setOnMenuItemClickListener( new ReactToolbar.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem menuItem) { mEventDispatcher.dispatchEvent( new ToolbarClickEvent( view.getId(), SystemClock.nanoTime(), menuItem.getOrder())); return true; } }); }
/** * Invoked when native view that corresponds to a root node has its size changed. */ public void updateRootNodeSize( int rootViewTag, int newWidth, int newHeight, EventDispatcher eventDispatcher) { ReactShadowNode rootCSSNode = mShadowNodeRegistry.getNode(rootViewTag); rootCSSNode.setStyleWidth(newWidth); rootCSSNode.setStyleHeight(newHeight); // If we're in the middle of a batch, the change will automatically be dispatched at the end of // the batch. As all batches are executed as a single runnable on the event queue this should // always be empty, but that calling architecture is an implementation detail. if (mOperationsQueue.isEmpty()) { dispatchViewUpdates(eventDispatcher, -1); // -1 = no associated batch id } }
@Override public void onChildStartedNativeGesture(MotionEvent androidEvent) { if (mReactInstanceManager == null || !mIsAttachedToInstance || mReactInstanceManager.getCurrentReactContext() == null) { FLog.w( ReactConstants.TAG, "Unable to dispatch touch to JS as the catalyst instance has not been attached"); return; } ReactContext reactContext = mReactInstanceManager.getCurrentReactContext(); EventDispatcher eventDispatcher = reactContext.getNativeModule(UIManagerModule.class) .getEventDispatcher(); mJSTouchDispatcher.onChildStartedNativeGesture(androidEvent, eventDispatcher); // Hook for containers or fragments to get informed of the on touch events to perform actions. if (mOnGenericMotionListener != null) { mOnGenericMotionListener.onGenericMotion(this, androidEvent); } }
private void dispatchCancelEvent(MotionEvent androidEvent, EventDispatcher eventDispatcher) { // This means the gesture has already ended, via some other CANCEL or UP event. This is not // expected to happen very often as it would mean some child View has decided to intercept the // touch stream and start a native gesture only upon receiving the UP/CANCEL event. if (mTargetTag == -1) { FLog.w( ReactConstants.TAG, "Can't cancel already finished gesture. Is a child View trying to start a gesture from " + "an UP/CANCEL event?"); return; } Assertions.assertCondition( !mChildIsHandlingNativeGesture, "Expected to not have already sent a cancel for this gesture"); Assertions.assertNotNull(eventDispatcher).dispatchEvent( TouchEvent.obtain( mTargetTag, SystemClock.nanoTime(), TouchEventType.CANCEL, androidEvent, mTargetCoordinates[0], mTargetCoordinates[1])); }
private void onStateChange(GestureHandler handler, int newState, int oldState) { if (handler.getTag() < 0) { // root containers use negative tags, we don't need to dispatch events for them to the JS return; } HandlerFactory handlerFactory = findFactoryForHandler(handler); EventDispatcher eventDispatcher = getReactApplicationContext() .getNativeModule(UIManagerModule.class) .getEventDispatcher(); RNGestureHandlerStateChangeEvent event = RNGestureHandlerStateChangeEvent.obtain( handler, newState, oldState, handlerFactory); eventDispatcher.dispatchEvent(event); }
private void dispatchCancelEvent(MotionEvent androidEvent, EventDispatcher eventDispatcher) { // This means the gesture has already ended, via some other CANCEL or UP event. This is not // expected to happen very often as it would mean some child View has decided to intercept the // touch stream and start a native gesture only upon receiving the UP/CANCEL event. if (mTargetTag == -1) { FLog.w( ReactConstants.TAG, "Can't cancel already finished gesture. Is a child View trying to start a gesture from " + "an UP/CANCEL event?"); return; } Assertions.assertCondition( !mChildIsHandlingNativeGesture, "Expected to not have already sent a cancel for this gesture"); Assertions.assertNotNull(eventDispatcher).dispatchEvent( TouchEvent.obtain( mTargetTag, TouchEventType.CANCEL, androidEvent, mTargetCoordinates[0], mTargetCoordinates[1], mTouchEventCoalescingKeyHelper)); }
public static FlatUIImplementation createInstance( ReactApplicationContext reactContext, List<ViewManager> viewManagers, EventDispatcher eventDispatcher, boolean memoryImprovementEnabled) { RCTImageViewManager rctImageViewManager = findRCTImageManager(viewManagers); if (rctImageViewManager != null) { Object callerContext = rctImageViewManager.getCallerContext(); if (callerContext != null) { RCTImageView.setCallerContext(callerContext); } } DraweeRequestHelper.setResources(reactContext.getResources()); TypefaceCache.setAssetManager(reactContext.getAssets()); ViewManagerRegistry viewManagerRegistry = new ViewManagerRegistry(viewManagers); FlatNativeViewHierarchyManager nativeViewHierarchyManager = new FlatNativeViewHierarchyManager( viewManagerRegistry); FlatUIViewOperationQueue operationsQueue = new FlatUIViewOperationQueue( reactContext, nativeViewHierarchyManager); return new FlatUIImplementation( reactContext, rctImageViewManager, viewManagerRegistry, operationsQueue, eventDispatcher, memoryImprovementEnabled ); }
private FlatUIImplementation( ReactApplicationContext reactContext, @Nullable RCTImageViewManager rctImageViewManager, ViewManagerRegistry viewManagers, FlatUIViewOperationQueue operationsQueue, EventDispatcher eventDispatcher, boolean memoryImprovementEnabled) { super(reactContext, viewManagers, operationsQueue, eventDispatcher); mReactContext = reactContext; mRCTImageViewManager = rctImageViewManager; mStateBuilder = new StateBuilder(operationsQueue); mMemoryImprovementEnabled = memoryImprovementEnabled; }
@Override public FlatUIImplementation createUIImplementation( ReactApplicationContext reactContext, List<ViewManager> viewManagers, EventDispatcher eventDispatcher) { return FlatUIImplementation.createInstance( reactContext, viewManagers, eventDispatcher, mMemoryImprovementEnabled); }
/** * Run after the shadow node hierarchy is updated. Detaches all children from Views that are * changing their native children, updates views, and dispatches commands before discarding any * dropped views. * * @param eventDispatcher Dispatcher for onLayout events. */ void afterUpdateViewHierarchy(EventDispatcher eventDispatcher) { if (mDetachAllChildrenFromViews != null) { int[] viewsToDetachAllChildrenFrom = collectViewTags(mViewsToDetachAllChildrenFrom); mViewsToDetachAllChildrenFrom.clear(); mDetachAllChildrenFromViews.setViewsToDetachAllChildrenFrom(viewsToDetachAllChildrenFrom); mDetachAllChildrenFromViews = null; } for (int i = 0, size = mUpdateViewBoundsOperations.size(); i != size; ++i) { mOperationsQueue.enqueueFlatUIOperation(mUpdateViewBoundsOperations.get(i)); } mUpdateViewBoundsOperations.clear(); // Process view manager commands after bounds operations, so that any UI operations have already // happened before we actually dispatch the view manager command. This prevents things like // commands going to empty parents and views not yet being created. for (int i = 0, size = mViewManagerCommands.size(); i != size; i++) { mOperationsQueue.enqueueFlatUIOperation(mViewManagerCommands.get(i)); } mViewManagerCommands.clear(); // This could be more efficient if EventDispatcher had a batch mode // to avoid multiple synchronized calls. for (int i = 0, size = mOnLayoutEvents.size(); i != size; ++i) { eventDispatcher.dispatchEvent(mOnLayoutEvents.get(i)); } mOnLayoutEvents.clear(); if (mViewsToDrop.size() > 0) { mOperationsQueue.enqueueDropViews(mViewsToDrop, mParentsForViewsToDrop); mViewsToDrop.clear(); mParentsForViewsToDrop.clear(); } mOperationsQueue.enqueueProcessLayoutRequests(); }
public void setShouldNotifyLoadEvents(boolean shouldNotify) { if (!shouldNotify) { mControllerListener = null; } else { final EventDispatcher mEventDispatcher = ((ReactContext) getContext()). getNativeModule(UIManagerModule.class).getEventDispatcher(); mControllerListener = new BaseControllerListener<ImageInfo>() { @Override public void onSubmit(String id, Object callerContext) { mEventDispatcher.dispatchEvent( new ImageLoadEvent(getId(), ImageLoadEvent.ON_LOAD_START)); } @Override public void onFinalImageSet( String id, @Nullable final ImageInfo imageInfo, @Nullable Animatable animatable) { if (imageInfo != null) { mEventDispatcher.dispatchEvent( new ImageLoadEvent(getId(), ImageLoadEvent.ON_LOAD, mImageSource.getSource(), imageInfo.getWidth(), imageInfo.getHeight())); mEventDispatcher.dispatchEvent( new ImageLoadEvent(getId(), ImageLoadEvent.ON_LOAD_END)); } } @Override public void onFailure(String id, Throwable throwable) { mEventDispatcher.dispatchEvent( new ImageLoadEvent(getId(), ImageLoadEvent.ON_ERROR)); mEventDispatcher.dispatchEvent( new ImageLoadEvent(getId(), ImageLoadEvent.ON_LOAD_END)); } }; } mIsDirty = true; }
@Override public void onChildStartedNativeGesture(MotionEvent androidEvent) { if (mReactInstanceManager == null || !mIsAttachedToInstance || mReactInstanceManager.getCurrentReactContext() == null) { FLog.w( ReactConstants.TAG, "Unable to dispatch touch to JS as the catalyst instance has not been attached"); return; } ReactContext reactContext = mReactInstanceManager.getCurrentReactContext(); EventDispatcher eventDispatcher = reactContext.getNativeModule(UIManagerModule.class) .getEventDispatcher(); mJSTouchDispatcher.onChildStartedNativeGesture(androidEvent, eventDispatcher); }
private void dispatchJSTouchEvent(MotionEvent event) { if (mReactInstanceManager == null || !mIsAttachedToInstance || mReactInstanceManager.getCurrentReactContext() == null) { FLog.w( ReactConstants.TAG, "Unable to dispatch touch to JS as the catalyst instance has not been attached"); return; } ReactContext reactContext = mReactInstanceManager.getCurrentReactContext(); EventDispatcher eventDispatcher = reactContext.getNativeModule(UIManagerModule.class) .getEventDispatcher(); mJSTouchDispatcher.handleTouchEvent(event, eventDispatcher); }
private UIImplementation( ReactApplicationContext reactContext, ViewManagerRegistry viewManagers, EventDispatcher eventDispatcher) { this( reactContext, viewManagers, new UIViewOperationQueue(reactContext, new NativeViewHierarchyManager(viewManagers)), eventDispatcher); }
protected UIImplementation( ReactApplicationContext reactContext, ViewManagerRegistry viewManagers, UIViewOperationQueue operationsQueue, EventDispatcher eventDispatcher) { mReactContext = reactContext; mViewManagers = viewManagers; mOperationsQueue = operationsQueue; mNativeViewHierarchyOptimizer = new NativeViewHierarchyOptimizer( mOperationsQueue, mShadowNodeRegistry); mEventDispatcher = eventDispatcher; }
public void onChildStartedNativeGesture(MotionEvent androidEvent, EventDispatcher eventDispatcher) { if (mChildIsHandlingNativeGesture) { // This means we previously had another child start handling this native gesture and now a // different native parent of that child has decided to intercept the touch stream and handle // the gesture itself. Example where this can happen: HorizontalScrollView in a ScrollView. return; } dispatchCancelEvent(androidEvent, eventDispatcher); mChildIsHandlingNativeGesture = true; mTargetTag = -1; }
public UIManagerModule( ReactApplicationContext reactContext, List<ViewManager> viewManagerList, UIImplementationProvider uiImplementationProvider, boolean lazyViewManagersEnabled) { super(reactContext); DisplayMetricsHolder.initDisplayMetricsIfNotInitialized(reactContext); mEventDispatcher = new EventDispatcher(reactContext); mModuleConstants = createConstants(viewManagerList, lazyViewManagersEnabled); mUIImplementation = uiImplementationProvider .createUIImplementation(reactContext, viewManagerList, mEventDispatcher); reactContext.addLifecycleEventListener(this); }
@Before public void setUp() { mReactContext = new ReactApplicationContext(RuntimeEnvironment.application); mUIImplementationProvider = mock(UIImplementationProvider.class); when(mUIImplementationProvider.createUIImplementation( any(ReactApplicationContext.class), any(List.class), any(EventDispatcher.class))) .thenReturn(mock(UIImplementation.class)); }