首页指南参考教程

实现复选框

了解如何在你的 Expo 项目中实现完全可定制的复选框。


expo-checkbox 包提供了一个复选框的快速实现,你可以直接在项目中使用它。但是,为了进行完全自定义并控制复选框的外观和感觉,本页面深入介绍了如何从头开始实现该组件。

¥The expo-checkbox package provides a quick implementation of a checkbox that you can directly use in your project. However, to have full customization, and control over the look and feel of the checkbox, this page goes in-depth on how to implement the component from scratch.

了解复选框

¥Understanding the checkbox

复选框是存在于两种状态之一的按钮 - 已选中或未选中。这使其成为 useState() 钩子的完美候选者。我们的第一次迭代将渲染一个在选中和未选中状态之间切换的按钮。选中该复选框后,我们将在按钮中心渲染一个复选标记图标。

¥A checkbox is a button that exists in one of two states — it is checked, or it isn't. This makes it a perfect candidate for the useState() hook. Our first iteration will render a button that toggles between checked and unchecked states. When the checkbox is checked, we'll render a checkmark icon in the center of the button.

你可以在我们的 图标指南 中找到有关在 Expo 项目中使用图标的更多信息。

¥You can find more information about using icons in your Expo project in our Icons guide.

Example
import { useState } from 'react';
import { Pressable, StyleSheet, Text, View } from 'react-native';
import { Ionicons } from '@expo/vector-icons';

function MyCheckbox() {
  const [checked, setChecked] = useState(false);
  return (
    <Pressable
      style={[styles.checkboxBase, checked && styles.checkboxChecked]}
      onPress={() => setChecked(!checked)}>
      {checked && <Ionicons name="checkmark" size={24} color="white" />}
    </Pressable>
  );
}

export default function App() {
  return (
    <View style={styles.appContainer}>
      <Text style={styles.appTitle}>Checkbox Example</Text>
      <View style={styles.checkboxContainer}>
        <MyCheckbox />
        <Text style={styles.checkboxLabel}>{`⬅️ Click!`}</Text>
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  checkboxBase: {
    width: 24,
    height: 24,
    justifyContent: 'center',
    alignItems: 'center',
    borderRadius: 4,
    borderWidth: 2,
    borderColor: 'coral',
    backgroundColor: 'transparent',
  },
  checkboxChecked: {
    backgroundColor: 'coral',
  },
  appContainer: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
  appTitle: {
    marginVertical: 16,
    fontWeight: 'bold',
    fontSize: 24,
  },
  checkboxContainer: {
    flexDirection: 'row',
    alignItems: 'center',
  },
  checkboxLabel: {
    marginLeft: 8,
    fontWeight: '500',
    fontSize: 18,
  },
});

icons.expo.fyi 是查找 @expo/vector-icons 包中所有可用图标的绝佳资源。

¥icons.expo.fyi is a great resource for finding all the icons available in the @expo/vector-icons package.

控制复选框

¥Controlling the checkbox

此复选框在此状态下没有用处,因为 checked 值只能从组件内部访问 - 通常你需要从外部控制该复选框。这可以通过将 checkedonChange 定义为传递到复选框的 props 来实现:

¥This checkbox isn't useful in this state because the checked value is accessible only from within the component — more often than not you'll want to control the checkbox from outside. This is achievable by defining checked and onChange as props that are passed into the checkbox:

Example
import { useState } from 'react';
import { Pressable, StyleSheet, Text, View } from 'react-native';
import { Ionicons } from '@expo/vector-icons';

function MyCheckbox({ onChange, checked }) {
  return (
    <Pressable
      style={[styles.checkboxBase, checked && styles.checkboxChecked]}
      onPress={onChange}>
      {checked && <Ionicons name="checkmark" size={24} color="white" />}
    </Pressable>
  );
}

export default function App() {
  const [checked, setChecked] = useState(false);
  return (
    <View style={styles.appContainer}>
      <Text style={styles.appTitle}>Checkbox Example</Text>
      <View style={styles.checkboxContainer}>
        <MyCheckbox onChange={() => setChecked(!checked)} checked={checked} />
        <Text style={styles.checkboxLabel}>{`⬅️ Click!`}</Text>
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  checkboxBase: {
    width: 24,
    height: 24,
    justifyContent: 'center',
    alignItems: 'center',
    borderRadius: 4,
    borderWidth: 2,
    borderColor: 'coral',
    backgroundColor: 'transparent',
  },
  checkboxChecked: {
    backgroundColor: 'coral',
  },
  appContainer: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
  appTitle: {
    marginVertical: 16,
    fontWeight: 'bold',
    fontSize: 24,
  },
  checkboxContainer: {
    flexDirection: 'row',
    alignItems: 'center',
  },
  checkboxLabel: {
    marginLeft: 8,
    fontWeight: 500,
    fontSize: 18,
  },
});

该模式称为 受控组件

¥This pattern is referred to as a controlled component.

扩展接口

¥Extending the interface

当复选标记为 checked 和不是时,需要渲染不同的样式是很常见的。让我们将其添加到复选框的属性中并使其更可重用:

¥It's common enough to need to render different styles when the checkmark is checked and when it is not. Let's add this to the checkbox's props and make it more reusable:

Example
import { useState } from 'react';
import { Pressable, StyleSheet, Text, View } from 'react-native';
import { Ionicons } from '@expo/vector-icons';

function MyCheckbox({
  checked,
  onChange,
  buttonStyle = {},
  activeButtonStyle = {},
  inactiveButtonStyle = {},
  activeIconProps = {},
  inactiveIconProps = {},
}) {
  const iconProps = checked ? activeIconProps : inactiveIconProps;
  return (
    <Pressable
      style={[
        buttonStyle,
        checked
          ? activeButtonStyle
          : inactiveButtonStyle,
      ]}
      onPress={() => onChange(!checked)}>
      {checked && (
        <Ionicons
          name="checkmark"
          size={24}
          color="white"
          {...iconProps}
        />
      )}
    </Pressable>
  );
}

export default function App() {
  const [checked, setChecked] = useState(false);
  return (
    <View style={styles.appContainer}>
      <Text style={styles.appTitle}>Checkbox Example</Text>
      <View style={styles.checkboxContainer}>
        <MyCheckbox
          checked={checked}
          onChange={setChecked}
          buttonStyle=

{styles.checkboxBase}


          activeButtonStyle=

{styles.checkboxChecked}


        />
        <Text style={styles.checkboxLabel}>{`⬅️ Click!`}</Text>
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  checkboxBase: {
    width: 24,
    height: 24,
    justifyContent: 'center',
    alignItems: 'center',
    borderRadius: 4,
    borderWidth: 2,
    borderColor: 'coral',
    backgroundColor: 'transparent',
  },
  checkboxChecked: {
    backgroundColor: 'coral',
  },
  appContainer: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
  appTitle: {
    marginVertical: 16,
    fontWeight: 'bold',
    fontSize: 24,
  },
  checkboxContainer: {
    flexDirection: 'row',
    alignItems: 'center',
  },
  checkboxLabel: {
    marginLeft: 8,
    fontWeight: 500,
    fontSize: 18,
  },
});

此复选框勾选了所有应有的框。它在 checked 状态之间切换,可以控制,并且样式是完全可定制的。

¥This checkbox ticks all the boxes of what it should be. It toggles between checked states, can be controlled, and the styles are fully customizable.

Expo 中文网 - 粤ICP备13048890号