Open ha3 opened 11 months ago
@kkafar hi. I created this patch, but not sure this is the correct approach–I'm quite inexperienced on the native side.
This solves the title and search bar being rendered on top of each other. But, in a real device, the search icon ends up aligned incorrectly to the left, if the search bar is blurred. On the emulator, everything works as expected.
diff --git a/node_modules/react-native-screens/android/src/main/java/com/swmansion/rnscreens/CustomSearchView.kt b/node_modules/react-native-screens/android/src/main/java/com/swmansion/rnscreens/CustomSearchView.kt
index 6984b10..17e23f0 100644
--- a/node_modules/react-native-screens/android/src/main/java/com/swmansion/rnscreens/CustomSearchView.kt
+++ b/node_modules/react-native-screens/android/src/main/java/com/swmansion/rnscreens/CustomSearchView.kt
@@ -4,6 +4,7 @@ import android.content.Context
import androidx.activity.OnBackPressedCallback
import androidx.appcompat.widget.SearchView
import androidx.fragment.app.Fragment
+import kotlin.collections.ArrayList
class CustomSearchView(context: Context, fragment: Fragment) : SearchView(context) {
/*
@@ -13,8 +14,9 @@ class CustomSearchView(context: Context, fragment: Fragment) : SearchView(contex
setOnSearchClickListener - https://developer.android.com/reference/android/widget/SearchView#setOnSearchClickListener(android.view.View.OnClickListener)
setOnCloseListener - https://developer.android.com/reference/android/widget/SearchView#setOnCloseListener(android.widget.SearchView.OnCloseListener)
*/
- private var mCustomOnCloseListener: OnCloseListener? = null
- private var mCustomOnSearchClickedListener: OnClickListener? = null
+
+ private var mCustomOnCloseListeners: MutableList<OnCloseListener> = ArrayList()
+ private var mCustomOnSearchClickedListeners: MutableList<OnClickListener> = ArrayList()
private var mOnBackPressedCallback: OnBackPressedCallback =
object : OnBackPressedCallback(true) {
@@ -40,12 +42,12 @@ class CustomSearchView(context: Context, fragment: Fragment) : SearchView(contex
fun setText(text: String) = setQuery(text, false)
- override fun setOnCloseListener(listener: OnCloseListener?) {
- mCustomOnCloseListener = listener
+ override fun setOnCloseListener(listener: OnCloseListener) {
+ mCustomOnCloseListeners.add(listener)
}
- override fun setOnSearchClickListener(listener: OnClickListener?) {
- mCustomOnSearchClickedListener = listener
+ override fun setOnSearchClickListener(listener: OnClickListener) {
+ mCustomOnSearchClickedListeners.add(listener)
}
override fun onAttachedToWindow() {
@@ -62,14 +64,14 @@ class CustomSearchView(context: Context, fragment: Fragment) : SearchView(contex
init {
super.setOnSearchClickListener { v ->
- mCustomOnSearchClickedListener?.onClick(v)
+ mCustomOnSearchClickedListeners.forEach { it.onClick(v) }
backPressOverrider.maybeAddBackCallback()
}
super.setOnCloseListener {
- val result = mCustomOnCloseListener?.onClose() ?: false
+ mCustomOnCloseListeners.forEach { it.onClose() }
backPressOverrider.removeBackCallbackIfAdded()
- result
+ false
}
maxWidth = Integer.MAX_VALUE
diff --git a/node_modules/react-native-screens/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.kt b/node_modules/react-native-screens/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.kt
index 86a7654..391ac4b 100644
--- a/node_modules/react-native-screens/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.kt
+++ b/node_modules/react-native-screens/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.kt
@@ -147,6 +147,25 @@ class ScreenStackFragment : ScreenFragment {
return false
}
+ private val subViewsToHideDuringSearch: MutableList<ScreenStackHeaderSubview>
+ get() {
+ val arr: MutableList<ScreenStackHeaderSubview> = ArrayList()
+
+ 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) {
+ arr.add(subView)
+ }
+ }
+ }
+
+ return arr
+ }
+
private fun updateToolbarMenu(menu: Menu) {
menu.clear()
if (shouldShowSearchBar()) {
@@ -154,6 +173,13 @@ class ScreenStackFragment : ScreenFragment {
if (searchView == null && currentContext != null) {
val newSearchView = CustomSearchView(currentContext, this)
searchView = newSearchView
+ newSearchView.setOnSearchClickListener {
+ subViewsToHideDuringSearch.forEach { it.visibility = View.GONE }
+ }
+ newSearchView.setOnCloseListener {
+ subViewsToHideDuringSearch.forEach { it.visibility = View.VISIBLE }
+ false
+ }
onSearchViewCreate?.invoke(newSearchView)
}
menu.add("").apply {
Exact problem i am facing, same with the headerRight icons, i cant seem to find a solid way, atm i got:
const navigation = useNavigation<TasksScreenNavigationProp<'index'>>();
const [search, setSearch] = React.useState('');
const [isSearching, setIsSearching] = React.useState(false);
const taskCount = 8381;
const searchBarRef = useRef<SearchBarCommands>(null);
useLayoutEffect(() => {
navigation.setOptions({
headerSearchBarOptions: {
autoCapitalize: 'none',
cancelButtonText: 'Annuleer',
placeholder: 'Zoeken',
shouldShowHintSearchIcon: false,
textColor: colors.white,
hintTextColor: colors.primary['300'],
tintColor: colors.white,
headerIconColor: colors.white,
onChangeText: event => setSearch(event.nativeEvent.text),
ref: searchBarRef,
onOpen: async () => {
setIsSearching(true);
},
onClose: async () => {
console.log('close');
setIsSearching(false);
},
},
headerTitle: props =>
!isSearching ? (
<HeaderTitle
style={{
marginLeft: Platform.OS === 'android' ? -20 : 0,
}}
{...props}>{`${taskCount} openstaande taken`}</HeaderTitle>
) : null,
headerRight: () =>
!isSearching ? (
<View
className={'h-full flex-row'}
style={{
gap: 10,
}}>
<Pressable hitSlop={7} className={'active:opacity-50'}>
<FontAwesomeIcon
color={'#fff'}
icon={['far', 'ellipsis-vertical']}
size={20}
/>
</Pressable>
<Pressable hitSlop={7} className={'active:opacity-50'}>
<FontAwesomeIcon
color={'#fff'}
icon={['far', 'filter']}
size={20}
/>
</Pressable>
</View>
) : null,
});
}, [isSearching, navigation]);
But this is causing a small flicker on open
@tboba thanks for the https://github.com/software-mansion/react-native-screens/pull/1903 which also addresses this issue. Changing the visibility of header elements, Instead of pushing them to the side, was my approach to the problem too. Unfortunately, with 3.27.0
I encountered the same problem that I had–the search icon is misaligned after the blur on certain Android devices, i.e. Xiaomi and Huawei.
On these devices, the search icon is pushed significantly to the left after the blur whether a custom header element is used or not. Here are some screenshots of the problem. It is tested on Xiaomi Redmi:
No custom element - Before focus:
No custom element - After blur:
Custom header left - Before focus:
Custom header left - After blur:
Hi, I've tested it with the latest version and could not reproduce the issue. I'll try again using Xiaomi/Huawei device in upcoming days. In the meantime, can anyone confirm that the problem still persists?
Description
In Android, when search bar is enabled along with a custom header title, they are rendered on top of each other. The problem persists after search bar is focused. It works correctly if a string is provided for the
headerTitle
.Steps to reproduce
Snack or a link to a repository
https://snack.expo.dev/@hozdemir/groaning-apples
Screens version
3.23.0
React Native version
0.72.3
Platforms
Android
JavaScript runtime
Hermes
Workflow
React Native (without Expo)
Architecture
Paper (Old Architecture)
Build type
Debug mode
Device
Real device
Device model
Redmi Note 7
Acknowledgements
Yes