ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • React Native: Scrollable Tab View 구현하기
    개발/리액트 네이티브 2021. 1. 19. 13:43

    탭 관련 라이브러리 없이 javascript와 react hooks로 스크롤러블 탭 뷰를 구현해보는게 목표.

     

    구현 해보고 싶은 2가지 기능: 

    1. 탭 지원 

    2. 탭 뷰 스크롤 제스쳐 지원

    3. 탭 메뉴 애니메이션 처리

     

    일단 탭 컴포넌트를 만들어서 사용할 때는 간단하게 사용하고 싶었다.

    <ScrollableTab tabBarUnderlineStyle={BodocBlue} renderTabBar={() => <ScrollableTabBar />}>
     <Page1 tabLabel="One" />
     <Page2 tabLabel="Two" />
     <Page3 tabLabel="Three" />
    </ScrollableTab>

    크게 부모 탭 컴포넌트가 감싸고 자식으로는 탭뷰를 넣는 구조가 좋을 것 같다고 생각했다.

    그럴라면 일단 필수적으로 React.Child를 활용해야했다.

     

    <ScrollableTab>에서 React.FC로 children 받으므로 children을 활용해보자!

     

    탭 뷰 구성하는 함수 만들기:

    탭 뷰를 구성하는 작은 단위의 함수를 만들어주었다.

    <ScrollableTab /> 안에 들어있는 Child만큼 반복문을 돌려주며, 키 값을 만들어준 뒤 <TabView />를 반환 시켜준다.

    const composeTabView = () => {
    	return React.Children.map(children, (chlid, idx)=>{
        	let key = makeTabViewKey(child, idx);
            return <TabView key={key} style={{width: containerWidth}}>{child}</TabView>
        }
    }

     

    탭 매뉴, 탭 뷰를 렌더링하기:

    composeTabView()를 통해 나온 리턴값을 tabview 변수에 담아주고 최종적으로 탭뷰를 렌더링하는 함수를 만들어주었다.

    첫 번째는 renderTabBar()와 renderTabView() 2가지의 그 다음 작은 단위의 함수를 만들어주는 것이다.

    // 탭
    const renderTabBar = (props) => {
      return <DefaultTabBar {...props} />;
    };
      
    // 탭뷰
    const renderTabView = () => {
      const tabview = composeTabView();
      return (
          <Animated.ScrollView
          ref={TabViewRef}
          horizontal
          pagingEnabled
          onScroll={Animated.event([{ nativeEvent: { contentOffset: { x: scrollX } } }], { useNativeDriver: true })}
          keyboardDismissMode="on-drag"
          scrollEventThrottle={16}
          directionalLockEnabled>
          {tabview}
        </Animated.ScrollView>
      );
    };

     

    렌더:

    [...]
    return (
       <View ref={contentView} style={{ flex: 1 }} onLayout={(e: any) => handleLayout(e)}>
         {renderTabBar(tabBarProps)}
         {renderTabView()}
       </View>
     );
    [...]

    renderTabBar()에 들어가는 인자값으로 탭 매뉴를 구성하는 프롭스를 객체로 보내주었다.

    만든 객체에 추가되는 속성을 넣어주면서 속성을 관리해주었다.

    // 탭 바를 이루는 프롭스
    let tabBarProps = {
        goToPage: goToPage,
        tabs: React.Children.map(children, (child: React.ReactNode) => child?.props.tabLabel),
        activeTab: currentPage,
        setCurrentPage: setCurrentPage,
        scrollX: scrollX,
        scrollValue: scrollValue,
        containerWidth: containerWidth,
    };
    
    // 탭 매뉴 배경 속성
    if (tabBarBackgroundColor) {
        tabBarProps.backgroundColor = tabBarBackgroundColor;
    }
    
    // 탭 매뉴 활성화 시 텍스트 색상 속성
    if (tabBarActiveTextColor) {
        tabBarProps.activeTextColor = tabBarActiveTextColor;
    } else {
        tabBarProps.activeTextColor = BodocBlue;
    }
    
    // 탭 매뉴 비활성화 시 텍스트 색상 속성
    if (tabBarInactiveTextColor) {
        tabBarProps.inactiveTextColor = tabBarInactiveTextColor;
    } else {
        tabBarProps.inactiveTextColor = BodocGray;
    }
    
    // 탭 매뉴 텍스트 스타일 속성
    if (tabBarTextStyle) {
    	tabBarProps.textStyle = tabBarTextStyle;
    }
    
    // 탭 메뉴 언더바 스타일 속성
    if (tabBarUnderlineStyle) {
      tabBarProps.underlineStyle = tabBarUnderLineStyle;
    } else {
      tabBarProps.underlineStyle = BodocBlue;
    }

    이러한 속성은 실제적으로 <ScrollableTab /> 태그에 계속 추가해주면서 사용할 수 있게 된다.: 

     

     

     

    결과

     

     

     

    보완해야 할 점과 느낀점:

    스크롤 탭 UI를 개발하면서 React 최상위 API를 학습하는 좋은 계기가 되었다.

    조금 더 소스를 최적화 해보는 작업을 하면서 메뉴 탭 애니메이션 처리를 보완할 예정이다.

    그리고 defaultTabBar말고 스크롤되는 TabBar도 추가할 것이다.

     

    + 탭 메뉴 애니메이션 추가:

     

     

      const tabUnderlineStyle: any = {
        position: 'absolute',
        width: containerWidth / numberOfTabs,
        height: 4,
        backgroundColor: activeTextColor,
        bottom: 0,
      };
      const left = scrollValue.interpolate({
        inputRange: [0, 1],
        outputRange: [0, containerWidth / numberOfTabs],
      });
    

     

Designed by Tistory.