akveo / react-native-ui-kitten

:boom: React Native UI Library based on Eva Design System :new_moon_with_face::sparkles:Dark Mode
https://akveo.github.io/react-native-ui-kitten/
MIT License
10.19k stars 952 forks source link

Modal is vibrating #1802

Open rklomp opened 4 months ago

rklomp commented 4 months ago

πŸ› Bug Report

My modal is vibrating horizontally by 1 pixel, similar to https://github.com/akveo/react-native-ui-kitten/issues/1681

In the modal component onContentMeasure code I added a log statement: console.log("onContentMeasure", contentFrame) In the bindToWindow of MeasureElement I added console.log("bindToWindow", frame,window)

This gives me

 LOG  bindToWindow {"origin": {"x": 41.904762268066406, "y": 172.1904754638672}, "size": {"height": 467.047607421875, "width": 327.6190490722656}} {"origin": {"x": 0, "y": 0}, "size": {"height": 812.5714285714286, "width": 411.42857142857144}}
 LOG  onContentMeasure {"origin": {"x": 41.904762268066406, "y": 172.1904754638672}, "size": {"height": 467.047607421875, "width": 327.6190490722656}}
 LOG  bindToWindow {"origin": {"x": 41.14285659790039, "y": 172.1904754638672}, "size": {"height": 467.047607421875, "width": 327.23809814453125}} {"origin": {"x": 0, "y": 0}, "size": {"height": 812.5714285714286, "width": 411.42857142857144}}
 LOG  onContentMeasure {"origin": {"x": 41.14285659790039, "y": 172.1904754638672}, "size": {"height": 467.047607421875, "width": 327.23809814453125}}
 LOG  bindToWindow {"origin": {"x": 41.904762268066406, "y": 172.1904754638672}, "size": {"height": 467.047607421875, "width": 327.6190490722656}} {"origin": {"x": 0, "y": 0}, "size": {"height": 812.5714285714286, "width": 411.42857142857144}}
 LOG  onContentMeasure {"origin": {"x": 41.904762268066406, "y": 172.1904754638672}, "size": {"height": 467.047607421875, "width": 327.6190490722656}}
 LOG  bindToWindow {"origin": {"x": 41.14285659790039, "y": 172.1904754638672}, "size": {"height": 467.047607421875, "width": 327.23809814453125}} {"origin": {"x": 0, "y": 0}, "size": {"height": 812.5714285714286, "width": 411.42857142857144}}
 LOG  onContentMeasure {"origin": {"x": 41.14285659790039, "y": 172.1904754638672}, "size": {"height": 467.047607421875, "width": 327.23809814453125}}
 LOG  bindToWindow {"origin": {"x": 41.904762268066406, "y": 172.1904754638672}, "size": {"height": 467.047607421875, "width": 327.6190490722656}} {"origin": {"x": 0, "y": 0}, "size": {"height": 812.5714285714286, "width": 411.42857142857144}}
 LOG  onContentMeasure {"origin": {"x": 41.904762268066406, "y": 172.1904754638672}, "size": {"height": 467.047607421875, "width": 327.6190490722656}}

It seems like UIManager is continuously looping between two values, but I cannot figure out why. It only happens in some cases, depending on the width of the content of the modal. Most of the times my modal is shown correctly. I've seen the same issue also with a modal vibrating vertically.

To Reproduce

I am not able to reproduce this in a snack yet, once I do I will update the issue.

Expected behavior

Link to runnable example or repository (highly encouraged)

UI Kitten and Eva version

Package Version
@eva-design/eva 2.2.0
@ui-kitten/components 5.3.1

Environment information

  System:
    OS: Windows 11 10.0.22631
    CPU: (16) x64 AMD Ryzen 7 5700G with Radeon Graphics
  Binaries:
    Node: 18.15.0 - C:\Program Files\nodejs\node.EXE
    Yarn: 1.22.21 - ~\AppData\Roaming\npm\yarn.CMD
    npm: 9.5.0 - C:\Program Files\nodejs\npm.CMD
  IDEs:
    Android Studio: AI-221.6008.13.2211.9619390
  npmPackages:
    react: 18.2.0 => 18.2.0 
    react-native: 0.73.2 => 0.73.2 
rklomp commented 4 months ago

I tried using Math.round() as in https://github.com/akveo/react-native-ui-kitten/pull/1790, but that did not work. However, using Math.floor() instead will remove the vibration.

As a workaround I now have this custom compontent:

import { Modal as KittenModal } from "@ui-kitten/components";
import { Frame } from "@ui-kitten/components/devsupport";

class Modal extends KittenModal {
    onContentMeasure = (contentFrame) => {
        contentFrame.size.height = Math.round(contentFrame.size.height);
        contentFrame.size.width = Math.floor(contentFrame.size.width);

        const displayFrame = contentFrame.centerOf(Frame.window());
        this.setState({ contentPosition: displayFrame.origin });
    };
}

export default Modal;

Edit: Came across a modal that did horizontal vibration. This was not solved using floor, but only using round. So using round for height and floor for width now. Not sure if that will cover all cases.