react-native styleSheet

dev bourgeois·2024년 8월 16일

React-Native 개발

목록 보기
5/16
post-thumbnail

가운데 정렬하기

alignItems: 'center' 속성을 부모 컨테이너에 추가하면 된다.
만약 부모 컨테이너가 Flexbox 레이아웃을 사용하고 있다면, alignItems: 'center'ustifyContent: 'center'를 사용하여 자식을 가운데에 배치할 수 있다.

버튼 하나를 고정시켜야 되는데 옆에 있는 이미지의 배치에 따라서 버튼 위치가 달라지는 문제가 발생했다. 🤔

❇️ 해결 방법
ScrollView 내에서 next 버튼의 위치를 고정시키는 대신,

View 요소를 사용하여 스크롤 가능한 영역과 고정된 영역을 나눴다. 이렇게 하면 next 버튼이 항상 고정되게 할 수 있다.

  • outerContainer 추가: 전체 화면을 감싸는 View를 추가하여 ScrollView와 고정된 하단 버튼을 분리했다.
    outerContainer: {
      flex: 1,
      backgroundColor: 'white',
    },

수정 전 코드

import React, {useState, useEffect} from 'react';
import {
  View,
  Text,
  StyleSheet,
  Image,
  TouchableOpacity,
  ScrollView,
  Modal,
  TouchableWithoutFeedback,
  Alert,
} from 'react-native';
import {useNavigation, useRoute} from '@react-navigation/native';
import {useSelector, useDispatch} from 'react-redux';
import {assignHashTag} from '../../api/HashTagAssign';
import {HashTagListCheck} from '../../api/HashTagListCheck';

const Filter4 = () => {
  const navigation = useNavigation();
  const route = useRoute(); // useRoute 훅을 사용하여 경로 정보 가져오기
  const {groupedImages} = route.params; // Filter3에서 전달된 데이터(여러 그룹 이미지들)
  const [modalVisible, setModalVisible] = useState(false);
  const [currentGroupId, setCurrentGroupId] = useState(null);
  const [currentGroupImages, setCurrentGroupImages] = useState([]); // 현재 그룹의 모든 이미지 저장
  const [selectedTags, setSelectedTags] = useState([]); // 각 그룹의 선택된 해시태그 저장
  const hashtagList = useSelector(state => state.HashTagReducer.hashtagList); // 해시태그 목록을 가져옴
  const dispatch = useDispatch();

  const handleNavigation = () => {
    navigation.navigate('Filter5', {
      groupedImages,
    });
  };

  // 해시태그 목록 요청
  useEffect(() => {
    dispatch(HashTagListCheck());
  }, [dispatch]);

  // 이미지 그룹 클릭할 때 호출 -> 현재 그룹 id, 이미지 저장
  const handleGroupPress = groupId => {
    setCurrentGroupId(groupId); // 선택한 그룹 ID 저장
    setCurrentGroupImages(groupedImages[groupId]); // 현재 그룹의 모든 이미지 저장
    setModalVisible(true);
  };

  // 해시태그를 선택할 때 호출 -> 선택한 해시태그 저장 및 API 호출
  const handleSelectTag = async tag => {
    const imageUrls = currentGroupImages.map(url => url.split('?')[0]);
    try {
      const requestBody = {
        imageUrls,
        hashtagId: tag.id,
      };
      const data = await assignHashTag(requestBody);
      console.log('해시태그 저장 성공:', data);
      setModalVisible(false);
    } catch (error) {
      console.error('해시태그 저장 중 오류 발생:', error);
      Alert.alert(
        'Error',
        해시태그 저장 중 오류가 발생했습니다: ${error.message},
      );
    }
  };

  return (
    <ScrollView contentContainerStyle={styles.container}>
      <View style={styles.header}>
        <Image
          style={styles.step_3}
          source={require('../../assets/icon/step_3.png')}
          resizeMode="contain"
        />
        <Text style={styles.text}>그룹을 클릭하고 해시태그를 지정하세요!</Text>
      </View>

      <View style={styles.gridContainer}>
        {groupedImages.map((group, index) => (
          <React.Fragment key={index}>
            {index % 2 === 0 && index !== 0 && (
              <View style={styles.separator} />
            )}
            <View style={styles.imageContainer}>
              <TouchableOpacity
                style={styles.imageWrapper}
                onPress={() => handleGroupPress(index)}>
                <Image
                  source={{uri: group[0]}} // 첫 번째 이미지를 썸네일로 사용
                  style={styles.image}
                />
                <Text style={styles.imageCount}>
                  {${group.length}} {/* 이미지 개수*/}
                </Text>
              </TouchableOpacity>
            </View>
          </React.Fragment>
        ))}
      </View>
      {modalVisible && (
        <Modal visible={modalVisible} animationType="slide" transparent={true}>
          <TouchableWithoutFeedback onPress={() => setModalVisible(false)}>
            <View style={styles.modalBackground}>
              <TouchableWithoutFeedback>
                <View style={styles.modalContainer}>
                  <ScrollView contentContainerStyle={styles.hashList}>
                    {hashtagList.map(item => (
                      <TouchableOpacity
                        key={item.id.toString()}
                        style={[
                          styles.hashItem,
                          selectedTags[currentGroupId] === item.text &&
                            styles.selectedHashItem,
                        ]}
                        onPress={() => handleSelectTag(item)}>
                        <Text
                          style={[
                            styles.hashText,
                            selectedTags[currentGroupId] === item.text &&
                              styles.selectedHashText,
                          ]}>
                          {#${item.text}}
                        </Text>
                      </TouchableOpacity>
                    ))}
                  </ScrollView>
                  <View style={styles.modalButtons}>
                    <TouchableOpacity
                      onPress={() => setModalVisible(false)}
                      style={styles.modalButtonContainer1}></TouchableOpacity>
                  </View>
                </View>
              </TouchableWithoutFeedback>
            </View>
          </TouchableWithoutFeedback>
        </Modal>
      )}
      <TouchableOpacity onPress={handleNavigation}>
        <Image // <--  수정 전
          style={styles.next}
          source={require('../../assets/icon/next2.png')}
          resizeMode="contain"
        />
      </TouchableOpacity>
    </ScrollView>
  );
};
...
export default Filter4;
 <Image // <--  수정 전
          style={styles.next}
          source={require('../../assets/icon/next2.png')}
          resizeMode="contain"
        />

버튼 이미지가 ScrollView 안에 있었다.

수정 후 코드

import React, {useState, useEffect} from 'react';
import {
  View,
  Text,
  StyleSheet,
  Image,
  TouchableOpacity,
  ScrollView,
  Modal,
  TouchableWithoutFeedback,
  Alert,
} from 'react-native';
import {useNavigation, useRoute} from '@react-navigation/native';
import {useSelector, useDispatch} from 'react-redux';
import {assignHashTag} from '../../api/HashTagAssign';
import {HashTagListCheck} from '../../api/HashTagListCheck';

const Filter4 = () => {
  const navigation = useNavigation();
  const route = useRoute(); // useRoute 훅을 사용하여 경로 정보 가져오기
  const {groupedImages} = route.params; // Filter3에서 전달된 데이터(여러 그룹 이미지들)
  const [modalVisible, setModalVisible] = useState(false);
  const [currentGroupId, setCurrentGroupId] = useState(null);
  const [currentGroupImages, setCurrentGroupImages] = useState([]); // 현재 그룹의 모든 이미지 저장
  const [selectedTags, setSelectedTags] = useState([]); // 각 그룹의 선택된 해시태그 저장
  const hashtagList = useSelector(state => state.HashTagReducer.hashtagList); // 해시태그 목록을 가져옴
  const dispatch = useDispatch();

  const handleNavigation = () => {
    navigation.navigate('Filter5', {
      groupedImages,
    });
  };

  // 해시태그 목록 요청
  useEffect(() => {
    dispatch(HashTagListCheck());
  }, [dispatch]);

  // 이미지 그룹 클릭할 때 호출 -> 현재 그룹 id, 이미지 저장
  const handleGroupPress = groupId => {
    setCurrentGroupId(groupId); // 선택한 그룹 ID 저장
    setCurrentGroupImages(groupedImages[groupId]); // 현재 그룹의 모든 이미지 저장
    setModalVisible(true);
  };

  // 해시태그를 선택할 때 호출 -> 선택한 해시태그 저장 및 API 호출
  const handleSelectTag = async tag => {
    const imageUrls = currentGroupImages.map(url => url.split('?')[0]);
    try {
      const requestBody = {
        imageUrls,
        hashtagId: tag.id,
      };
      const data = await assignHashTag(requestBody);
      console.log('해시태그 저장 성공:', data);
      setModalVisible(false);
    } catch (error) {
      console.error('해시태그 저장 중 오류 발생:', error);
      Alert.alert(
        'Error',
        `해시태그 저장 중 오류가 발생했습니다: ${error.message}`,
      );
    }
  };

  return (
    <View style={styles.outerContainer}>
      <ScrollView contentContainerStyle={styles.container}>
        <View style={styles.header}>
          <Image
            style={styles.step_3}
            source={require('../../assets/icon/step_3.png')}
            resizeMode="contain"
          />
          <Text style={styles.text}>그룹을 클릭하고 해시태그를 지정하세요!</Text>
        </View>

        <View style={styles.gridContainer}>
          {groupedImages.map((group, index) => (
            <React.Fragment key={index}>
              {index % 2 === 0 && index !== 0 && (
                <View style={styles.separator} />
              )}
              <View style={styles.imageContainer}>
                <TouchableOpacity
                  style={styles.imageWrapper}
                  onPress={() => handleGroupPress(index)}>
                  <Image
                    source={{uri: group[0]}} // 첫 번째 이미지를 썸네일로 사용
                    style={styles.image}
                  />
                  <Text style={styles.imageCount}>
                    {`${group.length}`} {/* 이미지 개수*/}
                  </Text>
                </TouchableOpacity>
              </View>
            </React.Fragment>
          ))}
        </View>
        {modalVisible && (
          <Modal visible={modalVisible} animationType="slide" transparent={true}>
            <TouchableWithoutFeedback onPress={() => setModalVisible(false)}>
              <View style={styles.modalBackground}>
                <TouchableWithoutFeedback>
                  <View style={styles.modalContainer}>
                    <ScrollView contentContainerStyle={styles.hashList}>
                      {hashtagList.map(item => (
                        <TouchableOpacity
                          key={item.id.toString()}
                          style={[
                            styles.hashItem,
                            selectedTags[currentGroupId] === item.text &&
                              styles.selectedHashItem,
                          ]}
                          onPress={() => handleSelectTag(item)}>
                          <Text
                            style={[
                              styles.hashText,
                              selectedTags[currentGroupId] === item.text &&
                                styles.selectedHashText,
                            ]}>
                            {`#${item.text}`}
                          </Text>
                        </TouchableOpacity>
                      ))}
                    </ScrollView>
                    <View style={styles.modalButtons}>
                      <TouchableOpacity
                        onPress={() => setModalVisible(false)}
                        style={styles.modalButtonContainer1}></TouchableOpacity>
                    </View>
                  </View>
                </TouchableWithoutFeedback>
              </View>
            </TouchableWithoutFeedback>
          </Modal>
        )}
      </ScrollView>
      
// ScrollView 에서 분리시켰다.
      <View style={styles.fixedFooter}>
        <TouchableOpacity onPress={handleNavigation}>
          <Image
            style={styles.next}
            source={require('../../assets/icon/next2.png')}
            resizeMode="contain"
          />
        </TouchableOpacity>
      </View>
    </View>
  );
};

버튼 이미지를 ScrollView 에서 분리시키면 된다!

0개의 댓글