diff --git a/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.kt b/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.kt index 1e77408dfc..f0b61f95b6 100644 --- a/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.kt +++ b/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.kt @@ -20,6 +20,7 @@ import androidx.coordinatorlayout.widget.CoordinatorLayout import androidx.core.view.ViewCompat import androidx.core.view.WindowInsetsAnimationCompat import androidx.core.view.WindowInsetsCompat +import androidx.core.view.children import com.facebook.react.uimanager.PixelUtil import com.facebook.react.uimanager.UIManagerHelper import com.google.android.material.appbar.AppBarLayout @@ -412,32 +413,43 @@ class ScreenStackFragment : return super.onCreateOptionsMenu(menu, inflater) } - private fun shouldShowSearchBar(): Boolean { + private fun locateSearchBarSubviewInConfig(): ScreenStackHeaderSubview? { val config = screen.headerConfig val numberOfSubViews = config?.configSubviewsCount ?: 0 if (config != null && numberOfSubViews > 0) { for (i in 0 until numberOfSubViews) { val subView = config.getConfigSubview(i) if (subView.type == ScreenStackHeaderSubview.Type.SEARCH_BAR) { - return true + return subView } } } - return false + return null + } + + private fun extractShowAsActionFromSearchBar(searchSubview: ScreenStackHeaderSubview): Int { + for (child in searchSubview.children) { + if (child is SearchBarView) { + return child.showAsAction + } + } + + return MenuItem.SHOW_AS_ACTION_ALWAYS } private fun updateToolbarMenu(menu: Menu) { menu.clear() - if (shouldShowSearchBar()) { + locateSearchBarSubviewInConfig()?.let { val currentContext = context if (searchView == null && currentContext != null) { val newSearchView = CustomSearchView(currentContext, this) searchView = newSearchView onSearchViewCreate?.invoke(newSearchView) } - menu.add("").apply { - setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS) + menu.add("Search").apply { actionView = searchView + setIcon(R.drawable.ic_action_search) + setShowAsAction(extractShowAsActionFromSearchBar(it)) } } } diff --git a/android/src/main/java/com/swmansion/rnscreens/SearchBarManager.kt b/android/src/main/java/com/swmansion/rnscreens/SearchBarManager.kt index 8be7cd731d..cf1a504393 100644 --- a/android/src/main/java/com/swmansion/rnscreens/SearchBarManager.kt +++ b/android/src/main/java/com/swmansion/rnscreens/SearchBarManager.kt @@ -78,6 +78,14 @@ class SearchBarManager : view.shouldOverrideBackButton = disableBackButtonOverride != true } + @ReactProp(name = "searchShowAsAction") + override fun setShowAsAction( + view: SearchBarView, + showAsAction: String?, + ) { + view.setShowAsAction(showAsAction) + } + @ReactProp(name = "inputType") override fun setInputType( view: SearchBarView, diff --git a/android/src/main/java/com/swmansion/rnscreens/SearchBarView.kt b/android/src/main/java/com/swmansion/rnscreens/SearchBarView.kt index dd666ba099..70c0c6fda8 100644 --- a/android/src/main/java/com/swmansion/rnscreens/SearchBarView.kt +++ b/android/src/main/java/com/swmansion/rnscreens/SearchBarView.kt @@ -2,6 +2,7 @@ package com.swmansion.rnscreens import android.annotation.SuppressLint import android.text.InputType +import android.view.MenuItem import androidx.appcompat.widget.SearchView import com.facebook.react.bridge.ReactContext import com.facebook.react.uimanager.UIManagerHelper @@ -30,6 +31,17 @@ class SearchBarView( var autoFocus: Boolean = false var shouldShowHintSearchIcon: Boolean = true + var showAsAction: Int = MenuItem.SHOW_AS_ACTION_ALWAYS + private set + + fun setShowAsAction(actionView: String?) { + showAsAction = when (actionView) { + "collapse" -> MenuItem.SHOW_AS_ACTION_ALWAYS or MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW + "always" -> MenuItem.SHOW_AS_ACTION_ALWAYS + else -> MenuItem.SHOW_AS_ACTION_ALWAYS + } + } + private var searchViewFormatter: SearchViewFormatter? = null private var areListenersSet: Boolean = false diff --git a/android/src/main/res/base/drawable-anydpi/ic_action_search.xml b/android/src/main/res/base/drawable-anydpi/ic_action_search.xml new file mode 100644 index 0000000000..6796805c38 --- /dev/null +++ b/android/src/main/res/base/drawable-anydpi/ic_action_search.xml @@ -0,0 +1,11 @@ + + + diff --git a/android/src/main/res/base/drawable-hdpi/ic_action_search.png b/android/src/main/res/base/drawable-hdpi/ic_action_search.png new file mode 100644 index 0000000000..056f7f6270 Binary files /dev/null and b/android/src/main/res/base/drawable-hdpi/ic_action_search.png differ diff --git a/android/src/main/res/base/drawable-mdpi/ic_action_search.png b/android/src/main/res/base/drawable-mdpi/ic_action_search.png new file mode 100644 index 0000000000..ca8f4a7629 Binary files /dev/null and b/android/src/main/res/base/drawable-mdpi/ic_action_search.png differ diff --git a/android/src/main/res/base/drawable-xhdpi/ic_action_search.png b/android/src/main/res/base/drawable-xhdpi/ic_action_search.png new file mode 100644 index 0000000000..46183233ce Binary files /dev/null and b/android/src/main/res/base/drawable-xhdpi/ic_action_search.png differ diff --git a/android/src/main/res/base/drawable-xxhdpi/ic_action_search.png b/android/src/main/res/base/drawable-xxhdpi/ic_action_search.png new file mode 100644 index 0000000000..96d063da4e Binary files /dev/null and b/android/src/main/res/base/drawable-xxhdpi/ic_action_search.png differ diff --git a/android/src/paper/java/com/facebook/react/viewmanagers/RNSSearchBarManagerDelegate.java b/android/src/paper/java/com/facebook/react/viewmanagers/RNSSearchBarManagerDelegate.java index 9d07db9b60..d3b167da1d 100644 --- a/android/src/paper/java/com/facebook/react/viewmanagers/RNSSearchBarManagerDelegate.java +++ b/android/src/paper/java/com/facebook/react/viewmanagers/RNSSearchBarManagerDelegate.java @@ -57,6 +57,9 @@ public void setProperty(T view, String propName, @Nullable Object value) { case "disableBackButtonOverride": mViewManager.setDisableBackButtonOverride(view, value == null ? false : (boolean) value); break; + case "showAsAction": + mViewManager.setShowAsAction(view, (String) value); + break; case "inputType": mViewManager.setInputType(view, value == null ? null : (String) value); break; diff --git a/android/src/paper/java/com/facebook/react/viewmanagers/RNSSearchBarManagerInterface.java b/android/src/paper/java/com/facebook/react/viewmanagers/RNSSearchBarManagerInterface.java index 04cd889eb5..37f8b34b8e 100644 --- a/android/src/paper/java/com/facebook/react/viewmanagers/RNSSearchBarManagerInterface.java +++ b/android/src/paper/java/com/facebook/react/viewmanagers/RNSSearchBarManagerInterface.java @@ -25,6 +25,7 @@ public interface RNSSearchBarManagerInterface { void setTintColor(T view, @Nullable Integer value); void setTextColor(T view, @Nullable Integer value); void setDisableBackButtonOverride(T view, boolean value); + void setShowAsAction(T view, @Nullable String value); void setInputType(T view, @Nullable String value); void setHintTextColor(T view, @Nullable Integer value); void setHeaderIconColor(T view, @Nullable Integer value); diff --git a/apps/src/tests/Test2744.tsx b/apps/src/tests/Test2744.tsx new file mode 100644 index 0000000000..4d57cfa163 --- /dev/null +++ b/apps/src/tests/Test2744.tsx @@ -0,0 +1,67 @@ +import React from 'react'; +import { NavigationContainer, ParamListBase } from '@react-navigation/native'; +import { NativeStackNavigationProp, createNativeStackNavigator } from '@react-navigation/native-stack'; +import { Button, View, ScrollView } from 'react-native'; + +type StackRouteParamList = { + Home: undefined; + SearchAlways: undefined; + SearchCollapse: undefined; +}; + +type NavigationProp = { + navigation: NativeStackNavigationProp; +}; + +type StackNavigationProp = NavigationProp; + +const SearchAlways = ({navigation}: StackNavigationProp) => { + return +