React Native Academy · Lektion

Tryckhantering med TouchableOpacity och Pressable

Lägg till återkoppling vid tryck på UI-element med TouchableOpacity och det nyare API:t Pressable, inklusive visuell återkoppling vid tryckning och när tryckningen släpps.

Lektion 2 av 413 steg

Tryckhantering med TouchableOpacity och Pressable är en gratis lektion i React Native Academy på CoddyKit. Detta är lektion 2 av 4. Du kan läsa vilka 3 lektioner som helst i den här lärvägen kostnadsfritt i sin helhet – därefter låser CoddyKit PRO upp alla lektioner, plus praktisk övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Den ingår i lärvägen för React Native Academy, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i React Native Academy innehåller totalt 4 lektioner.

Göra element tryckbara

I React Native är de flesta komponenter, som View och Text, inte tryckbara som standard — de ignorerar pekhändelser. Om du vill att något ska reagera på tryck omsluter du det med en tryckbar komponent. React Native erbjuder flera alternativ: TouchableOpacity (tonar ned elementet vid tryck), TouchableHighlight (mörkar bakgrunden vid tryck), TouchableWithoutFeedback (ingen visuell återkoppling) och det nyare API:et Pressable (mest flexibelt). TouchableOpacity och Pressable är de två du kommer att använda för de allra flesta gränssnittselement.

import { TouchableOpacity, Text, View } from 'react-native';

export default function TapExample() {
  return (
    <View style={{ padding: 24 }}>
      <TouchableOpacity
        onPress={() => console.log('Tapped!')}
        style={{ backgroundColor: '#4f86f7', padding: 16, borderRadius: 10 }}
      >
        <Text style={{ color: '#fff', textAlign: 'center', fontWeight: 'bold' }}>
          Tap Me
        </Text>
      </TouchableOpacity>
    </View>
  );
}

TouchableOpacity och activeOpacity

TouchableOpacity är den vanligaste tryckbara komponenten. När användaren trycker på den minskar opaciteten hos dess barn för att visa att trycket registrerades. Standardvärdet för activeOpacity är 0.2 (80 % toning). Anpassa det med egenskapen activeOpacity: 0.7 för diskret återkoppling, 0.9 för nästan ingen förändring eller 0.1 för en tydlig toning. Toningsanimeringen körs på den nativa tråden, vilket gör den mjuk även när JS-tråden är upptagen med att behandla andra händelser — det är det som gör att gränssnittet känns responsivt.

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

export default function Buttons() {
  return (
    <View style={styles.col}>
      <TouchableOpacity
        activeOpacity={0.8}  // subtle fade
        onPress={() => {}}
        style={styles.btn}
      >
        <Text style={styles.label}>Subtle (0.8)</Text>
      </TouchableOpacity>

      <TouchableOpacity
        activeOpacity={0.2}  // strong fade (default)
        onPress={() => {}}
        style={styles.btn}
      >
        <Text style={styles.label}>Strong (0.2)</Text>
      </TouchableOpacity>
    </View>
  );
}

const styles = StyleSheet.create({
  col: { padding: 16, gap: 12 },
  btn: { backgroundColor: '#4f86f7', padding: 16, borderRadius: 10, alignItems: 'center' },
  label: { color: '#fff', fontWeight: '600', fontSize: 16 },
});

onPress, onLongPress och onPressIn/Out

TouchableOpacity utlöser flera pekhändelser. onPress utlöses efter ett fullständigt tryck (tryck ned + släpp upp). onLongPress utlöses när användaren håller kvar trycket i cirka 500 ms — användbart för snabbmenyer eller bekräftelser av borttagning. onPressIn utlöses direkt när fingret vidrör skärmen (innan det lyfts), och onPressOut utlöses när fingret lyfts. onPressIn används för att ge omedelbar visuell återkoppling eller starta animeringar innan trycket är slutfört. Använd delayLongPress för att anpassa hur länge användaren måste hålla kvar trycket innan onLongPress utlöses.

import { TouchableOpacity, Text } from 'react-native';

export default function TouchEvents() {
  return (
    <TouchableOpacity
      onPressIn={() => console.log('Touch started')}
      onPressOut={() => console.log('Touch ended')}
      onPress={() => console.log('Tap completed!')}
      onLongPress={() => console.log('Long pressed!')}
      delayLongPress={700} // ms before onLongPress fires
      style={{ backgroundColor: '#4f86f7', padding: 20, borderRadius: 10, margin: 20 }}
    >
      <Text style={{ color: '#fff', textAlign: 'center' }}>
        Tap or hold me
      </Text>
    </TouchableOpacity>
  );
}

Pressable: det moderna API:et

Pressable är det nyare och mer flexibla API:et för tryckbara komponenter, som introducerades i React Native 0.63. Den viktigaste fördelen är att egenskaperna style och children kan ta emot funktioner som får det aktuella trycktillståndet ({ pressed: boolean }). Det gör dynamisk utformning vid tryck enkel utan att du behöver hantera separata state-variabler. Pressable stöder också mer detaljerad händelsehantering, bland annat hitSlop, pressRetentionOffset och unstable_pressDelay. För ny kod bör du föredra Pressable framför TouchableOpacity.

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

export default function PressableButton({ label, onPress }) {
  return (
    <Pressable
      onPress={onPress}
      style={({ pressed }) => [
        styles.btn,
        pressed && styles.pressed,  // apply when finger is down
      ]}
    >
      {({ pressed }) => (
        <Text style={[styles.label, pressed && styles.pressedLabel]}>
          {pressed ? 'Holding...' : label}
        </Text>
      )}
    </Pressable>
  );
}

const styles = StyleSheet.create({
  btn: { backgroundColor: '#4f86f7', padding: 16, borderRadius: 12, alignItems: 'center' },
  pressed: { backgroundColor: '#2563d4', transform: [{ scale: 0.97 }] },
  label: { color: '#fff', fontWeight: '700', fontSize: 16 },
  pressedLabel: { color: '#c3d8ff' },
});

hitSlop: utöka tryckområdet

Riktlinjer för användbarhet på mobila enheter rekommenderar en minsta tryckyta på 44×44 punkter (iOS) eller 48×48 dp (Android). Små ikoner och textlänkar uppfyller ofta inte detta mått visuellt, men du kan utöka det tryckbara området med hitSlop. Det lägger till osynligt utrymme runt komponenten som fortfarande reagerar på tryck. Skicka ett objekt med värdena top, bottom, left och right (i punkter). På så sätt kan du behålla en liten visuell ikon och samtidigt göra den enkel att trycka på — särskilt viktigt för navigeringspilar, stängningsknappar och åtgärdsikoner i listobjekt.

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

export default function SmallButton() {
  return (
    <View style={{ flexDirection: 'row', alignItems: 'center', padding: 16 }}>
      <Text style={{ flex: 1, fontSize: 16 }}>Notification item</Text>

      {/* Small X button — hitSlop expands the tap area */}
      <TouchableOpacity
        onPress={() => console.log('Dismissed')}
        hitSlop={{ top: 16, bottom: 16, left: 16, right: 16 }}
      >
        <Text style={styles.closeIcon}>✕</Text>
      </TouchableOpacity>
    </View>
  );
}

const styles = StyleSheet.create({
  closeIcon: { fontSize: 16, color: '#999', padding: 4 },
});

Inaktiverat tillstånd för knappar

Använd egenskapen disabled på TouchableOpacity eller Pressable för att förhindra interaktion. En inaktiverad tryckbar komponent ignorerar alla pekhändelser. Visa visuellt att komponenten är inaktiverad genom att minska opaciteten eller ändra färgen — React Native gör inte detta automatiskt. Använd stilen opacity eller tillämpa en villkorsstyrd stil baserad på egenskapen disabled. Inaktiverade knappar är viktiga för att förhindra att formulär skickas flera gånger, visa att obligatoriska fält inte är ifyllda eller ange att en funktion kräver en premiumprenumeration.

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

function ActionButton({ label, onPress, disabled }) {
  return (
    <TouchableOpacity
      onPress={onPress}
      disabled={disabled}
      style={[styles.btn, disabled && styles.btnDisabled]}
      activeOpacity={0.8}
    >
      <Text style={[styles.label, disabled && styles.labelDisabled]}>
        {label}
      </Text>
    </TouchableOpacity>
  );
}

const styles = StyleSheet.create({
  btn: { backgroundColor: '#4f86f7', padding: 16, borderRadius: 10, alignItems: 'center' },
  btnDisabled: { backgroundColor: '#c4d8ff', opacity: 0.7 },
  label: { color: '#fff', fontWeight: 'bold', fontSize: 16 },
  labelDisabled: { color: 'rgba(255,255,255,0.6)' },
});

TouchableHighlight för byte av bakgrundsfärg

TouchableHighlight ändrar elementets bakgrundsfärg när användaren trycker på det, i stället för att tona opaciteten som TouchableOpacity gör. Ange underlayColor till den färg som ska visas vid tryck. Komponenten måste ha exakt ett barn — omslut flera barn i en View. TouchableHighlight passar bra för listobjekt och menyrader där en snabb färgförändring motsvarar det förväntade nativa beteendet (iOS-tabellvystil). Den används mer sällan i anpassade gränssnitt där designers anger opacitetsbaserad återkoppling.

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

export default function ListItem({ title, subtitle, onPress }) {
  return (
    <TouchableHighlight
      onPress={onPress}
      underlayColor='#f0f0f0' // highlight color when pressed
      activeOpacity={1}        // no opacity change, only highlight
    >
      <View style={styles.row}>
        <Text style={styles.title}>{title}</Text>
        <Text style={styles.subtitle}>{subtitle}</Text>
      </View>
    </TouchableHighlight>
  );
}

const styles = StyleSheet.create({
  row: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', paddingHorizontal: 16, paddingVertical: 14, backgroundColor: '#fff', borderBottomWidth: StyleSheet.hairlineWidth, borderBottomColor: '#eee' },
  title: { fontSize: 16, color: '#222' },
  subtitle: { fontSize: 14, color: '#999' },
});

Förhindra oavsiktliga tryck i ScrollView

I en ScrollView eller FlatList kan ett tryck på Pressable eller TouchableOpacity utlösa onPress när användaren egentligen tänkte rulla. Egenskapen keyboardShouldPersistTaps='handled' på rullningsbehållaren hjälper, och unstable_pressDelay i Pressable lägger till en fördröjning innan ett tryck identifieras. För listor ger inställningen delayPressIn på TouchableOpacity rullningshanteraren prioritet. Genom att förstå prioriteringen mellan pekgester kan du bygga listor som rullar mjukt utan att radtryck oavsiktligt utlöses under rullning.

import { FlatList, TouchableOpacity, Text, View, StyleSheet } from 'react-native';

export default function ScrollableList({ items }) {
  return (
    <FlatList
      data={items}
      keyExtractor={item => item.id}
      renderItem={({ item }) => (
        <TouchableOpacity
          onPress={() => console.log('Item pressed:', item.title)}
          delayPressIn={50}  // give scroll a 50ms head start
        >
          <View style={styles.row}>
            <Text style={styles.title}>{item.title}</Text>
          </View>
        </TouchableOpacity>
      )}
      keyboardShouldPersistTaps='handled'
    />
  );
}

const styles = StyleSheet.create({
  row: { padding: 16, borderBottomWidth: StyleSheet.hairlineWidth, borderBottomColor: '#eee' },
  title: { fontSize: 16 },
});

Skalningsanimering vid tryck med Pressable

Kombinera Pressable med Animated API för att skapa en skalningseffekt vid tryck — ett populärt designmönster där knappen krymper något när användaren håller kvar trycket. Det ger platta gränssnittselement en känsla av fysisk djup. Använd Animated.spring, utlöst av onPressIn och onPressOut. Även om hela Animated API behandlas i en senare kurs visar detta snabba mönster hur Pressable-händelserna onPressIn/Out kan användas tillsammans med en visuell animering för att skapa en genomarbetad och tillfredsställande återkoppling från knappar.

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

export default function SpringButton({ label, onPress }) {
  const scale = useRef(new Animated.Value(1)).current;

  function pressIn() {
    Animated.spring(scale, { toValue: 0.93, useNativeDriver: true, speed: 50 }).start();
  }
  function pressOut() {
    Animated.spring(scale, { toValue: 1, useNativeDriver: true, speed: 50 }).start();
  }

  return (
    <Pressable onPress={onPress} onPressIn={pressIn} onPressOut={pressOut}>
      <Animated.View style={[styles.btn, { transform: [{ scale }] }]}>
        <Text style={styles.label}>{label}</Text>
      </Animated.View>
    </Pressable>
  );
}

const styles = StyleSheet.create({
  btn: { backgroundColor: '#4f86f7', padding: 18, borderRadius: 14, alignItems: 'center' },
  label: { color: '#fff', fontWeight: '700', fontSize: 17 },
});

Bästa praxis för tryckbara komponenter

Följ dessa rekommendationer: ge alltid visuell återkoppling vid tryck (opacitet, färgändring eller skalning — använd aldrig TouchableWithoutFeedback för interaktiva element). Säkerställ en minsta tryckyta på minst 44×44 punkter. Använd accessibilityRole='button' på anpassade tryckbara element så att skärmläsare meddelar dem korrekt. Undvik djup nästling av tryckbara komponenter — nästlade tryckbara komponenter orsakar gestkonflikter; använd mönster med stopPropagation eller strukturera om layouten. Föredra Pressable i ny kod — det är kraftfullare och det rekommenderade valet framöver enligt React Native-teamet.

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

// Best-practice accessible button
export default function AccessibleButton({ label, onPress, disabled }) {
  return (
    <Pressable
      onPress={onPress}
      disabled={disabled}
      accessibilityRole='button'
      accessibilityState={{ disabled }}
      accessibilityLabel={label}
      hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }}
      style={({ pressed }) => [
        styles.btn,
        pressed && styles.pressed,
        disabled && styles.disabled,
      ]}
    >
      <Text style={styles.label}>{label}</Text>
    </Pressable>
  );
}

const styles = StyleSheet.create({
  btn: { minWidth: 44, minHeight: 44, backgroundColor: '#4f86f7', paddingHorizontal: 20, borderRadius: 10, alignItems: 'center', justifyContent: 'center' },
  pressed: { opacity: 0.75, transform: [{ scale: 0.97 }] },
  disabled: { backgroundColor: '#aac4f7' },
  label: { color: '#fff', fontWeight: '700' },
});

Ikonknappar och FAB:er

En Floating Action Button (FAB) är en absolut positionerad, cirkelformad knapp som visas ovanpå allt innehåll för att utlösa den primära åtgärden på en skärm. Använd position: 'absolute', bottom och right (eller end för stöd för RTL) för att förankra den längst ned till höger på skärmen. Omslut cirkeln i en Pressable eller TouchableOpacity med skugga/elevation för att skapa djup. Ikonknappar, som en bakåtpil, ett stängningskryss eller en filterikon, följer samma regel om en minsta tryckyta på 44×44 genom att använda hitSlop när den visuella storleken är mindre.

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

export default function FAB({ onPress, icon = '+' }) {
  return (
    <TouchableOpacity
      style={styles.fab}
      onPress={onPress}
      activeOpacity={0.85}
      accessibilityRole='button'
      accessibilityLabel='Add new item'
    >
      <Text style={styles.icon}>{icon}</Text>
    </TouchableOpacity>
  );
}

const styles = StyleSheet.create({
  fab: {
    position: 'absolute',
    bottom: 24,
    right: 24,
    width: 60,
    height: 60,
    borderRadius: 30,
    backgroundColor: '#4f86f7',
    alignItems: 'center',
    justifyContent: 'center',
    // Shadow iOS
    shadowColor: '#4f86f7',
    shadowOffset: { width: 0, height: 4 },
    shadowOpacity: 0.4,
    shadowRadius: 8,
    // Shadow Android
    elevation: 8,
  },
  icon: { color: '#fff', fontSize: 28, fontWeight: '300', lineHeight: 32 },
});

Snabbkontroll

Testa dina kunskaper om begreppen inom React Native Mobile Development från den här lektionen.

Sammanfattning av lektionen

I den här lektionen lärde du dig att TouchableOpacity ger opacitetsbaserad återkoppling vid tryck och används brett i befintliga kodbaser, att Pressable är det moderna API:et med funktionsbaserade dynamiska stilar och mer exakt händelsekontroll och att hitSlop utökar tryckområdet för små interaktiva element. Härnäst utforskar vi växlare, omkopplare och kryssrutor.

Gratis att börja

Lär dig JavaScript med en AI-lärare – gratis

Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.

Kurser
30
Lektioner
120

Vanliga frågor

Är lektionen ”Tryckhantering med TouchableOpacity och Pressable” gratis?

Ja – du kan läsa vilka 3 lektioner som helst i lärvägen React Native Academy, inklusive ”Tryckhantering med TouchableOpacity och Pressable”, kostnadsfritt i sin helhet här på webben. Därefter låser CoddyKit PRO upp alla lektioner, plus interaktiv övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Kursen i React Native Academy innehåller totalt 4 lektioner.

Vad lär jag mig i ”Tryckhantering med TouchableOpacity och Pressable”?

Lägg till återkoppling vid tryck på UI-element med TouchableOpacity och det nyare API:t Pressable, inklusive visuell återkoppling vid tryckning och när tryckningen släpps. Ni övar på React Native Academy med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.

Behöver jag någon erfarenhet för att börja lära mig React Native Academy?

Du behöver inga förkunskaper. Utbildningen i React Native Academy på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 2 av 4.

Hur lång tid tar lektionen ”Tryckhantering med TouchableOpacity och Pressable”?

De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.

Kan jag skriva och köra kod i den här React Native Academy-lektionen?

Ja. Varje React Native Academy-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.

Alla lektioner i den här kursen

  1. Grunderna i TextInput och tangentbordstyper
  2. Tryckhantering med TouchableOpacity och Pressable
  3. Växlare, switchar och kryssrutor
  4. Bygga ett enkelt inloggningsformulär
← Tillbaka till React Native Academy