【React Native】よく使うスタイル実装まとめ【StyleSheet】

React Nativeでどう実装するんだっけ？と、よく検索する内容とその結果をまとめました。
編集リクエストウェルカムです。

※追記↓
codeSandboxに実装サンプルを載せました。
react-native-webで変換した内容ですのでネイティブと差異あると思いますが参考程度にどうぞ。
<a href="https://codesandbox.io/s/mmk53ww05j?fontsize=14">
  <img alt="Edit react-native styles Gallery" src="https://codesandbox.io/static/img/play-codesandbox.svg">
</a>

## 配置

### Vertical Align: 縦方向整列
**1.alignItems:**

```jsx
const style = StyleSheet.create({
  container: {
    alignItems: 'center'
  },
});

const Vertical = () => (
  <View style={style.container}>
    <Text>A</Text>
    <Text>B</Text>
  </View>
);
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/103475/8cf690ad-087b-28a5-73e8-5f68d72cf3e4.png)

**2. flexDirection: `column`:**

```jsx
  <View style={{ flexDirection: 'column' }}>
    <Text>A</Text>
    <Text>B</Text>
  </View>
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/103475/2c72f19f-7672-2b63-53fa-a3523a4f40e8.png)


### Horizontal Align: 横方向整列

```jsx
  <View style={{ flexDirection: 'row' }}>
    <Text>A</Text>
    <Text>B</Text>
  </View>
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/103475/7e43b7b5-388a-974d-1975-fcb512193c24.png)

### 左右上下中央
いくつかのやり方を紹介します
#### 1) 内包コンポーネントのプライマリ/セカンダリ方向に対して`center`を指定する

- alignItems:'center'
- justifyContent:'center'

```jsx
  <View style={{ justifyContent: 'center', flexDirection: 'row' }}>
    <Text>A</Text>
    <Text>B</Text>
  </View>
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/103475/d5ac1628-f0b1-5af1-cf65-390eea1c33e2.png)

#### 2) margin: 'auto'をreact-nativeで実現する
```jsx
const styles = StyleSheet.create({
  container: {
    marginLeft: 'auto',
    marginRight: 'auto',
    marginTop: 'auto',
    marginBottom: 'auto',
  },
});

  <View style={styles.container}>
    <Text>A</Text>
    <Text>B</Text>
  </View>
```


### 右揃え
> [How can you float: right in React Native? - Stack Overflow](https://stackoverflow.com/questions/32030050/how-can-you-float-right-in-react-native)

StackOverFlowでいくつかのやりかたが載っていたので、記載させていただきます。

**1. textAlign: 'right'をTextにあてる**

```jsx
<View>
  <Text style={{ textAlign: 'right' }}>Hello, World!</Text>
</View>
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/103475/a003262d-eba3-04de-0f3f-67152aed0e52.png)


**2. alignSelf: 'flex-end'をTextに:**

```jsx
  <View>
    <Text style={{ alignSelf: 'flex-end' }}>Hello, World!2</Text>
  </View>
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/103475/2a29e9c3-9033-9271-09b2-280146804527.png)

**3. alignItems: 'flex-end'をViewに:**

```jsx
  <View style={{ alignItems: 'flex-end' }}>
    <Text>Hello, World!3</Text>
  </View>
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/103475/475cea8a-d8bf-81b0-70fc-a5a73cb4c790.png)

**4. flexDirection: 'row' と justifyContent: 'flex-end' をViewに:**

```jsx
  <View style={{ flexDirection: 'row', justifyContent: 'flex-end' }}>
    <Text>Hello, World!4</Text>
  </View>
```


![image.png](https://qiita-image-store.s3.amazonaws.com/0/103475/3e89e688-c4a7-62c5-3135-113bbae5a332.png)

**5. flexDirection: 'row' をViewにあてて marginLeft: 'auto' をTextに:**

```jsx
  <View style={{ flexDirection: 'row' }}>
    <Text style={{ marginLeft: 'auto' }}>Hello, World!5</Text>
  </View>
```
![image.png](https://qiita-image-store.s3.amazonaws.com/0/103475/80cdb2fc-38b0-e743-a9df-2b5f129ad4a8.png)

**6. position: 'absolute' と right: 0 をTextに:**

```jsx
  <View>
    <Text style={{ position: 'absolute', right: 0 }}>Hello, World!6</Text>
  </View>
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/103475/c088f9e1-a8a3-457b-7fc5-2edd7e8065f7.png)


### 左、右、中央に均等配置する方法
> 引用: [react native - How to justify (left, right, center) each child independently? - Stack Overflow](https://stackoverflow.com/questions/36008969/how-to-justify-left-right-center-each-child-independently/36010239)

```jsx
<View style={styles.navBar}>
  <View style={styles.leftContainer}>
    <Text style={[styles.text, {textAlign: 'left'}]}>
      {'<'}
    </Text>
  </View>
  <Text style={styles.text}>
    Fitness & Nutrition Tracking
  </Text>
  <View style={styles.rightContainer}>
    <View style={styles.rightIcon}/>
  </View>
</View>

const styles = StyleSheet.create({
  navBar: {
    height: 60,
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    backgroundColor: 'blue',
  },
  leftContainer: {
    flex: 1,
    flexDirection: 'row',
    justifyContent: 'flex-start',
    backgroundColor: 'green'
  },
  rightContainer: {
    flex: 1,
    flexDirection: 'row',
    justifyContent: 'flex-end',
    alignItems: 'center',
    backgroundColor: 'red',
  },
  rightIcon: {
    height: 10,
    width: 10,
    resizeMode: 'contain',
    backgroundColor: 'white',
  }
});
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/103475/456aed13-1ea3-520e-ea70-b44c7f95eb2a.png)

## inside TextにComponentの幅を自動で合わせる
**alignSelf**を使用する。

```jsx:boxの外側の要素のwidthにfit
// before
          <View style={{ flexDirection: "column" }}>
            <Text>{"最大幅ああああああああああああああ"}</Text>
            <View style={{ borderWidth: 1, borderColor: "red" }}>
              <Text style={{ color: "red" }}>{"あいうえお"}</Text>
            </View>
          </View>
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/103475/10ae53e5-96bd-6287-89b9-39ed2df48e37.png)

```jsx:boxの内側の要素のwidthにfit
// after
          <View style={{ flexDirection: "column" }}>
            <Text>{"最大幅ああああああああああああああ"}</Text>
            <View
              style={{
                alignSelf: "flex-start",
                borderWidth: 1,
                borderColor: "red"
              }}
            >
              <Text style={{ color: "red" }}>{"あいうえお"}</Text>
            </View>
          </View>
</View>
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/103475/aa52c3c8-84c4-48c7-1703-ac84ac217543.png)

> 引用： [javascript - React-native view auto width by text inside - Stack Overflow](https://stackoverflow.com/questions/38233789/react-native-view-auto-width-by-text-inside)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/103475/28273cee-6e99-d38c-fe9e-5fe194a5092c.png)



## Text
### Textの中にTextをネストすると内側のTextがインライン要素のように振る舞う
ちゃんと知らなかった。公式にも書いてあったんですね。
> [Text · React Native](https://facebook.github.io/react-native/docs/text#nested-text)

```jsx
// ↓ViewではなくTextをコンテナとして使う
<Text style={{fontWeight: 'bold'}}>
    I am bold
    <Text style={{color: 'red'}}>
      and red
    </Text>
  </Text>
```
Viewの階層としては全部まとめてひとつのTextViewになっている

![image.png](https://qiita-image-store.s3.amazonaws.com/0/103475/ea53aec5-21ca-a6d7-342e-b140af5ec470.png)
> [Textコンポーネントをインライン要素っぽく扱う - Qiita](https://qiita.com/Nkzn/items/98c36619f4c06bd0e77b)

### font weight
> https://gist.github.com/knowbody/c5cdf26073b874eae86ba96e7cf3a540

```jsx
{ fontWeight: '100' }, // Thin
{ fontWeight: '200' }, // Ultra Light
{ fontWeight: '300' }, // Light
{ fontWeight: '400' }, // Regular
{ fontWeight: '500' }, // Medium
{ fontWeight: '600' }, // Semibold
{ fontWeight: '700' }, // Bold
{ fontWeight: '800' }, // Heavy
{ fontWeight: '900' }, // Black
```

こちらは定数にすると扱いやすし

```variable.jsx
// 例
export const FONT_WEIGHT = {
  LIGHT: '300',
  MEDIUM: '500',
  BOLD: '700',
  BLACK: '900',
};
```

### 行高さ
**lineHeight: number**

```jsx
// Before
  <Text style={{fontSize: 14}}>
    吾輩は猫である。名前はまだ無い。どこで生れたかとんと見当がつかぬ。何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。吾輩はここで始めて人間というものを見た。しかもあとで聞くとそれは書生という人間中で一番獰悪な種族であったそうだ。
  </Text>
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/103475/298309eb-a924-7895-49d8-d6e0a4831d5b.png)

```jsx
// After
  <Text style={{lineHeight:20, fontSize: 14}}>
    吾輩は猫である。名前はまだ無い。どこで生れたかとんと見当がつかぬ。何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。吾輩はここで始めて人間というものを見た。しかもあとで聞くとそれは書生という人間中で一番獰悪な種族であったそうだ。
  </Text>
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/103475/1b17faeb-b4d3-e3cd-52c1-978a8311427a.png)

### 文字間隔
**letterSpacing: number**

```jsx
// Before
  <Text style={{fontSize: 14}}>
    吾輩は猫である。名前はまだ無い。どこで生れたかとんと見当がつかぬ。何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。吾輩はここで始めて人間というものを見た。しかもあとで聞くとそれは書生という人間中で一番獰悪な種族であったそうだ。
  </Text>
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/103475/298309eb-a924-7895-49d8-d6e0a4831d5b.png)

```jsx
// After
  <Text style={{letterSpacing: 1, fontSize: 14}}>
    吾輩は猫である。名前はまだ無い。どこで生れたかとんと見当がつかぬ。何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。吾輩はここで始めて人間というものを見た。しかもあとで聞くとそれは書生という人間中で一番獰悪な種族であったそうだ。
  </Text>
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/103475/56dcc4fd-a4b4-9273-476e-4507fe821ed7.png)


## 画像
### 外部(http~)Imageはsize(width, height)を指定しないと表示されない？

```jsx
// BAD
<Image
  source={{ uri: 'https://facebook.github.io/react-native/docs/assets/favicon.png'}}
/>
```

```jsx
// GOOD
<Image
  source={{ uri: 'https://facebook.github.io/react-native/docs/assets/favicon.png'}}
  style = {{ width: 200, height: 200 }}
/>
```

### 外部Imageは{uri: path}じゃないといけない？
```jsx
// BAD
<Image
  source={ require('https://facebook.github.io/react-native/docs/assets/favicon.png')
/>
```

```jsx
// GOOD
<Image
  source={{ uri: 'https://facebook.github.io/react-native/docs/assets/favicon.png'}}
  style = {{ width: 200, height: 200 }}
/>
```

### リサイズ
resizeModeを使う。optionは公式参照 : [Image · React Native](https://facebook.github.io/react-native/docs/image#resizemode)

```jsx
  <Image
    source={{ uri: 'https://facebook.github.io/react-native/docs/assets/favicon.png'}}
    style = {{
      width: 100,
      height: 100,
      resizeMode: 'contain',
    }}
  />
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/103475/6afefff0-3644-b508-08c1-27fd0a91b85f.png)

#### AspectRatio


```tsx
          <Image
            source={{
              uri:
                "https://facebook.github.io/react-native/docs/assets/favicon.png"
            }}
            style={{
              height: 200,
              aspectRatio: 1,
              resizeMode: "contain"
            }}
          />
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103475/2fd89e7b-20fd-847b-60bc-1d18920f0415.png)


### 画像の不透明

```jsx
  <Image
    source={{ uri: 'https://facebook.github.io/react-native/docs/assets/favicon.png'}}
    style = {{
      width: 100,
      height: 100,
      resizeMode: 'contain',
      opacity: 0.6,
    }}
  />
```

## 複数のstyleを当てたいとき
Componentへのstyleに配列形式で渡す。

```jsx
<View style={[{width: 100}, {backgroundColor: 'gray'}]} />
```

## 特定の角だけ角丸にしたい
**borderRadiusは各コーナーに設定可能**
https://stackoverflow.com/questions/35341502/how-to-use-border-radius-only-for-1-corner-react-native

- borderBottomLeftRadius: number
- borderBottomRightRadius: number
- borderTopLeftRadius: number
- borderTopRightRadius: number 

```jsx
  <View style={{
    borderWidth: 1,
    borderColor:'gray',
    borderBottomLeftRadius:5,
    borderTopRightRadius:10,
    margin:10,
  }}>
    <Text>A</Text>
    <Text>B</Text>
  </View>
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/103475/4059f11a-97d3-7472-4e63-cb453a682437.png)