diff --git a/apps/example/src/Screens/Article.tsx b/apps/example/src/Screens/Article.tsx index da3d5290..431d7820 100644 --- a/apps/example/src/Screens/Article.tsx +++ b/apps/example/src/Screens/Article.tsx @@ -53,6 +53,7 @@ export function Article({ console.log(Platform.OS, ' Rendering Article'); return ( console.log(layout)} ref={ref} style={{ backgroundColor: '#fff' }} contentContainerStyle={styles.content} diff --git a/packages/react-native-bottom-tabs/android/src/main/java/com/rcttabview/RCTTabView.kt b/packages/react-native-bottom-tabs/android/src/main/java/com/rcttabview/RCTTabView.kt index 4719d1d8..f3baa61f 100644 --- a/packages/react-native-bottom-tabs/android/src/main/java/com/rcttabview/RCTTabView.kt +++ b/packages/react-native-bottom-tabs/android/src/main/java/com/rcttabview/RCTTabView.kt @@ -12,6 +12,7 @@ import android.util.Log import android.util.Size import android.util.TypedValue import android.view.Choreographer +import android.view.Gravity import android.view.HapticFeedbackConstants import android.view.MenuItem import android.view.View @@ -72,16 +73,19 @@ class ReactBottomNavigationView(context: Context) : LinearLayout(context) { addView( layoutHolder, LayoutParams( - LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT, 0, - ).apply { weight = 1f } + ) + .apply { weight = 1f } ) layoutHolder.isSaveEnabled = false addView(bottomNavigation, LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT - )) + ).apply { + gravity = Gravity.BOTTOM + }) uiModeConfiguration = resources.configuration.uiMode post { @@ -142,9 +146,11 @@ class ReactBottomNavigationView(context: Context) : LinearLayout(context) { return } - val container = createContainer() - container.addView(child, params) - layoutHolder.addView(container, index) +// val container = createContainer() +// container.addView(child, params) + child.visibility = GONE + child.isEnabled = false + layoutHolder.addView(child, index) val itemKey = items[index].key if (selectedItem == itemKey) { @@ -153,18 +159,18 @@ class ReactBottomNavigationView(context: Context) : LinearLayout(context) { } } - private fun createContainer(): FrameLayout { - val container = FrameLayout(context).apply { - layoutParams = FrameLayout.LayoutParams( - FrameLayout.LayoutParams.MATCH_PARENT, - FrameLayout.LayoutParams.MATCH_PARENT - ) - isSaveEnabled = false - visibility = GONE - isEnabled = false - } - return container - } +// private fun createContainer(): FrameLayout { +// val container = FrameLayout(context).apply { +// layoutParams = FrameLayout.LayoutParams( +// FrameLayout.LayoutParams.MATCH_PARENT, +// FrameLayout.LayoutParams.MATCH_PARENT +// ) +// isSaveEnabled = false +// visibility = GONE +// isEnabled = false +// } +// return container +// } private fun setSelectedIndex(itemId: Int) { bottomNavigation.selectedItemId = itemId diff --git a/packages/react-native-bottom-tabs/android/src/main/java/com/rcttabview/RCTTabViewPackage.kt b/packages/react-native-bottom-tabs/android/src/main/java/com/rcttabview/RCTTabViewPackage.kt index 54492e1b..729eecf7 100644 --- a/packages/react-native-bottom-tabs/android/src/main/java/com/rcttabview/RCTTabViewPackage.kt +++ b/packages/react-native-bottom-tabs/android/src/main/java/com/rcttabview/RCTTabViewPackage.kt @@ -10,6 +10,7 @@ class RCTTabViewPackage : ReactPackage { override fun createViewManagers(reactContext: ReactApplicationContext): List> { val viewManagers: MutableList> = ArrayList() viewManagers.add(RCTTabViewManager(reactContext)) + viewManagers.add(RCTTabViewScreenManager(reactContext)) return viewManagers } diff --git a/packages/react-native-bottom-tabs/android/src/main/jni/CMakeLists.txt b/packages/react-native-bottom-tabs/android/src/main/jni/CMakeLists.txt new file mode 100644 index 00000000..71147d64 --- /dev/null +++ b/packages/react-native-bottom-tabs/android/src/main/jni/CMakeLists.txt @@ -0,0 +1,87 @@ +cmake_minimum_required(VERSION 3.13) +set(CMAKE_VERBOSE_MAKEFILE ON) + +set(LIB_LITERAL RNCTabView) +set(LIB_TARGET_NAME react_codegen_${LIB_LITERAL}) + +set(LIB_ANDROID_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../..) +set(LIB_COMMON_DIR ${LIB_ANDROID_DIR}/../common/cpp) +set(LIB_ANDROID_GENERATED_JNI_DIR ${LIB_ANDROID_DIR}/build/generated/source/codegen/jni) +set(LIB_ANDROID_GENERATED_COMPONENTS_DIR ${LIB_ANDROID_GENERATED_JNI_DIR}/react/renderer/components/${LIB_LITERAL}) + +add_compile_options( + -fexceptions + -frtti + -std=c++20 + -Wall + -Wpedantic + -Wno-gnu-zero-variadic-macro-arguments +) + +file(GLOB LIB_CUSTOM_SRCS CONFIGURE_DEPENDS *.cpp ${LIB_COMMON_DIR}/react/renderer/components/${LIB_LITERAL}/*.cpp) +file(GLOB LIB_CODEGEN_SRCS CONFIGURE_DEPENDS ${LIB_ANDROID_GENERATED_JNI_DIR}/*.cpp ${LIB_ANDROID_GENERATED_COMPONENTS_DIR}/*.cpp) + +add_library( + ${LIB_TARGET_NAME} + SHARED + ${LIB_CUSTOM_SRCS} + ${LIB_CODEGEN_SRCS} +) + +target_include_directories( + ${LIB_TARGET_NAME} + PUBLIC + . + ${LIB_COMMON_DIR} + ${LIB_ANDROID_GENERATED_JNI_DIR} + ${LIB_ANDROID_GENERATED_COMPONENTS_DIR} +) + +# https://github.com/react-native-community/discussions-and-proposals/discussions/816 +# This if-then-else can be removed once this library does not support version below 0.76 +if (REACTNATIVE_MERGED_SO) + target_link_libraries( + ${LIB_TARGET_NAME} + fbjni + jsi + reactnative + ) +else() + target_link_libraries( + ${LIB_TARGET_NAME} + fbjni + folly_runtime + glog + jsi + react_codegen_rncore + react_debug + react_render_componentregistry + react_render_core + react_render_debug + react_render_graphics + react_render_imagemanager + react_render_mapbuffer + react_utils + react_nativemodule_core + rrc_image + turbomodulejsijni + rrc_view + yoga + ) +endif() + +target_compile_options( + ${LIB_TARGET_NAME} + PRIVATE + -DLOG_TAG=\"ReactNative\" + -fexceptions + -frtti + -std=c++20 + -Wall +) + +target_include_directories( + ${CMAKE_PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR} +) diff --git a/packages/react-native-bottom-tabs/android/src/main/jni/RNCTabView.h b/packages/react-native-bottom-tabs/android/src/main/jni/RNCTabView.h new file mode 100644 index 00000000..9f7070bd --- /dev/null +++ b/packages/react-native-bottom-tabs/android/src/main/jni/RNCTabView.h @@ -0,0 +1,13 @@ +#pragma once + +#include +#include +#include +#include + +namespace facebook::react { +JSI_EXPORT +std::shared_ptr RNCTabView_ModuleProvider( + const std::string &moduleName, + const JavaTurboModule::InitParams ¶ms); +} diff --git a/packages/react-native-bottom-tabs/android/src/newarch/RCTTabViewManager.kt b/packages/react-native-bottom-tabs/android/src/newarch/RCTTabViewManager.kt index 5d919760..8dca9840 100644 --- a/packages/react-native-bottom-tabs/android/src/newarch/RCTTabViewManager.kt +++ b/packages/react-native-bottom-tabs/android/src/newarch/RCTTabViewManager.kt @@ -1,7 +1,9 @@ package com.rcttabview +import android.util.Log import android.view.View -import android.view.ViewGroup +import android.widget.FrameLayout +import androidx.core.view.children import com.facebook.react.bridge.ReactApplicationContext import com.facebook.react.bridge.ReadableArray import com.facebook.react.module.annotations.ReactModule @@ -11,7 +13,6 @@ import com.facebook.react.uimanager.ViewGroupManager import com.facebook.react.uimanager.ViewManagerDelegate import com.facebook.react.viewmanagers.RNCTabViewManagerDelegate import com.facebook.react.viewmanagers.RNCTabViewManagerInterface -import com.rcttabview.events.OnNativeLayoutEvent import com.rcttabview.events.PageSelectedEvent import com.rcttabview.events.TabLongPressEvent @@ -36,9 +37,21 @@ class RCTTabViewManager(context: ReactApplicationContext) : eventDispatcher?.dispatchEvent(TabLongPressEvent(viewTag = view.id, key)) } - view.onNativeLayoutListener = { width, height -> - eventDispatcher?.dispatchEvent(OnNativeLayoutEvent(viewTag = view.id, width, height)) - } +// view.onNativeLayoutListener = { width, height -> +// val childCount = tabViewImpl.getChildCount(view) +// for (i in 0 until childCount) { // Use 'until' instead of '..' to exclude childCount +// val child = tabViewImpl.getChildAt(view, i) +// +// // Safe cast for FrameLayout +// if (child is RCTTabViewScreen) { +// child.updateFrame(width, height) +// +// Log.w("TAB_VIEW", "CHILD: ${child}") +// } +// } +// +//// eventDispatcher?.dispatchEvent(OnNativeLayoutEvent(viewTag = view.id, width, height)) +// } return view } @@ -72,9 +85,9 @@ class RCTTabViewManager(context: ReactApplicationContext) : tabViewImpl.removeViewAt(parent, index) } - override fun needsCustomLayoutForChildren(): Boolean { - return tabViewImpl.needsCustomLayoutForChildren() - } +// override fun needsCustomLayoutForChildren(): Boolean { +// return tabViewImpl.needsCustomLayoutForChildren() +// } override fun setItems(view: ReactBottomNavigationView?, value: ReadableArray?) { if (view != null && value != null) diff --git a/packages/react-native-bottom-tabs/android/src/newarch/RCTTabViewScreenManager.kt b/packages/react-native-bottom-tabs/android/src/newarch/RCTTabViewScreenManager.kt new file mode 100644 index 00000000..cd8e53e5 --- /dev/null +++ b/packages/react-native-bottom-tabs/android/src/newarch/RCTTabViewScreenManager.kt @@ -0,0 +1,98 @@ +package com.rcttabview + +import android.content.Context +import android.os.Build +import android.util.Log +import android.view.View +import android.view.WindowInsets +import android.view.WindowManager +import android.widget.FrameLayout +import androidx.core.view.ViewCompat +import androidx.core.view.WindowInsetsCompat +import com.facebook.react.bridge.Arguments +import com.facebook.react.bridge.ReactApplicationContext +import com.facebook.react.module.annotations.ReactModule +import com.facebook.react.uimanager.ReactStylesDiffMap +import com.facebook.react.uimanager.StateWrapper +import com.facebook.react.uimanager.ThemedReactContext +import com.facebook.react.uimanager.ViewGroupManager +import com.facebook.react.uimanager.ViewManagerDelegate +import com.facebook.react.viewmanagers.RNCTabViewScreenManagerDelegate +import com.facebook.react.viewmanagers.RNCTabViewScreenManagerInterface +import com.facebook.react.views.view.ReactViewGroup + +class RCTTabViewScreen(context: Context): ReactViewGroup(context) { + private var stateWrapper: StateWrapper? = null + + public fun setStateWrapper(stateWrapper: StateWrapper?) { + this.stateWrapper = stateWrapper + } + + init { + getSystemInsets(this) { left, top, right, bottom -> + Log.w("TAB_VIEW", "${left} ${top} ${right} ${bottom}") + + stateWrapper?.updateState(Arguments.createMap().apply { + putDouble("width", Utils.convertPixelsToDp(context, width)) + putDouble("height", Utils.convertPixelsToDp(context, height - bottom)) + }) + } + } + + fun getSystemInsets(view: View, callback: (left: Int, top: Int, right: Int, bottom: Int) -> Unit) { + ViewCompat.setOnApplyWindowInsetsListener(view) { v, insets -> + val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()) + callback( + systemBars.left, // Left inset (for left-aligned Navigation Rail) + systemBars.top, // Top inset + systemBars.right, // Right inset (for right-aligned Navigation Rail) + systemBars.bottom // Bottom inset (for bottom navigation) + ) + insets + } + // Ensure we request insets + if (view.isAttachedToWindow) { + ViewCompat.requestApplyInsets(view) + } else { + view.addOnAttachStateChangeListener(object : View.OnAttachStateChangeListener { + override fun onViewAttachedToWindow(v: View) { + ViewCompat.requestApplyInsets(v) + v.removeOnAttachStateChangeListener(this) + } + override fun onViewDetachedFromWindow(v: View) = Unit + }) + } + } +} + + +@ReactModule(name = "RNCTabViewScreen") +class RCTTabViewScreenManager(context: ReactApplicationContext) : + ViewGroupManager(), + RNCTabViewScreenManagerInterface { + + private val delegate: RNCTabViewScreenManagerDelegate = + RNCTabViewScreenManagerDelegate(this) + + + override fun createViewInstance(context: ThemedReactContext): RCTTabViewScreen { + return RCTTabViewScreen(context); + } + + override fun updateState( + view: RCTTabViewScreen, + props: ReactStylesDiffMap?, + stateWrapper: StateWrapper? + ): Any? { + view.setStateWrapper(stateWrapper) + return super.updateState(view, props, stateWrapper) + } + + override fun getDelegate(): ViewManagerDelegate { + return delegate + } + + override fun getName(): String { + return "RNCTabViewScreen" + } +} diff --git a/packages/react-native-bottom-tabs/common/cpp/react/renderer/components/RNCTabView/RNCTabViewScreenComponentDescriptor.h b/packages/react-native-bottom-tabs/common/cpp/react/renderer/components/RNCTabView/RNCTabViewScreenComponentDescriptor.h new file mode 100644 index 00000000..1f94458e --- /dev/null +++ b/packages/react-native-bottom-tabs/common/cpp/react/renderer/components/RNCTabView/RNCTabViewScreenComponentDescriptor.h @@ -0,0 +1,33 @@ +#ifdef __cplusplus + +#pragma once + +#include +#include + +namespace facebook::react { + +class RNCTabViewScreenComponentDescriptor final : public ConcreteComponentDescriptor +{ +public: + RNCTabViewScreenComponentDescriptor(const ComponentDescriptorParameters ¶meters) + : ConcreteComponentDescriptor(parameters) {} + + + /** + Retrieve shadow node's state and update it's layout size accordingly. + This is needed because we need to accomodate for bottom bar / sidebar size. + */ + void adopt(ShadowNode &shadowNode) const override { + auto& layoutableShadowNode = static_cast(shadowNode); + auto& stateData = layoutableShadowNode.getStateData(); + + layoutableShadowNode.setSize(stateData.frameSize); + + ConcreteComponentDescriptor::adopt(shadowNode); + } +}; + +} + +#endif diff --git a/packages/react-native-bottom-tabs/common/cpp/react/renderer/components/RNCTabView/RNCTabViewScreenShadowNode.cpp b/packages/react-native-bottom-tabs/common/cpp/react/renderer/components/RNCTabView/RNCTabViewScreenShadowNode.cpp new file mode 100644 index 00000000..2134c247 --- /dev/null +++ b/packages/react-native-bottom-tabs/common/cpp/react/renderer/components/RNCTabView/RNCTabViewScreenShadowNode.cpp @@ -0,0 +1,7 @@ +#include "RNCTabViewScreenShadowNode.h" + +namespace facebook::react { + +extern const char RNCTabViewScreenComponentName[] = "RNCTabViewScreen"; + +} diff --git a/packages/react-native-bottom-tabs/common/cpp/react/renderer/components/RNCTabView/RNCTabViewScreenShadowNode.h b/packages/react-native-bottom-tabs/common/cpp/react/renderer/components/RNCTabView/RNCTabViewScreenShadowNode.h new file mode 100644 index 00000000..f9dfe13f --- /dev/null +++ b/packages/react-native-bottom-tabs/common/cpp/react/renderer/components/RNCTabView/RNCTabViewScreenShadowNode.h @@ -0,0 +1,32 @@ +#ifdef __cplusplus + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +namespace facebook::react { + +JSI_EXPORT extern const char RNCTabViewScreenComponentName[]; + +/* +* `ShadowNode` for component. +*/ +class JSI_EXPORT RNCTabViewScreenShadowNode final +: public ConcreteViewShadowNode< +RNCTabViewScreenComponentName, +RNCTabViewScreenProps, +RNCTabViewScreenEventEmitter, +RNCTabViewScreenState> +{ +public: + using ConcreteViewShadowNode::ConcreteViewShadowNode; +}; +} + +#endif diff --git a/packages/react-native-bottom-tabs/common/cpp/react/renderer/components/RNCTabView/RNCTabViewScreenState.h b/packages/react-native-bottom-tabs/common/cpp/react/renderer/components/RNCTabView/RNCTabViewScreenState.h new file mode 100644 index 00000000..5742ac94 --- /dev/null +++ b/packages/react-native-bottom-tabs/common/cpp/react/renderer/components/RNCTabView/RNCTabViewScreenState.h @@ -0,0 +1,30 @@ +#ifdef __cplusplus + +#pragma once +#include +#ifdef ANDROID +#include +#endif + +namespace facebook::react { + +class RNCTabViewScreenState +{ +public: + RNCTabViewScreenState() = default; + RNCTabViewScreenState(Size frameSize): frameSize(frameSize) {}; + + Size frameSize; + +#ifdef ANDROID + RNCTabViewScreenState(RNCTabViewScreenState const &previousState, folly::dynamic data) + : frameSize((Float)data["width"].getDouble(), (Float)data["height"].getDouble()) {}; + folly::dynamic getDynamic() const { + return {}; + }; +#endif +}; + +} + +#endif diff --git a/packages/react-native-bottom-tabs/ios/Fabric/RCTTabViewComponentView.mm b/packages/react-native-bottom-tabs/ios/Fabric/RCTTabViewComponentView.mm index 7d55de42..44d12fd8 100644 --- a/packages/react-native-bottom-tabs/ios/Fabric/RCTTabViewComponentView.mm +++ b/packages/react-native-bottom-tabs/ios/Fabric/RCTTabViewComponentView.mm @@ -1,5 +1,6 @@ #ifdef RCT_NEW_ARCH_ENABLED #import "RCTTabViewComponentView.h" +#import "RCTTabViewScreenComponentView.h" #import #import @@ -244,13 +245,24 @@ - (void)onTabBarMeasuredWithHeight:(NSInteger)height reactTag:(NSNumber *)reactT } } +- (size_t)getSelectedIndex +{ + const auto &props = *std::static_pointer_cast(_props); + + auto selectedItem = std::find_if(props.items.begin(), props.items.end(), + [&](const RNCTabViewItemsStruct &item) { + return item.key == props.selectedPage; + }); + + return std::distance(props.items.begin(), selectedItem); +} + - (void)onLayoutWithSize:(CGSize)size reactTag:(NSNumber *)reactTag { - auto eventEmitter = std::static_pointer_cast(_eventEmitter); - if (eventEmitter) { - eventEmitter->onNativeLayout(RNCTabViewEventEmitter::OnNativeLayout { - .height = size.height, - .width = size.width - }); + size_t selectedIndex = [self getSelectedIndex]; + + RCTTabViewScreenComponentView *child = (RCTTabViewScreenComponentView *)_reactSubviews[selectedIndex]; + if ([child respondsToSelector:@selector(updateFrameSize:)]) { + [child updateFrameSize:size]; } } diff --git a/packages/react-native-bottom-tabs/ios/Fabric/RCTTabViewScreenComponentView.h b/packages/react-native-bottom-tabs/ios/Fabric/RCTTabViewScreenComponentView.h new file mode 100644 index 00000000..a6374034 --- /dev/null +++ b/packages/react-native-bottom-tabs/ios/Fabric/RCTTabViewScreenComponentView.h @@ -0,0 +1,19 @@ +#ifdef RCT_NEW_ARCH_ENABLED +#import +#if TARGET_OS_OSX +#import +#else +#import +#endif + +NS_ASSUME_NONNULL_BEGIN + +@interface RCTTabViewScreenComponentView: RCTViewComponentView + +- (void)updateFrameSize:(CGSize)size; + +@end + +NS_ASSUME_NONNULL_END + +#endif /* RCT_NEW_ARCH_ENABLED */ diff --git a/packages/react-native-bottom-tabs/ios/Fabric/RCTTabViewScreenComponentView.mm b/packages/react-native-bottom-tabs/ios/Fabric/RCTTabViewScreenComponentView.mm new file mode 100644 index 00000000..d860f5d5 --- /dev/null +++ b/packages/react-native-bottom-tabs/ios/Fabric/RCTTabViewScreenComponentView.mm @@ -0,0 +1,63 @@ +#ifdef RCT_NEW_ARCH_ENABLED +#import "RCTTabViewScreenComponentView.h" + +#import +#import +#import +#import + +#import + +#if TARGET_OS_OSX +typedef NSView PlatformView; +#else +typedef UIView PlatformView; +#endif + + +using namespace facebook::react; + +@interface RCTTabViewScreenComponentView () { +} + +@end + +@implementation RCTTabViewScreenComponentView { + RNCTabViewScreenShadowNode::ConcreteState::Shared _state; +} + ++ (ComponentDescriptorProvider)componentDescriptorProvider +{ + return concreteComponentDescriptorProvider(); +} + +- (instancetype)initWithFrame:(CGRect)frame +{ + if (self = [super initWithFrame:frame]) { + static const auto defaultProps = std::make_shared(); + _props = defaultProps; + } + + return self; +} + +- (void)updateState:(const facebook::react::State::Shared &)state oldState:(const facebook::react::State::Shared &)oldState { + _state = std::static_pointer_cast(state); +} + +- (void)updateFrameSize:(CGSize)size +{ + _state->updateState(RNCTabViewScreenState({size.width, size.height})); +} + +@end + +Class RNCTabViewScreenCls(void) +{ + return RCTTabViewScreenComponentView.class; +} + +#endif // RCT_NEW_ARCH_ENABLED + + + diff --git a/packages/react-native-bottom-tabs/package.json b/packages/react-native-bottom-tabs/package.json index f5529e23..8e05a81d 100644 --- a/packages/react-native-bottom-tabs/package.json +++ b/packages/react-native-bottom-tabs/package.json @@ -24,6 +24,7 @@ "files": [ "src", "lib", + "common", "android", "ios", "cpp", @@ -126,7 +127,8 @@ }, "ios": { "componentProvider": { - "RNCTabView": "RCTTabViewComponentView" + "RNCTabView": "RCTTabViewComponentView", + "RNCTabViewScreen": "RCTTabViewScreenComponentView" } } } diff --git a/packages/react-native-bottom-tabs/react-native-bottom-tabs.podspec b/packages/react-native-bottom-tabs/react-native-bottom-tabs.podspec index d4b92897..03aa219f 100644 --- a/packages/react-native-bottom-tabs/react-native-bottom-tabs.podspec +++ b/packages/react-native-bottom-tabs/react-native-bottom-tabs.podspec @@ -1,6 +1,7 @@ require "json" package = JSON.parse(File.read(File.join(__dir__, "package.json"))) +new_arch_enabled = ENV['RCT_NEW_ARCH_ENABLED'] == '1' Pod::Spec.new do |s| s.name = "react-native-bottom-tabs" @@ -20,6 +21,13 @@ Pod::Spec.new do |s| s.source_files = "ios/**/*.{h,m,mm,cpp,swift}" s.static_framework = true + if new_arch_enabled + s.subspec "common" do |ss| + ss.source_files = "common/cpp/**/*.{cpp,h}" + ss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/common/cpp\"" } + end + end + s.dependency "SwiftUIIntrospect", '~> 1.0' s.dependency 'SDWebImage', '>= 5.19.1' s.dependency 'SDWebImageSVGCoder', '>= 1.7.0' diff --git a/packages/react-native-bottom-tabs/react-native.config.js b/packages/react-native-bottom-tabs/react-native.config.js new file mode 100644 index 00000000..ef6fcb2a --- /dev/null +++ b/packages/react-native-bottom-tabs/react-native.config.js @@ -0,0 +1,11 @@ +module.exports = { + dependency: { + platforms: { + android: { + libraryName: 'RNCTabView', + componentDescriptors: ['RNCTabViewScreenComponentDescriptor'], + cmakeListsPath: 'src/main/jni/CMakeLists.txt', + }, + }, + }, +}; diff --git a/packages/react-native-bottom-tabs/src/TabView.tsx b/packages/react-native-bottom-tabs/src/TabView.tsx index 616f0ac9..1bb70641 100644 --- a/packages/react-native-bottom-tabs/src/TabView.tsx +++ b/packages/react-native-bottom-tabs/src/TabView.tsx @@ -16,6 +16,7 @@ import NativeTabView from './TabViewNativeComponent'; import useLatestCallback from 'use-latest-callback'; import type { BaseRoute, NavigationState } from './types'; import DelayedFreeze from './DelayedFreeze'; +import TabViewScreenNativeComponent from './TabViewScreenNativeComponent'; const isAppleSymbol = (icon: any): icon is { sfSymbol: string } => icon?.sfSymbol; @@ -195,9 +196,6 @@ const TabView = ({ // @ts-ignore const focusedKey = navigationState.routes[navigationState.index].key; const [tabBarHeight, setTabBarHeight] = React.useState(0); - const [measuredDimensions, setMeasuredDimensions] = React.useState< - { width: number; height: number } | undefined - >(); const trimmedRoutes = React.useMemo(() => { if ( @@ -304,9 +302,6 @@ const TabView = ({ onTabBarMeasured={({ nativeEvent: { height } }) => { setTabBarHeight(height); }} - onNativeLayout={({ nativeEvent: { width, height } }) => { - setMeasuredDimensions({ width, height }); - }} hapticFeedbackEnabled={hapticFeedbackEnabled} activeTintColor={activeTintColor} inactiveTintColor={inactiveTintColor} @@ -330,13 +325,10 @@ const TabView = ({ const freeze = !focused ? getFreezeOnBlur({ route }) : false; return ( - ({ jumpTo, })} - + ); })} diff --git a/packages/react-native-bottom-tabs/src/TabViewScreenNativeComponent.ts b/packages/react-native-bottom-tabs/src/TabViewScreenNativeComponent.ts new file mode 100644 index 00000000..c6addc1e --- /dev/null +++ b/packages/react-native-bottom-tabs/src/TabViewScreenNativeComponent.ts @@ -0,0 +1,8 @@ +import type { ViewProps } from 'react-native'; +import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; + +export interface TabViewScreenProps extends ViewProps {} + +export default codegenNativeComponent('RNCTabViewScreen', { + interfaceOnly: true, +});