响应式React-native-web布局

3

我正在尝试从一个React Native项目中创建仪表板布局。想法是保持大部分代码与Android、iOS和Web相似,只有布局或导航样式会改变。但我发现在Web上制作这种布局很容易,但要使其具有响应性且不重新渲染非常困难。

我通过按照以下代码手动计算窗口的高度和宽度来实现此目标:

Dimensions.get('window').width Dimensions.get('window').height

通过事件监听器不断更新状态,以便它再次重复呈现整个页面。

Dimensions.addEventListener("change", this.updateScreen);

是否有一种方法可以简单地使用一些%值来填充屏幕?现在,如果我使用%,它会压缩到子“View”的大小。我甚至尝试过使用flex:1alignSelf:stretchalignItem:stretchwidth:'100%'等,但没有成功。

暂时,让我们谈论中心行(附带图像),它包含3列。我希望左右块(菜单和呼叫到行动)每个都是300像素。现在,如果我的显示器宽度为1000像素,我的内容块应该是(1000 - (300 + 300))400像素。如果显示器为1200px,则内容块将为(1200 - (300 + 300))600px。

enter image description here

2个回答

3

我希望这不会太晚。

  <View style={{ flex: 1 }}>
    <View style={{ height: 100, backgroundColor: 'red' }} />

    <View style={{ flex: 1, backgroundColor: 'gray', flexDirection: 'row' }}>
      <View style={{ width: 100, backgroundColor: 'green' }} />
      <View style={{ flex: 1, backgroundColor: 'blue' }} />
      <View style={{ width: 100, backgroundColor: 'green' }} />
    </View>

    <View style={{ height: 100, backgroundColor: 'red' }} />
  </View>

这是以上代码的结果。 result 您根本不需要进行百分比计算,只需将其结构化为2层flex布局。
对于不应该拉伸的组件,请声明它们的宽度。对于其他组件,请指定flex值。
如果您坚持使用1层来处理所有内容,则我们需要再讨论一下。
干杯。

0

我出于完全相同的原因制作了这个:

https://www.npmjs.com/package/react-native-animated-layout

演示:

Expo snack: https://snack.expo.dev/@mehmetkaplan/react-native-animated-layout

Web demo: https://mehmetkaplan.github.io/react-native-animated-layout/

它以布局作为输入,并使用屏幕的宽度/高度比来决定使用哪种布局。

在每个布局内,您可以使用位于0和1之间的坐标定义每个屏幕的顶部、右侧、底部和左侧。(因为浏览器调整大小会改变每个视图的坐标,并且您希望视图保持确切的相对位置。)

import React, { useState, useEffect } from 'react';
import { Text, View } from 'react-native';
import ReactNativeAnimatedLayout from 'react-native-animated-layout';


export default function App() {
    const [rerender, setRerender] = useState(0);
    const redView = <View style={{ backgroundColor: 'red', height: '100%', width: '100%', }}><Text>{"I am the red view"}</Text></View>;
    const greenView = <View style={{ backgroundColor: 'green', height: '100%', width: '100%', overflow: 'hidden'}}>
        <Text>{"I am the green view and my contents overflow. Because of the overflow prop, the over-flown content is hidden."}</Text><Text>{"0"}</Text><Text>{"1"}</Text><Text>{"2"}</Text><Text>{"3"}</Text><Text>{"4"}</Text><Text>{"5"}</Text><Text>{"6"}</Text><Text>{"7"}</Text><Text>{"8"}</Text><Text>{"9"}</Text><Text>{"10"}</Text><Text>{"11"}</Text><Text>{"12"}</Text><Text>{"13"}</Text><Text>{"14"}</Text><Text>{"15"}</Text><Text>{"16"}</Text><Text>{"17"}</Text><Text>{"18"}</Text><Text>{"19"}</Text><Text>{"20"}</Text><Text>{"21"}</Text><Text>{"22"}</Text><Text>{"23"}</Text><Text>{"24"}</Text><Text>{"25"}</Text><Text>{"26"}</Text><Text>{"27"}</Text><Text>{"28"}</Text><Text>{"29"}</Text>
        </View>;
    const blueView = <View style={{ backgroundColor: 'blue', height: '100%', width: '100%', }}><Text>{"I am the blue view"}</Text></View>;
    const layouts = [
        {
            validAfterWHRatio: 0,
            validBeforeWHRatio: 0.9,
            views: [
                { top: 0, bottom: 0.5, left: 0, right: 1, children: redView },
                { top: 0.75, bottom: 1, left: 0, right: 1, children: blueView },
                { top: 0.5, bottom: 0.75, left: 0, right: 1, children: greenView },
            ]
        },
        {
            validAfterWHRatio: 1 / 0.62,
            validBeforeWHRatio: 999, // infinity
            views: [
                { top: 0, bottom: 1, left: 0, right: 0.5, children: redView },
                { top: 0.5, bottom: 1, left: 0.5, right: 1, children: blueView },
                { top: 0, bottom: 0.5, left: 0.5, right: 1, children: greenView },
            ]
        },
        {
            defaultFlag: true,
            views: [
                { top: 0.16, bottom: 0.84, left: 0.16, right: 0.5, children: redView },
                { top: 0.50, bottom: 0.84, left: 0.5, right: 0.84, children: blueView },
                { top: 0.16, bottom: 0.50, left: 0.5, right: 0.84, children: greenView },
            ]
        },
    ];

    useEffect(() => {
        let nextRerender = rerender + 1;
        setRerender(nextRerender);
    }, []); // when we want to re-render

    return <ReactNativeAnimatedLayout
        layouts={layouts}
        rerender={rerender}
    />;
}

注意:这种方法特别适用于渐进式 Web 应用程序。如果您需要使用滚动条,则应将其放置在其中一个视图中,可能是“内容视图”。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接