React Native Navigation Patterns

블로그 이미지

클라인STR

,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
 
import {Navigation} from 'react-native-navigation';
import Welcome from './src/Welcome';
import SignIn from './src/SignIn';
import SignUp from './src/SignUp';
 
 
 
Navigation.registerComponent('Welcome', ()=>Welcome );
Navigation.registerComponent('SignIn', ()=>SignIn );
Navigation.registerComponent('SignUp', ()=>SignUp );
 
Navigation.events().registerAppLaunchedListener(()=>{
    Navigation.setRoot({
        root: {
            stack : {
                id:'AppStack',
                children : [
                    {
                        component : {
                            name'Welcome',
                            options:{
                                topBar : {
                                    title:
                                    {
                                        text'Welcome'
                                    }     
                                }
                                
                            }
                        },
                    }
                ]
            }
        }
    })
});
cs

[index.js]


index.js 파일을 root: 부분에 statck 항목을 추가한다. 

Navigation.setRoot() 함수는 탭 또는 스택 또는 이 두 가지의 조합과 같은 모든 종류의 레이아웃에 대한 속성을 받는다.

stack 은 RNN (react-native-navigation) 에서 레이아웃의 한종류이다. 

자식 레이아웃을 지원한다. stack은 둘 이상의 화면으로 초기화 될수 있고 마지막 화면이 스택 맨위에 표시된다.


const stack = {

  children: [

    {

      component: {}

    },

    {

      component: {}

    }

  ],

  options: {}

}




Welcome.js 파일을 아래와 같이 수정한다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import React, {Component} from "react";
import {
    View,
    Text,
    StyleSheet,
    Button
} from "react-native";
import {Navigation} from "react-native-navigation";
 
 
class WelcomScreen extends Component {
 
    goToScreen = (screenName) => {
        Navigation.push(this.props.componentId,{
            component : {
                name: screenName
            }
        })
    }
 
    render() {
 
        return (
            <View style={styles.container}>
                <Button title='Sign In' onPress={()=> this.goToScreen('SignIn')} />
                <Button title='Sign Up' onPress={()=> this.goToScreen('SignUp')} />
            </View>
        );
    }
}
 
 
export default WelcomScreen;
 
 
const styles = StyleSheet.create({
    
    container : {
        flex : 1,
        alignItems: 'center',
        justifyContent : 'center'
    }
});
cs

[Welcome.js]



push(componentId, layout)



Navigation Stack에서 새로운 화면을 추가할때 사용하는 메서드이다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import React, {Component} from "react";
import {
    View,
    Text,
    StyleSheet,
    Button
} from "react-native";
import {Navigation} from "react-native-navigation";
 
class SignIn extends Component {   
 
    render() {
 
        return (
            <View style={styles.container}>
                <Text>SignIn</Text>
            </View>
        );
    }
}
 
 
export default SignIn;
 
 
const styles = StyleSheet.create({
    
    container : {
        flex : 1,
        alignItems: 'center',
        justifyContent : 'center'
    }
});


cs

[SignIn.js]



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import React, {Component} from "react";
import {
    View,
    Text,
    StyleSheet,
    Button
} from "react-native";
 
 
class SignUp extends Component {
    render() {
 
        return (
            <View style={styles.container}>
                <Text>SignUp</Text>
            </View>
        );
    }
}
 
 
export default SignUp;
 
 
const styles = StyleSheet.create({
    
    container : {
        flex : 1,
        alignItems: 'center',
        justifyContent : 'center'
    }
});
cs

[SignUp.js]

블로그 이미지

클라인STR

,

componentDidAppearcomponentDidDisappear 는 component가 나타나고 사라질때 호출되는  React Native Navigation LifeCycle 콜백메서드이다.  (Navigation.events().bindComponent(this) 사용되어진 뒤에 )


React의 componentDidMount, componentWillUnmount 마찬가지로 다른 점은 사용자가 실제로 마운트되어 있는지 여부뿐만 아니라 문제의 구성 요소를 실제로 볼 수 있는지 여부를 나타낸다. React Native Navigation 성능을 최적화하는 방식 때문에, 컴포넌트는 실제로 레이아웃의 일부분으로 탑재되지만, 항상 보이지는 않는다.(예를 들어 다른 화면이 그위에 푸쉬된경우 )


이들을 사용하려면 다른 React LifeCycle 함수와 같이 구성요소에 구현하기 만하면 모든 기능을 자동으로 호출하는 탐색 이벤트 모듈에 화면을 바인딩 한다.


 ScreenLifeCycle 예제 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import React, {Component} from "react";
import {
    View,
    Text,
    StyleSheet,
    Button
} from "react-native";
import {Navigation} from "react-native-navigation";
 
class SignIn extends Component {
 
    constructor(props) {
        super(props);
        Navigation.events().bindComponent(this);
        this.state = {
          text'nothing yet'
        };
      }
 
      componentDidAppear() {
        alert('componentDidAppear');        
      }
    
      componentDidDisappear() {
       alert('componentDidDisappear');
      }
 
    render() {
 
        return (
            <View style={styles.container}>
                <Text>SignIn</Text>
            </View>
        );
    }
}
 
 
export default SignIn;
 
 
const styles = StyleSheet.create({
    
    container : {
        flex : 1,
        alignItems: 'center',
        justifyContent : 'center'
    }
});

cs

[SignIn.js]


[실행화면]


참고 : https://wix.github.io/react-native-navigation/#/docs/Usage?id=screen-lifecycle

블로그 이미지

클라인STR

,



react-native-navigation 줄여서 RNN을 이용하여 UI를 화면에 표시해보자 

먼저 리액트네이티브 react-native-navigation 개발환경 설정 을 통해서 프로젝트를 생성하고 RNN을 사용하기 위한 설정이 필요하다 .



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// /** @format */
 
// import {AppRegistry} from 'react-native';
// import App from './App';
// import {name as appName} from './app.json';
 
// AppRegistry.registerComponent(appName, () => App);
 
 
import {Navigation} from 'react-native-navigation';
 
import Welcome from './Welcome';
 
Navigation.registerComponent('Welcome', ()=>Welcome );
 
Navigation.events().registerAppLaunchedListener(()=>{
    Navigation.setRoot({
        root: {
            component: {
                name'Welcome'
            }
        }
    })
});

cs


[index.js]


index.js 에서 프로젝트 생성시 자동으로 생성되는 1~7번째 라인 구문을 주석처리한다. 10번째 줄에 react-native-navigation에있는  Navigation 객체를 import 하였다.  12번째 줄에 Welcome.js 파일을 import 하였다.

14번째 라인에 Navigation 객체에 registerComponet메서드를 이용하여 페이지를 등록하였고, 16번째 라인에 Navigation.events().registerAppLaunchedListenerI() 메서드를 이용하여 root 화면을 등록하였다.



Navigation.events().registerAppLaunchedListener(() => {


});

앱이 실행되면 onAppLaunched 이벤트가 실행된다. 이 이벤트는  애플리케이션 레이아웃이 초기화될때 사용된다. 



registerComponent(screenID, generator)


앱에서 사용할화면 구성요소를 등록하며, screenID는 고유한 이름으로 등록되어야 한다. (중복되면안됨) generator 에 경우는 React.Component 또는 React.PureComponent를 확장하는 일반적인 React구성요소가 올 수 있다. 




registerAppLaunchedListener(callback)

앱이 실행되면 registerAppLaunchedListener 이벤트가 호출된다. 

Navigation객체의 setRoot 명령을 통해서 원하는 레이아웃으로 앱을 초기화 할 수 있다. root에 컴포넌트 이름으로 해당React 요소를 로딩한다. 



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import React, {Component} from "react";
import {
    View,
    Text,
    StyleSheet
} from "react-native";
 
 
class WelcomScreen extends Component {
    render() {
 
        return (
            <View style={styles.container}>
                <Text>WelcomeScreen</Text>
            </View>
        );
    }
}

 
 
const styles = StyleSheet.create({
    
    container : {
        flex : 1,
        alignItems: 'center',
        justifyContent : 'center'
    }
});

export default WelcomScreen;

cs

[Welcome.js]

React.Component 상속하여 Welcome 화면을 만들었다.


react-native run-ios 명령어를 이용하여 실행해본다.


참고 : https://wix.github.io/react-native-navigation/#/docs/Usage?id=the-basics

블로그 이미지

클라인STR

,


http://flexboxfroggy.com/ 접속하면 1단게부터 24단게 까지 게임을 통해서 flexBox 레이아웃을 연습할 수 있다.  

FlexBox Froggy 게임해답 (마우스로 아래 영역을 긁으세요)

1. justify-content:flex-end;

2. justify-content:center;

3.justify-content:space-around;

4. justify-content:space-between;

5. align-items:flex-end;

6. justify-content:center;

    align-items:center;

7. justify-content:space-around;

   align-items:flex-end;

8.flex-direction:row-reverse;

9. flex-direction:column;

10. flex-direction:row-reverse;

      justify-content:flex-end;

11. flex-direction:column;

     justify-content:flex-end;

12. flex-direction:column-reverse;

     justify-content:space-between;

13. justify-content:center;

     flex-direction:row-reverse;

     align-items:flex-end;

14. order:1;

15. order:-3;

16. align-self:flex-end;

17. order:2;

     align-self:flex-end;

18. flex-wrap:wrap;

19. flex-wrap:wrap;

     flex-direction:column;

20. flex-flow:column wrap;

21. align-content:flex-start;

22. align-content:flex-end;

23. flex-direction:column-reverse;

      align-content:center;

24. flex-direction:column-reverse;

      flex-wrap:wrap-reverse;

      align-content:space-between;

      justify-content:center;



블로그 이미지

클라인STR

,

Flexbox 모델을 사용하기위해서는 flex-container를 정의 한다음 

display:flex 또는 display:inline-flex 설정하면된다. 


1
2
3
4
5
<ul> <!--parent element-->
  <li></li> <!--first child element-->
  <li></li> <!--second child element-->
  <li></li> <!--third child element-->
</ul>
cs


1. Flexbox 컨테이너와 Flexbox 아이템 


ul에 display:flex 속성을 준경우 Flex Container 라고하며 , ul 내부에 있는 li 앨리먼트들을 Flex Container 내부에 있는 Flexbox Item 이라고 한다. 이때 주의할점은 Flexbox item이되는것들은 <li>요소들이며 li요소내부는 적용이 되지 않는다는 점이다.  FlexBox Item 항목에 height값을 주지 않으면 기본값이 stretch 라 컨테이너를 꽉 채우게된다. 



2. flexbox 주축과 교차축 


flexbox에는 주축(Main Axis)과 교차축 (Cros Axis) 이라는 두 개의 축이 존재한다. 




 flex-direction 디폴트값은 row(행)이므로  주축은 (Main Axis)는 행값을 기준으로 한다. cross axis라고 하면 주축에 정확히 교차하는 교차축을 얘기한다. 


여기서 flex-direction 값을 column(열)로 바꾸면 주축과 교차축에 값이 아래와 같이 반대로 바뀐다. 





3.justify-content 

 justify-content 주축에(Main Axis) 대한 정렬이다. 

space-between a, b 사이의 공간 b, c 사이를 동일한 간격으로 위치시킨다. 반면에  space-around는 a, b, c 사이의 공간을 동일하게 둘러싸는 것을 얘기한다. 즉 space-between 은 박스와 박스 사이에서만 공간이 생기지만 space-around인경우는 블록과 박스 박스와 박스 사이에 균등하게 공간이 생긴다. (공간을 둘러싼다는게 어떤느낌인지 와닿지가 않아서 처음에 이해하기 힘들었음)


justify-content 속성중 space-evenly 사용하면, 블록과 a,b,c 공간이 모두 균등하게 위치할 수 있다.


4.flex-wrap (nowrap, wrap, wrap-reverse)  

flexBox에서는 기본적으로 박스의 크기가 넘칠경우 박스 공간을 뚫고 나가는 식으로 레이아웃이 배치가된다. (flex-wrap:nowrap 디폴트값이므로)

부모 컨테이너 속성에 flewx-wrap : wrap  속성을 사용할경우 박스공간 아래로 항목들이 자동으로 떨어진다. 



flexBox인경우 width값에 상관없이 부모컨테이너에 항목을 넘어가더라도 flex Item이 자동으로 정렬되게 되는데 이는 flex-shrink 값이 1이 기본으로 설정되어 있기 때문이다. 


5. flex-basis

flexBox에서 width 값대신에 flex-basis 속성을 사용하여 값을 적용한다. 


 6.flex-grow & flex-shrink 


flexItem 항목을 늘려주거나 줄여줄때 사용하는 속성이 flex-grow, flex-shrink 이다. 


flex : flex-grow , flex-shrink, flex-basis  형태로 축약해서 쓸 수 있다.


7. align-content 

align-content 는 교차축에 대한정렬이다.  속성으로는 flex-start, flex-end, center, space-between, space-around, stretch.

flex-item 덩어리 전체가 교차축을 기준으로 정렬이 된다. 



8.align-items

align-content 와는 다르게 개별 아이템항목을 정렬할때 사용하는 속성이 align-items 이다. align-items 역시 교차축 기준으로 상 하 가운데 설정할 수 있다. 

가운데 정렬을 하기위해서는 justify-content속성과 align-items 속성을 사용할 수 있다.


9. order

order 속성을 사용하면 flexItem 항목을 순서를 변경할 수 있다.


10. align-self 

flexItem 개별 속성을 정렬할때 사용하는 속성이 align-self 이다. 요소 값은 align-items가 사용하는 값들을 인자로 받는다. 


11. flex-flow


참고 원문

FlexBox기본개념

FlexBox 이해

블로그 이미지

클라인STR

,

React-native 에서 화면 간의 이동을 하기위해서는 사용하는 대표적인? 방법으로는 react-navigation 과 react-native-navigation  있다. 이중에서 react-native-navigation 사용하기 위해서 개발 환경을 설정해보기로 한다. 


1. RN프로젝트를 생성하고 해당폴더에서 아래명령어로 library를 설치한다.


npm install --save react-native-navigation



2.  Xcode를 실행한후 RN프로젝트를 Open 하고 프로젝트 네비게이션을 선택한후 
Libraries > Add files to "프로젝트명" 을 선택한다. 
node_modules/react-native-navigation/lib/ios/ReactNativeNavigation.xcodeproj 를 선택한다.



3. Project Navigator (왼쪽 패널)에서 프로젝트 (위)를 클릭 한 다음 대상 행 (오른쪽 창의 왼쪽 열에있는 "프로젝트 및 대상 목록")을 클릭하고 Build Phases 라이브러리가있는 링크 바이너리 섹션에 libReactNativeNavigation.a를 추가한다.






4. IOS 설정에 경우  AppDelegate.m 파일을 편집해야한다. AppDelegate.m 파일을 선택하고 파일 내용을 아래와 같이 수정한다.




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#import "AppDelegate.h"
 
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
 #import <ReactNativeNavigation/ReactNativeNavigation.h>
 
@implementation AppDelegate
 
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  NSURL *jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
  [ReactNativeNavigation bootstrap:jsCodeLocation launchOptions:launchOptions];
  
  return YES;
}
 
@end
 
cs


파일 선택시  RCTBundleURLProvider.h file not fonud  에러메시지가 나타날경우 아래와 같이조치를 해준다. 프로젝트 폴더에 해당명렁어를 실행하고 


npm install -g react-native-git-upgrade


Xcode 에서 Product -> Scheme -> Manage Schemes 선택하고 + 기호를 선택하여 React를 추가한다음 Shread 열에 체크를 선택한다. 


이때 Target을 React로 선택한다.







참고 https://wix.github.io/react-native-navigation/#/docs/Installing


유트브에서 React Native Navigation 설치 영상을 참고해도 좋다.



블로그 이미지

클라인STR

,

미세먼지 농도를 표시할려는 앱을 현재 구상중인데 아래와 같은 원형차트와 비슷한느낌을 내는 라이브러리를 찾아서 소개하고자 한다.


차트 모양이 완전히 똑같진 않지만 진행상태를 원형 상태바를 유지하고 있다. 


리액트네이티브 프로젝트를 생성하고 npm 명령어를 이용하여 라이브러리를 설치한다.


npm install --save react-native-progress-circle




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import React, {Component} from 'react';
import {Platform, StyleSheet, Text, View} from 'react-native';
import ProgressCircle from 'react-native-progress-circle'
 
export default class App extends Component {
    render() {
      return (
        <View style={{ justifyContent : 'center',  height : 60,  alignItems : 'center', flexDirection: 'column', flex : 1 }} >
            <ProgressCircle
                percent={30}
                radius={100}
                borderWidth={30}
                color="#06BF35"
                shadowColor="#CDF2D7"
                bgColor="#fff">
                <Text style={{ fontSize: 30 , fontWeight : 'bold' }}>{'30'}</Text>
            </ProgressCircle>
          </View>
      )
  }
}
cs

[App.js]


프로젝트를 실행하면 아래와 같이 Progress Cirlce 원이 실행된다.



주요속성으로는 아래와 같은속성이 있다.


percent : 진행상태를 나타낼 퍼센트 값을 입력한다. Number Type 

radius :  Circle에 크기를 나타낸다.


[radius 값이 50일때 원크기]


[radius 값이 100일때의 원크기]


borderWidth :  Circle 에 두깨를 나타낸다. 값이 클수록 두꺼워진다. 

color : border color

shadowColor : border에 백그라운드 컬러 (바로 위에 스샷은 회색이다.)

bgColor : 원안쪽에 컬러이다. (바로 위에 스샷에 30%글자 영역이 bgColor 영역이다.)



참고 

https://cmichel.io/react-native-progress-circle

https://github.com/MrToph/react-native-progress-circle#readme



블로그 이미지

클라인STR

,