hoaphantn7604 / react-native-element-dropdown

A react-native dropdown component easy to customize for both iOS and Android.
MIT License
993 stars 173 forks source link

isTablet in const "isFull" is not getting real value in the physical samsung tab6 #115

Open thaynarbo opened 2 years ago

thaynarbo commented 2 years ago

We were experiencing a bug in our app that we couldn't simulate in the android studio emulator. After a lot of time trying to understand the reasons that we couldn't simulate what tue QA analyst was showing on the physical device, we found that the

useDetectDevice returns a wrong isTablet value for the input, therefore the alignment was completely different in the physical device. We searched a bit deeper and found out that some android widths and heights from Dimensions are not accurate.

To solve the issue we applied a local patch

` import { Platform, Dimensions } from 'react-native'; import type { IUseDetectDevice } from './model';

const msp = (dim, limit) => { return (dim.scale dim.width) >= limit || (dim.scale dim.height) >= limit; };

const isTablet = () => { const dim = Dimensions.get('screen'); return ((dim.scale < 2 && msp(dim, 1000)) || (dim.scale >= 2 && msp(dim, 1900))); };

const useDetectDevice: IUseDetectDevice = { isAndroid: Platform.OS === 'android', isIOS: Platform.OS === 'ios', isTablet: isTablet(), };

export { useDetectDevice }; `

by changing to it, the problem was solved. Another way that we could solve the problem is to be able to send a property down to the Dropdown and instead of checking const isFull = orientation === 'LANDSCAPE' && !isTablet; We could do const isFull = orientation === 'LANDSCAPE' && ( !customProp || !isTablet);

Is there a way this could be fixed? We don't want to use a local fix.

pictures of the problem happening:

image

after changing isTablet function the result image

hoaphantn7604 commented 2 years ago

hi @thaynarbo , What is your simulator device name?

thaynarbo commented 2 years ago

Well, I couldn’t reproduce the problem on the emulator. I've used the samsung remote lab, to be able to simulate the BUG the tester has found in the real device.

In case you try using the Samsung remote lab, please make use of Tab S6, android 12.

Unfortunately, there is no pre-built device on android studio and creating a new one with the same specification as a tab S6 real device works fine. The problem occurs exclusively on real/physical devices.

jeandiego commented 2 years ago

Hi @hoaphantn7604,

One point to mention is that the problem only occurs in release mode. If we build app on debug, works fine.

hoaphantn7604 commented 1 year ago

Hi @hoaphantn7604,

One point to mention is that the problem only occurs in release mode. If we build app on debug, works fine.

Hi @jeandiego I'm working on it.

hoaphantn7604 commented 1 year ago

hi @jeandiego @thaynarbo , I have updated function "isTablet" in release 2.4.0. Not sure is it working. Can you help me re-check issue?

thaynarbo commented 1 year ago

Hello there, sorry for the delay. It didn't work :(

It's still considering it not to be a tablet I guess.

Is there a chance the code below could be implemented? Our patch worked with it. In many emulators as well as in the physical device.

const isTablet = () => { const dim = Dimensions.get('screen'); return ((dim.scale < 2 && msp(dim, 1000)) || (dim.scale >= 2 && msp(dim, 1900))); };

image

hoaphantn7604 commented 1 year ago

hi @thaynarbo , I tried your patch but it doesn't work on some devices.

thaynarbo commented 1 year ago

Isn't it possible to receive as a prop to the dropdown component an optional customIsTablet? That would help us because we use the react-device-info lib to specify when to render a specific component. If we happen to have

const isFull = orientation === 'LANDSCAPE' && ( !customIsTablet|| !isTablet);

We could pass it down to the component and it may work properly.

JJSLIoT commented 1 year ago

Can confirm, suggestions provided by @thaynarbo do work! I was facing the exact issue on Landscape mode with Statusbar = hidden on iOS.

JJSLIoT commented 1 year ago

This issue is not tablet specific, the expanded dropdown container position does not respect the position of the dropdown input field while in landscape mode on a phone(not a tablet).

JJSLIoT commented 1 year ago

I made a patch file react-native-element-dropdown+2.8.0.patch to fix this issue:

diff --git a/node_modules/react-native-element-dropdown/lib/typescript/components/Dropdown/model.d.ts b/node_modules/react-native-element-dropdown/lib/typescript/components/Dropdown/model.d.ts
index 785b399..0a51b53 100644
--- a/node_modules/react-native-element-dropdown/lib/typescript/components/Dropdown/model.d.ts
+++ b/node_modules/react-native-element-dropdown/lib/typescript/components/Dropdown/model.d.ts
@@ -47,4 +47,5 @@ export type DropdownProps = {
     searchQuery?: (keyword: string, labelValue: string) => boolean;
     onChangeText?: (search: string) => void;
     onConfirmSelectItem?: (item: any) => void;
+    isLandscapeMode?: boolean;
 };
diff --git a/node_modules/react-native-element-dropdown/src/components/Dropdown/index.tsx b/node_modules/react-native-element-dropdown/src/components/Dropdown/index.tsx
index adb9267..8ba28ba 100644
--- a/node_modules/react-native-element-dropdown/src/components/Dropdown/index.tsx
+++ b/node_modules/react-native-element-dropdown/src/components/Dropdown/index.tsx
@@ -86,6 +86,7 @@ const DropdownComponent = React.forwardRef<any, DropdownProps>(
       onConfirmSelectItem,
       accessibilityLabel,
       itemAccessibilityLabelField,
+      isLandscapeMode,
     } = props;

     const ref = useRef<View>(null);
@@ -156,7 +157,7 @@ const DropdownComponent = React.forwardRef<any, DropdownProps>(
     const _measure = useCallback(() => {
       if (ref && ref?.current) {
         ref.current.measure((_width, _height, px, py, fx, fy) => {
-          const isFull = orientation === 'LANDSCAPE' && !isTablet;
+          const isFull = orientation === 'LANDSCAPE' && !(isTablet || isLandscapeMode);
           const w = Math.floor(px);
           const top = isFull ? 20 : Math.floor(py) + Math.floor(fy) + 2;
           const bottom = H - top;
@@ -556,8 +557,8 @@ const DropdownComponent = React.forwardRef<any, DropdownProps>(
             dropdownPosition === 'auto'
               ? bottom < (isIOS ? 200 : search ? 310 : 300)
               : dropdownPosition === 'top'
-              ? true
-              : false;
+                ? true
+                : false;
           let topHeight = isTopPosition ? top - height : top;

           let keyboardStyle: ViewStyle = {};
diff --git a/node_modules/react-native-element-dropdown/src/components/Dropdown/model.ts b/node_modules/react-native-element-dropdown/src/components/Dropdown/model.ts
index 21362a7..940026b 100644
--- a/node_modules/react-native-element-dropdown/src/components/Dropdown/model.ts
+++ b/node_modules/react-native-element-dropdown/src/components/Dropdown/model.ts
@@ -61,4 +61,5 @@ export type DropdownProps = {
   searchQuery?: (keyword: string, labelValue: string) => boolean;
   onChangeText?: (search: string) => void;
   onConfirmSelectItem?: (item: any) => void;
+  isLandscapeMode?: boolean;
 };

And then use the Dropdown like this:

<Dropdown
  ...
  ...
  isLandscapeMode={orientation === "LANDSCAPE"} // Pass true if in landscape mode

@hoaphantn7604 similarly, we can add isLandscapeMode key into the props of multi select dropdown as well. Hopefully, we can get a new version of this module soon, with this fix integrated into it.