在React Native中将两个具有动态增长的Flex元素粘合在一起。

huangapple go评论79阅读模式
英文:

Stick two flex elements with dynamic growing in react-native

问题

使用React Native,我希望在同一行内使用TextInput与MaterialIcons.Button。

我希望所有元素都在水平方向上居中,但无法使用以下代码实现:

import React from 'react';
import {
  StyleSheet, TextInput, View,
} from 'react-native';
import MaterialIcons from 'react-native-vector-icons/MaterialIcons';

const WordInput = () => {
  return (
    <View style={styles.container}>
      <View style={styles.textInputContainer}>
        <TextInput
          textAlign="left"
        />
      </View>
      
      <View style={styles.arrowButtonContainer}>
        <MaterialIcons.Button
          name="arrow-forward-ios"
        />
      </View>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flexDirection: 'row',
    flex: 1,
  },
  textInputContainer: {
    flex: 1,
    alignItems: 'flex-end',
    justifyContent: 'center',
  },
  arrowButtonContainer: {
    flex: 1,
    alignItems: 'flex-start',
    justifyContent: 'center',
  },
});

这里是关联的Expo Snack链接

问题是当我在TextInput内输入文本时,按钮根本不会移动。我希望它在TextInput的宽度增加时动态向右移动。整体应该在水平方向上居中。

有谁知道我应该如何操作吗?

谢谢!

英文:

With react-native, I'm looking forward having a TextInput stuck with a MaterialIcons.Button within the same line.

I want the whole elements be centered horizontally but cannot achieve this with the following code:

import React from &#39;react&#39;;
import {
  StyleSheet, TextInput, View,
} from &#39;react-native&#39;;
import MaterialIcons from &#39;react-native-vector-icons/MaterialIcons&#39;;

const WordInput = () =&gt; {
  return (
    &lt;View style={styles.container}&gt;
      &lt;View style={styles.textInputContainer}&gt;
        &lt;TextInput
          textAlign=&quot;left&quot;
        /&gt;
      &lt;/View&gt;
      
      &lt;View style={styles.arrowButtonContainer}&gt;
        &lt;MaterialIcons.Button
          name=&quot;arrow-forward-ios&quot;
        /&gt;
      &lt;/View&gt;
    &lt;/View&gt;
  );
};

const styles = StyleSheet.create({
  container: {
    flexDirection: &#39;row&#39;,
    flex: 1,
  },
  textInputContainer: {
    flex: 1,
    alignItems: &#39;flex-end&#39;,
    justifyContent: &#39;center&#39;,
  },
  arrowButtonContainer: {
    flex: 1,
    alignItems: &#39;flex-start&#39;,
    justifyContent: &#39;center&#39;,
  },
});

Here is the associated expo snack link.

The problem is that when I type text inside the TextInput, the Button doesn't move at all.
I would like it to dynamically shift to the right when the TextInput's width grow. The overall should be horizontally centered.

Does anyone know how I can proceed?

Thanks!

答案1

得分: 0

抱歉,以下是您提供的代码部分的翻译:

不幸的是`<TextInput>` 默认不支持任何形式的自动增长行为但您可以自己实现使用一个隐藏的 `<Text>` 该层具有与您的 `<TextInput>` 相同的字体样式和大小规则然后您可以将输入值呈现到该 `<Text>` 元素然后测量该元素的布局并将测得的宽度应用于您的 `<TextInput>` 组件

```javascript
import { useState } from 'react';
import { StyleSheet, TextInput, View, Dimensions, Text } from 'react-native';
import MaterialIcons from 'react-native-vector-icons/MaterialIcons';

export default function App() {
  const [value, setValue] = useState();
  const [containerWidth, setContainerWidth] = useState(
    Dimensions.get('window').width
  );
  const [textWidth, setTextWidth] = useState(0);
  const [buttonWidth, setButtonWidth] = useState(0);

  const inputWidth = Math.min(textWidth, containerWidth - buttonWidth);

  return (
    <View style={styles.root}>
      <View
        style={styles.inner}
        onLayout={(e) => setContainerWidth(e.nativeEvent.layout.width)}>
        <Text
          style={styles.hiddenText}
          onLayout={(e) => setTextWidth(e.nativeEvent.layout.width)}
          numberOfLines={1}
          accessibilityElementsHidden
          importantForAccessibility="no-hide-decendants">
          {value}
        </Text>
        <TextInput
          textAlign="left"
          placeholder="输入文本"
          style={[styles.input, { width: inputWidth }]}
          onChangeText={setValue}
        />
        <View onLayout={(e) => setButtonWidth(e.nativeEvent.layout.width)}>
          <MaterialIcons.Button name="arrow-forward-ios" />
        </View>
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  root: {
    flex: 1,
    justifyContent: 'center',
  },
  inner: {
    flexDirection: 'row',
    justifyContent: 'center',
    borderWidth: 1,
    borderColor: 'red',
  },
  input: {
    borderWidth: 1,
    borderColor: 'green',
    minWidth: 100,
  },
  hiddenText: {
    position: 'absolute',
    top: 0,
    left: 0,
    opacity: 0,
  },
});

这里有一个 expo snack 示例

英文:

Unfortunately &lt;TextInput&gt; doesn't support any sort of "auto-growing" behaviour by default, but you could implement something yourself using a hidden &lt;Text&gt; layer that has the same font styling and sizing rules as your &lt;TextInput&gt;. If you then render your input value to that &lt;Text&gt; element, you can measure the layout of that element and apply the measured width to your &lt;TextInput&gt; component.

import { useState } from &#39;react&#39;;
import { StyleSheet, TextInput, View, Dimensions, Text } from &#39;react-native&#39;;
import MaterialIcons from &#39;react-native-vector-icons/MaterialIcons&#39;;

export default function App() {
  const [value, setValue] = useState();
  const [containerWidth, setContainerWidth] = useState(
    Dimensions.get(&#39;window&#39;).width
  );
  const [textWidth, setTextWidth] = useState(0);
  const [buttonWidth, setButtonWidth] = useState(0);

  const inputWidth = Math.min(textWidth, containerWidth - buttonWidth);

  return (
    &lt;View style={styles.root}&gt;
      &lt;View
        style={styles.inner}
        onLayout={(e) =&gt; setContainerWidth(e.nativeEvent.layout.width)}&gt;
        &lt;Text
          style={styles.hiddenText}
          onLayout={(e) =&gt; setTextWidth(e.nativeEvent.layout.width)}
          numberOfLines={1}
          accessibilityElementsHidden
          importantForAccessibility=&quot;no-hide-decendants&quot;&gt;
          {value}
        &lt;/Text&gt;
        &lt;TextInput
          textAlign=&quot;left&quot;
          placeholder=&quot;enter text&quot;
          style={[styles.input, { width: inputWidth }]}
          onChangeText={setValue}
        /&gt;
        &lt;View onLayout={(e) =&gt; setButtonWidth(e.nativeEvent.layout.width)}&gt;
          &lt;MaterialIcons.Button name=&quot;arrow-forward-ios&quot; /&gt;
        &lt;/View&gt;
      &lt;/View&gt;
    &lt;/View&gt;
  );
}

const styles = StyleSheet.create({
  root: {
    flex: 1,
    justifyContent: &#39;center&#39;,
  },
  inner: {
    flexDirection: &#39;row&#39;,
    justifyContent: &#39;center&#39;,
    borderWidth: 1,
    borderColor: &#39;red&#39;,
  },
  input: {
    borderWidth: 1,
    borderColor: &#39;green&#39;,
    minWidth: 100,
  },
  hiddenText: {
    position: &#39;absolute&#39;,
    top: 0,
    left: 0,
    opacity: 0,
  },
});

Here's an expo snack example.

huangapple
  • 本文由 发表于 2023年1月9日 06:32:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/75051739.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定