Pressable va tugmalar — bosish, uzoq bosish, feedback

~12 daq · React Native · Asosiy komponentlar

Muammodan boshlaylik

Tugma yasadingiz. Bosganda ish bajariladi — lekin tugma o'zi hech qanday reaksiya bildirmaydi. Foydalanuvchi bosdimi, yo'qmi — bilmaydi va yana bosadi. Buyurtma ikki marta yuboriladi.

Mobil ilovada teginishga javob (feedback) — majburiy: tugma bosilganda xiralashishi, rangi o'zgarishi yoki to'lqin effekti. Bu darsda bosiladigan elementlarni to'g'ri yasashni o'rganamiz.


Button — eng oddiy, lekin cheklangan

import { Button } from 'react-native';

<Button title="Saqlash" onPress={saqlash} color="#0284c7" />

Har bir platformada tizim tugmasi. Lekin stil berib bo'lmaydi (shrift, padding, border-radius). Real ilovalarda deyarli ishlatilmaydi.


Pressable — zamonaviy yo'l

import { Pressable, Text, StyleSheet } from 'react-native';

<Pressable
  onPress={saqlash}
  style={({ pressed }) => [styles.tugma, pressed && styles.bosilgan]}
>
  <Text style={styles.matn}>Saqlash</Text>
</Pressable>

const styles = StyleSheet.create({
  tugma: {
    backgroundColor: '#0284c7',
    paddingVertical: 14,
    paddingHorizontal: 24,
    borderRadius: 12,
    alignItems: 'center',
  },
  bosilgan: { opacity: 0.7, transform: [{ scale: 0.98 }] },
  matn: { color: 'white', fontSize: 16, fontWeight: '600' },
});

style funksiya bo'lishi mumkin: u { pressed } ni oladi. Barmoq tegib turganda — xira va biroz kichikroq. Oddiy, lekin "jonli" his beradi.

Bolalar ham holatni olishi mumkin:

<Pressable onPress={...}>
  {({ pressed }) => (
    <Text style={{ color: pressed ? '#0369a1' : '#0284c7' }}>Havola</Text>
  )}
</Pressable>

Hodisalar

<Pressable
  onPress={() => console.log('bosildi')}
  onLongPress={() => console.log('uzoq bosildi')}   // kontekst menyu, o'chirish
  delayLongPress={400}
  onPressIn={() => console.log('tegdi')}
  onPressOut={() => console.log("qo'yib yubordi")}
  disabled={yuklanmoqda}
  hitSlop={10}
/>

hitSlop — bosish maydonini kengaytirish

Kichik ikonka (20×20) ni barmoq bilan aniq bosish qiyin. hitSlop={10} — ko'rinishni o'zgartirmasdan har tomonga 10 birlik bosiladigan maydon qo'shadi.

[!TIP] Apple va Google tavsiyasi: bosiladigan element kamida 44×44 (iOS) / 48×48 (Android) bo'lsin. Kichik ikonkalar uchun hitSlop yoki padding.

Android to'lqin effekti

<Pressable android_ripple={{ color: 'rgba(0,0,0,0.1)' }} style={styles.band}>
  <Text>Sozlamalar</Text>
</Pressable>

Android foydalanuvchilariga tanish "ripple". iOS da e'tiborsiz qoldiriladi — u yerda pressed holatidagi opacity ishlatiladi.


Qayta ishlatiladigan Tugma komponenti

// components/Tugma.tsx
import { Pressable, Text, ActivityIndicator, StyleSheet, PressableProps } from 'react-native';

type Props = PressableProps & {
  matn: string;
  turi?: 'asosiy' | 'ikkinchi' | 'xavfli';
  yuklanmoqda?: boolean;
};

export function Tugma({ matn, turi = 'asosiy', yuklanmoqda, disabled, ...props }: Props) {
  const ochiq = disabled || yuklanmoqda;
  return (
    <Pressable
      accessibilityRole="button"
      accessibilityState={{ disabled: !!ochiq, busy: !!yuklanmoqda }}
      disabled={ochiq}
      style={({ pressed }) => [
        styles.asos,
        styles[turi],
        pressed && { opacity: 0.8 },
        ochiq && { opacity: 0.5 },
      ]}
      {...props}
    >
      {yuklanmoqda
        ? <ActivityIndicator color={turi === 'ikkinchi' ? '#0284c7' : 'white'} />
        : <Text style={[styles.matn, turi === 'ikkinchi' && { color: '#0284c7' }]}>{matn}</Text>}
    </Pressable>
  );
}

const styles = StyleSheet.create({
  asos: { paddingVertical: 14, borderRadius: 12, alignItems: 'center', minHeight: 50, justifyContent: 'center' },
  asosiy: { backgroundColor: '#0284c7' },
  ikkinchi: { backgroundColor: 'white', borderWidth: 1, borderColor: '#0284c7' },
  xavfli: { backgroundColor: '#dc2626' },
  matn: { color: 'white', fontSize: 16, fontWeight: '600' },
});
<Tugma matn="Buyurtma berish" onPress={buyurtma} yuklanmoqda={yuborilmoqda} />
<Tugma matn="Bekor qilish" turi="ikkinchi" onPress={() => router.back()} />

yuklanmoqda paytida tugma disabled — ikki marta yuborish muammosi hal (boshidagi muammo).

accessibilityRole="button" — ekran o'quvchisi "Buyurtma berish, tugma" deb o'qiydi.


Eski komponentlar

Eski kodda ko'rasiz:

Komponent Nima qiladi
TouchableOpacity Bosilganda xiralashadi
TouchableHighlight Bosilganda fon rangi o'zgaradi
TouchableWithoutFeedback Hech qanday effektsiz

Ular hali ishlaydi, lekin rasmiy tavsiya — Pressable: barcha imkoniyatlar bitta komponentda va moslashuvchanroq.


Nima uchun shunday?

Nima uchun React Native da tugmalar vebdagi <button> kabi tayyor ko'rinishga ega emas?

Chunki "tugma" har bir platformada boshqacha ko'rinadi va har bir ilova o'z dizayn tizimiga ega. Agar React Native platformaning standart tugmasini majburlasa — ilovalar bir xil ko'rinardi va dizaynerlar cheklanib qolardi (Button aynan shunday — shuning uchun kam ishlatiladi). Pressable esa "bosish mantig'i" ni ko'rinishdan ajratadi: u faqat teginishni boshqaradi, ko'rinish — butunlay sizning qo'lingizda.


Xulosa

Eslab qoling:

  • Button — stilsiz, cheklangan; real ilovada Pressable
  • style={({ pressed }) => [...]} — bosilgandagi feedback
  • onPress, onLongPress, disabled, hitSlop, android_ripple
  • Bosiladigan maydon — kamida 44-48 birlik
  • Yuklanayotganda disabled — ikki marta yuborishdan himoya
  • accessibilityRole="button", accessibilityState
  • TouchableOpacity — eski; yangi kodda Pressable

Keyingi dars

11-dars: Modal, Alert, ActivityIndicator, Switch