[ 卡卡 DAY 28 ] - React Native 自制 radio button + textarea

今天天外飞来一笔说需要 RN 表单画面
emergency!!!
咦咦咦 啊怎麽只有 TextInput
radio button 跟 textarea 怎麽都没有
基於目前还找不到符合我们需求的!
所以我就开始手刻元件拉 QQ

textarea

我运用 textinput 来做 textarea,主要设置为以下:

  1. 设定 style 的 minHeight 为 130
  2. onChangeText
    Callback that is called when the text input's text changes. Changed text is passed as a single string argument to the callback handler.
  3. keyboardType 使用预设的
  4. multiline true 代表 input 可以自由更变行数
  5. placeholder 空的时候预设的字
import React from 'react';
import { TextInput, StyleSheet } from 'react-native';
import { LAYOUT } from '@constants';
const Textarea = (props) => {
  const [text, setText] = React.useState(null);

  return (
    <TextInput
      multiline
      style={styles.input}
      onChangeText={(text) => setText(text)}
      value={text}
      placeholder="请填写您宝贵的意见"
      keyboardType="default"
    />
  );
};

const styles = StyleSheet.create({
  input: {
    fontSize: 16,
    borderWidth: 1,
    minHeight: 130,
    borderColor: '#d6d6d6',
    ...LAYOUT.margin(15, 0),
    ...LAYOUT.padding(10)
  }
});
export default Textarea;

https://ithelp.ithome.com.tw/upload/images/20211009/20142011M6pkORCztK.png
若字数太多他会一直往下长:P

radio button(单选)- 来举例同不同意的样式

记得我们的问卷调查有问满意度跟同意度吗?
我使用同意度来举例,其实 radio button 也可以这样使用
这次我使用 Text, View, TouchableOpacity 来完成

  1. seleted 为预设值 0
  2. data 为按钮文字的 mock // label 与 value
  3. onPress 运用按了按钮 setSelected 以 value 来判断
  4. selected === item.value 来判断是否选取到的颜色显示
  5. renderTextTwo + renderText 基於样式需求所以做字串切割,若各位大大有什麽好的建议,欢迎提出来供我参考 QQ
import React from 'react';
import { Text, View, TouchableOpacity, StyleSheet } from 'react-native';

const AgreeItem = (props) => {
  const [selected, setSelected] = React.useState(0); // 注解1
  const [data] = React.useState([
    { label: '非常同意', value: 0 },
    { label: '同意', value: 1 },
    { label: '普通', value: 2 },
    { label: '不同意', value: 3 },
    { label: '非常不同意', value: 4 }
  ]); // 注解2

  const renderTextTwo = (text) => {
    let str = text;
    str = str.substring(0, 2);
    return str;
  };
  const renderText = (text) => {
    let str = text;
    str = str.substring(2);
    return str;
  };
  const pressBtn = (value) => {
    setSelected(value);
  };
  return (
    <View style={{ flex: 1, flexDirection: 'row', marginVertical: 15 }}>
      {data.map((item) => {
        return (
          <TouchableOpacity
            style={[props.style, styles.btnContainer]}
            onPress={() => pressBtn(item.value)}  // 注解3
            key={item.value}
          >
            <View
              style={[
                styles.radioBox,
                {
                  borderColor: selected === item.value ? '#f05c38' : '#bfbfbf', //注解4
                  backgroundColor: selected === item.value ? '#f05c38' : null
                }
              ]}
            >
              {item.label.length < 5 ? (
                <Text
                  style={[
                    styles.btnText,
                    {
                      color: selected === item.value ? '#ffffff' : '#bfbfbf'
                    }
                  ]}
                >
                  {item.label}
                </Text>
              ) : (
                <View>
                  <View>
                    <Text
                      style={[
                        styles.btnText,
                        {
                          color:
                            selected === item.value ? '#ffffff' : '#bfbfbf',
                          textAlign: 'center'
                        }
                      ]}
                    >
                      {renderTextTwo(item.label)}
                    </Text>
                  </View>
                  <View>
                    <Text
                      style={[
                        styles.btnText,
                        {
                          color:
                            selected === item.value ? '#ffffff' : '#bfbfbf',
                          textAlign: 'center'
                        }
                      ]}
                    >
                      {renderText(item.label)}
                    </Text>
                  </View>
                </View>
              )}
            </View>
          </TouchableOpacity>
        );
      })}
    </View>
  );
};

const styles = StyleSheet.create({
  btnContainer: { flexDirection: 'row', flex: 1 },
  btnText: { fontSize: 12 },
  radioBox: {
    height: 44,
    width: 57,
    borderWidth: 2,
    marginRight: 5,
    alignItems: 'center',
    justifyContent: 'center'
  }
});
export default AgreeItem;

https://ithelp.ithome.com.tw/upload/images/20211009/20142011ddTXOdrXQ4.png
大致上做出了这两个 UI 供大家参考及延伸,若有更好的想法欢迎多多指教唷!
Day 28 done


<<:  【Day30】挑战回顾 & 铁人练成心得分享

>>:  [Day28] 前端部署网页的方式 (Vercel, AWS S3 & Netlify)

予焦啦!准备工具链

本节是以 Golang 上游 1a708bcf1d17171056a42ec1597ca8848c...

Day 06 - Google Map 在地向导也是另一种数位足迹

图片来源 延续上一篇最後提到的老照片, 不知道大家认不认为除了FB开地球(开放所有人浏览)之外, ...

Day06:爸爸这麽做都是为你好

当我们在定义类别时,有三种东西可以定义,属性(field)、建构子(constructor)、方法(...

序章:最幸福的事,莫过於当你看到code变成一幅幅美丽的画

自序 大家好,我是来自中山大学的Jerry,接触javascript大约三年了,虽然不像业界的各路大...

自动化测试,让你上班拥有一杯咖啡的时间 | Day 2 - Cypress 环境设定

此系列文章会同步发文到个人部落格,有兴趣的读者可以前往观看喔。 今天要教大家 Cypress 环境...