iT邦幫忙

2021 iThome 鐵人賽

DAY 28
0
Mobile Development

卡卡30天學 React Native系列 第 28

[ 卡卡 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


上一篇
[ 卡卡 DAY 27 ] - React Native keyboard 之亂之按螢幕就收鍵盤
下一篇
[ 卡卡 DAY 29 ] - React Native iOS 打包步驟及離線 jsbundle產生
系列文
卡卡30天學 React Native30

尚未有邦友留言

立即登入留言