组件

Stepper

Stepper 在 − 和 + 两个按钮之间显示一个数字。每按一次,数字按 step 变化,并保持在 min 与 max 之间。按住按钮会连续步进。连续步进的计时器在核心中运行,JS 只会收到携带每个新值的 onChange。

ui-stepper.tsx 在线编辑 在新标签页打开
// Stepper: its own value, a controlled one with a fractional step, and its ref.
import { mount, signal, Text, View } from "nsh";
import { Button, Group, Stepper, type StepperRef } from "nsh/ui/mobile";

function Row(props: { label: string; children: any }) {
  return (
    <View style={{ flexDirection: "row", alignItems: "center", justifyContent: "space-between" }}>
      <Text>{props.label}</Text>
      {props.children}
    </View>
  );
}

function App() {
  const quantity = signal(1.5);
  const asked = signal("");
  let own!: StepperRef;
  return (
    <View style={{ flex: 1, backgroundColor: "#f5f5f5", padding: 16, paddingTop: 24, gap: 20 }}>
      <Text style={{ fontSize: 22, fontWeight: "700" }}>Stepper</Text>
      <Group footer={<Text>Hold − or + to keep stepping.</Text>}>
        <Row label="Own value (0–10)">
          <Stepper ref={own} defaultValue={3} min={0} max={10} />
        </Row>
        <Row label={`Controlled: ${quantity()}`}>
          <Stepper value={quantity()} min={0} max={5} step={0.5} onChange={(v) => quantity.set(v)} />
        </Row>
        <Row label="Disabled">
          <Stepper defaultValue={2} disabled />
        </Row>
      </Group>
      <Button
        variant="secondary"
        title="Read the first, then set it to 7"
        onPress={async () => {
          const was = await own.value();
          own.setValue(7);
          asked.set(`It was ${was}`);
        }}
      />
      <Text style={{ color: "#737373" }}>{asked()}</Text>
    </View>
  );
}

mount(App);
import { Stepper, type StepperRef } from "nsh/ui/mobile";

#用法

import { mount, signal, Text, View } from "nsh";
import { Stepper } from "nsh/ui/mobile";

function App() {
  const guests = signal(2);
  return (
    <View style={{ flex: 1, padding: 16, paddingTop: 48, gap: 12 }}>
      <Text>{`${guests()} guests`}</Text>
      <Stepper value={guests()} min={1} max={12} onChange={(v) => guests.set(v)} />
    </View>
  );
}

mount(App);

#受控与非受控

  • 受控:传入 value 并在 onChange 中更新它。Stepper 显示 value;按下按钮时通过 onChange 报告下一个值,等你设置了新的 value 后数字才会变化。
  • 非受控:不传 value。Stepper 自己保存数值,从 defaultValue 开始,并通过 onChange 报告每次变化。
<Stepper defaultValue={5} min={0} max={50} onChange={(v) => console.log("now", v)} />

#范围、步长与小数位

  • 数值始终位于 min 与 max 之间。如果 min 大于 max,两者会互换;负的 step 按正值处理。
  • 显示的小数位数与 step 的小数位数相同:step={0.25} 显示 1.75,step={1} 显示 2。
  • 数值会四舍五入到这个小数位数,从而避免 0.30000000000000004 这类浮点误差。
  • min、max 或 step 改变时,数值会被移回新的范围之内。
<Stepper value={weight()} min={0} max={5} step={0.5} onChange={(v) => weight.set(v)} />

#按住按钮

按下时立即步进一次。如果 400 ms 后按钮仍被按住,Stepper 会每 80 ms 再步进一次,直到松开按钮,或数值到达 min 或 max。到达边界时,对应的按钮会变暗并禁用。

#Ref 方法

传入 ref 即可获得一个 StepperRef,用来在代码中读取和设置数值:

import { mount, View } from "nsh";
import { Button, Stepper, type StepperRef } from "nsh/ui/mobile";

function App() {
  let stepper!: StepperRef;
  return (
    <View style={{ flex: 1, padding: 16, paddingTop: 48, gap: 12 }}>
      <Stepper ref={stepper} defaultValue={3} max={10} />
      <Button
        title="Reset"
        onPress={async () => {
          console.log("was", await stepper.value());
          stepper.setValue(0);
        }}
      />
    </View>
  );
}

mount(App);
成员说明
setValue(value: number): void设置数值(四舍五入到步长的小数位数,并限制在范围内),并像按下按钮一样通过 onChange 报告。对受控的 Stepper,数字要等你更新 value 后才会变化。
value(): Promise<number>当前显示的数值。返回 Promise,因为数值保存在核心中,而不在 JS 里。
node: YNodeStepper 的宿主节点。

#属性

属性类型默认值说明
valuenumber | null无(非受控)由应用控制时的数值。
defaultValuenumber0不由应用控制时的初始值。
minnumber0最小值。
maxnumber100最大值。
stepnumber1每按一次数值的变化量。
disabledbooleanfalse不响应按下,两个按钮都变暗。
refStepperRef | ((ref: StepperRef) => void)无接收 ref。
class、classList、style、testID、onLayout作用于 Stepper 的根视图(整行)。

#事件

事件参数触发时机
onChangenumber:新值按下、按住时的连续步进或 setValue 改变了数值。数值不会变化时(位于边界)不触发。

#主题

部位主题键
按钮secondary.background,按下时为 secondary.active.background,圆角为 radius
− 和 +secondary.foreground,字号 font.size + 4
数字foreground,字号 font.size + 1

按钮尺寸为 40 × 40 pt。禁用的按钮或位于边界的按钮以 40% 不透明度显示。参见主题。

#无障碍

两个按钮的角色都是 button,标签分别为 “Decrease” 和 “Increase”。位于边界的按钮,或整个 Stepper 被禁用时,按钮会报告为已禁用。数字是普通文本,屏幕阅读器按原样朗读。

#相关

  • Group:在设置行中使用 Stepper。
  • Input:配合 keyboardType 自由输入数字。