[React Native] Development Guides 살펴보기

·2023년 12월 18일
0

React Native

목록 보기
2/2
post-thumbnail

Handling Touches

사용자는 주로 터치를 통해 모바일 앱과 상호작용한다. 버튼 누르기, 목록 스크롤, 지도 확대/축소 등 다양한 동작을 조합하여 사용할 수 있다.
React Native는 모든 종류의 일반적인 제스처를 처리하는 컴포넌트는 물론 포괄적인 제스처 응답 시스템을 제공하여 고급 제스처 인식을 허용한다.

Displaying a basic button

Button은 모든 플랫폼에서 렌더링되는 기본 버튼 컴포넌트를 제공한다.

<Button
	onPress={() => {
      console.log('You tapped the button!')
    }}
    title="Press Me"
/>

iOS에서는 파란색 라벨이 렌더링되고, Android에서는 밝은 텍스트가 포함된 파란색 둥근 사각형이 렌더링된다.

Touchables

기본 버튼이 앱에 적합하지 않은 경우 'Touchables' 중 하나를 사용하여 자신만의 버튼을 만들 수 있다.
'Touchables'한 컴포넌트는 두드리는 동작을 캡처하는 기능을 제공하고 동작이 인식되면 피드백을 표시할 수 있다. 그러나 이러한 컴포넌트는 기본 스타일을 제공하지 않으므로 앱에서 보기 좋게 보이도록 약간의 작업을 수행해야 한다.

  • 일반적으로 웹에서 버튼이나 링크를 사용할 수 있는 모든 곳에서 TouchableHighlight를 사용할 수 있다. 사용자가 버튼을 누르면 보기의 배경이 어두워진다.
  • Android에서 TouchableNativeFeedback을 사용하여 사용자의 터치에 반응하는 잉크 표면 반응 잔물결을 표시하는 것을 고려할 수 있다.
  • TouchableOpacity는 버튼의 불투명도를 줄여 사용자가 누르고 있는 동안 배경이 보이도록 하여 피드백을 제공하는 데 사용할 수 있다.
  • 탭 동작을 처리해야 하지만 피드백을 표시하지 않으려면 TouchableWithoutFeedback을 사용할 수 있다.

사용자가 설정된 시간 동안 뷰를 누르고 있는 것을 감지하고 싶은 경우 Tochables 컴포넌트의 props인onLongPress를 사용할 수 있다.

import {Component} from 'react';
import {
  Alert,
  Platform,
  StyleSheet,
  Text,
  TouchableHighlight,
  TouchableOpacity,
  TouchableNativeFeedback,
  TouchableWithoutFeedback,
  View,
} from 'react-native';

export default class Touchables extends Component {
  _onPressButton() {
    Alert.alert('You tapped the button!');
  }

  _onLongPressButton() {
    Alert.alert('You long-pressed the button!');
  }

  render() {
    return (
      <View style={styles.container}>
        <TouchableHighlight onPress={this._onPressButton} underlayColor="white">
          <View style={styles.button}>
            <Text style={styles.buttonText}>TouchableHighlight</Text>
          </View>
        </TouchableHighlight>

        <TouchableOpacity onPress={this._onPressButton}>
          <View style={styles.button}>
            <Text style={styles.buttonText}>TouchableOpacity</Text>
          </View>
        </TouchableOpacity>

        <TouchableNativeFeedback
          onPress={this._onPressButton}
          background={
            Platform.OS === 'android'
              ? TouchableNativeFeedback.SelectableBackground()
              : undefined
          }>
          <View style={styles.button}>
            <Text style={styles.buttonText}>
              TouchableNativeFeedback{' '}
              {Platform.OS !== 'android' ? '(Android only)' : ''}
            </Text>
          </View>
        </TouchableNativeFeedback>

        <TouchableWithoutFeedback onPress={this._onPressButton}>
          <View style={styles.button}>
            <Text style={styles.buttonText}>TouchableWithoutFeedback</Text>
          </View>
        </TouchableWithoutFeedback>

        <TouchableHighlight
          onPress={this._onPressButton}
          onLongPress={this._onLongPressButton}
          underlayColor="white">
          <View style={styles.button}>
            <Text style={styles.buttonText}>Touchable with Long Press</Text>
          </View>
        </TouchableHighlight>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    paddingTop: 60,
    alignItems: 'center',
  },
  button: {
    marginBottom: 30,
    width: 260,
    alignItems: 'center',
    backgroundColor: '#2196F3',
  },
  buttonText: {
    textAlign: 'center',
    padding: 20,
    color: 'white',
  },
});

Scrolling and swiping

일반적으로 터치 가능한 화면이 있는 기기에서 사용되는 동작에는 스와이프와 팬(하나 이상의 손가락을 움직이는 제스처)이 포함된다. 이를 통해 사용자는 항목 목록을 스크롤하거나 컨텐츠 페이지를 스와이프할 수 있다.

Navigating Between Screens

모바일 앱은 단일 화면으로 구성되는 경우가 거의 없으므로, 여러 화면의 표시 및 전환 관리는 일반적으로 Navigator로 처리된다.
Navigate를 할 경우 React Navigation을 사용하는 것이 좋다. React Navigation은 Android와 iOS 모두에서 일반적인 stack navigation 및 tap navigation 패턴을 제공하는 기능을 갖춘 간단한 Navigate 솔루션을 제공한다.

React Navigation

App.jsNavigationContainer로 감싸야 react-navigation을 사용할 수 있다.

import {NavigationContainer} from '@react-navigation/native';

const App = () => {
  return (
    <NavigationContainer>
      {/* Rest of your app code */}
    </NavigationContainer>
  );
};

export default App;
import {NavigationContainer} from '@react-navigation/native';
import {createNativeStackNavigator} from '@react-navigation/native-stack';

const Stack = createNativeStackNavigator();

const MyStack = () => {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen
          name="Home"
          component={HomeScreen}
          options={{title: 'Welcome'}}
        />
        <Stack.Screen name="Profile" component={ProfileScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
};

이 예에서는 컴포넌트를 사용하여 정의된 Home, Profile 두 개의 화면이 있다.
Stack.Screenoptions props에서 각 화면의 화면 제목과 같은 옵션을 설정할 수 있다.
Stack.Screen 각 화면은 React 컴포넌트인 component props를 사용한다. 이러한 컴포넌트는 다른 화면에 연결하는 다양한 방법이 있는 navigation이라는 속성을 받는다. 예를 들어 navigation.navigate를 사용하여 Profile 화면으로 이동할 수 있다.

const HomeScreen = ({navigation}) => {
  return (
    <Button
      title="Go to Jane's profile"
      onPress={() =>
        navigation.navigate('Profile', {name: 'Jane'})
      }
    />
  );
};
const ProfileScreen = ({navigation, route}) => {
  return <Text>This is {route.params.name}'s profile</Text>;
};

Gesture Responder System

제스처 응답 시스템은 앱의 제스처 라이프사이클을 관리한다. 앱이 사용자의 의도를 결정함에 따라 터치는 여러 단계를 거칠 수 있다.
예를 들어 앱은 터치가 스크롤되는지, 위젯에서 슬라이딩되는지 또는 탭하는지 확인해야 한다. 터치하는 동안에도 변경될 수 있으며, 동시에 여러 터치가 있을 수도 있다.
컴포넌트가 부모 또는 자식 컴포넌트에 대한 추가 지식 없이 이러한 터치 상호 작용들을 협상할 수 있도록 하려면 터치 응답 시스템이 필요하다.

모범 사례

  • Feedback/highlighting : 사용자에게 터치를 처리하는 내용과 제스처를 실행하면 어떤 일이 발생하는지 보여준다.
  • Cancel-ability : 작업을 수행할 때 사용자는 터치 중에 손가락을 드래그하여 작업을 중단할 수 있어야 한다.

TouchableHighlight and Touchable

응답자 시스템은 사용하기 복잡할 수 있다. 따라서 React Native는 'tappable'해야 하는 것들에 대한 추상적인 Touchable 구현을 제공한다. 이것은 응답자 시스템을 사용하고 탭 상호작용을 선언적으로 구성할 수 있게 해준다.
웹에서 버튼이나 링크를 사용하는 곳이라면 어디서나 TouchableHighlight를 사용할 수 있다.

Responder Lifecycle

view는 올바른 협상 방법을 구현함으로써 터치 responder가 될 수 있다. veiw가 responder가 되기를 원하는지 묻는 두 가지 방법이 있다.

  • View.props.onStartShouldSetResponder: evt => true : view가 터치 시작 시 responder가 되기를 원하는지?
  • View.props.onMoveShouldSetResponder: evt => true : responder가 아닌 경우 view의 모든 터치 동작을 요청한다. 이 view가 터치 응답성을 '주장'하기를 원하는지?

view가 true를 반환하고 responder가 되려고 한다면, 다음 중 하나가 발생한다.

  • View.props.onResponderGrant: evt => {} : view는 이제 터치 이벤트에 응답한다. 지금 무슨 일이 일어나고 있는지 사용자에게 강조하고 보여줄 때 이다.
  • View.props.onResponderReject: evt => {} : 다른 것이 지금 responder이므로 해제하지 않는다.

view가 응답하는 경우 다음 핸들러를 호출할 수 있다.

  • View.props.onResponderMove: evt => {} : 사용자가 손가락을 움직이고 있다.
  • View.props.onResponderRelease: evt => {} : 터치가 끝나면 실행된다. 즉 'touchUp'이다.
  • View.props.onResponderTerminationRequest: evt => true : 다른 것이 responder가 되길 원한다. 이 view가 responder를 해제해야 하는지? true를 반환하면 해제가 허용된다.
  • View.props.onResponderTerminate: evt => {} : responder를 view에서 가져온다. onResponderTerminationRequest 호출 후 다른 view에서 가져오거나 묻지 않고 OS에서 가져갈 수 있다. (iOS의 제어센터, 알림센터에서 발생)

evt는 다음과 같은 형태의 합성 터치 이벤트이다.

  • nativeEvent
    - changedTouches : 마지막 이벤트 이후 변경된 모든 터치 이벤트 배열
    - identifier : 터치의 ID
    - locationX : 요소를 기준으로 한 터치의 X 위치
    - locationY : 요소를 기준으로 한 터치의 Y 위치
    - pageX : 루트 요소를 기준으로 한 터치의 X 위치
    - pageY : 루트 요소를 기준으로 터치의 Y 위치
    - target : 터치 이벤트를 수신하는 요소의 노드 ID
    - timestamp : 속도 계산에 유용한 터치 시간 식별자
    - touches : 화면의 모든 현재 터치 배열

Capture ShouldSet Handlers

onStartShouldSetResponderonMoveShouldSetResponder는 가장 깊은 노드가 먼저 호출되는 버블링 패턴으로 호출된다. 즉, ShouldSetResponder 핸들러에 대해 여러 view가 true를 반환하면 가장 깊은 컴포넌트가 responder가 된다. 이렇게 하면 모든 컨트롤과 버튼을 사용할 수 있으므로 대부분의 경우 바람직하다.

그러나 부모나 responder가 되길 원할 수도 있는데, 이는 캡처 단계를 사용하여 처리할 수 있다. 응답자 시스템이 가장 깊은 컴포넌트에서부터 버블링되기 전에 캡처 단계를 수행하고 ShouldSetResponderCapture가 실행된다. 따라서 상위 view가 터치 시작 시 하위 view가 responder가 되는 것을 방지하려면 true를 반환하는 onStartShouldSetResponderCapture 핸들러가 있어야 한다.

  • View.props.onStartShouldSetResponderCapture: evt => true
  • View.props.onMoveShouldSetResponderCapture: evt => true
profile
개발을 개발새발 열심히➰🐶

0개의 댓글