2019-05-18に投稿

ReactNativeアプリを作り始めました。

背景

アニメ視聴遅れ管理サービスを作っているのですが、ReactNativeアプリで好きなアニメランキングを作りはじめました。
これがランキングを作る際の番組選択画面にあたります。
(warningが出てるのは許してください....。)

image

GraphQLでサーバからデータを取得する

以前、ReactでGraphQL APIにアクセスするという記事を書いたので今回は割愛します。

今回作成したクエリはこちら。
${year} で取得したい年を渡しています。
クエリの内容としては、${year}で指定した番組のタイトル、画像URL、annict上の番組ID、シーズンを視聴者数順にソートして返します。

let query = gql`{
        searchWorks(
          seasons:["${year}-spring","${year}-summer","${year}-autumn","${year}-winter"],
          orderBy: { field: WATCHERS_COUNT, direction: DESC }
          ){
          edges{
            node{
              title
              image{recommendedImageUrl}
              annictId
              seasonName
              seasonYear
            }
          }
        }
      }`

長すぎるタイトルを省略する

TextコンポーネントにこんなPropsがあるらしい。
【React Native】三点リーダーでテキストを省略

今回使ったProps。

numberOfLines={3}
ellipsizeMode="tail"

番組データを3カラムで表示する

deprecatedになっているListViewを使っているところは気になりますが、FlatListに読み替えてしまえばかなりの良記事だと思います。
React Native の ListView で2カラムの表示を簡単に

番組画像に作品タイトルをオーバーレイさせる

元々UIに疎かった私。
画像に半透明のレイヤーを被せてその上に文字を表示するのを何というかということも知らなかったので、「画像 文字 のせる」というところからググりはじめて「オーバーレイ」と呼ぶことを知ったので、「react native overlay text」でググると...。
How to place a text over image in react native?

Imageコンポーネントはchildrenを持てないようなので、
ImageBackGroundコンポーネントを使います。

実装まとめ

今回行った実装の一部です。
Imageコンポーネントに画像URLを渡していますが、
空文字やnullなどは怒られてしまうので条件分岐をさせて回避します。
これで作品画像にタイトルがオーバーレイしたリストを3カラムで表示させることができます。

return (
        <FlatList
          style={{ flex: 1, paddingTop: 20, backgroundColor: '#dddddd' }}
          contentContainerStyle={{ flexDirection: 'row', flexWrap: 'wrap' }}
          data={store.getState().data}
          renderItem={(rowData)=>{
            let image
            if(rowData.item.node.image !== null){
              image = (
                <ImageBackground 
                  style={
                    {
                      width: (Dimensions.get('window').width - 20) / 3 - 20,
                      height: 80,
                      marginTop:10,
                      marginBottom:10,
                      marginLeft:10,
                      marginRight:10
                    }
                  }
                  source={
                    {
                      uri: rowData.item.node.image.recommendedImageUrl
                    }
                  }>
                  <View 
                    style={
                    {
                      position: 'absolute',
                      //width: '100%',
                      bottom: 0,
                      justifyContent: 'center',
                      alignItems: 'center'}}>
                    <Text
                    style={{
                      fontWeight:'bold',
                      backgroundColor: 'rgba(255, 255, 255, 0.8)',
                      width:(Dimensions.get('window').width - 20) / 3 - 20

                    }}
                    numberOfLines={3}
                    ellipsizeMode="tail"
                  >{rowData.item.node.title}</Text>
                  </View>
                  </ImageBackground>
              )
            }else{
              image = null
            }
            return (
              <View style={
                { padding: 1,
                  backgroundColor: 'white',
                  margin: 2,
                  width: (Dimensions.get('window').width - 20) / 3,
                  height: 100
                }
              }
              >
                {image}
              </View>
            )
          }}
          />
      )

ckoshien

個人開発4年目。普段はアプリケーションエンジニア。 ReactJS/NodeJS/ReactNative/Java

Crieitは個人で開発中です。 興味がある方は是非記事の投稿をお願いします! どんな軽い内容でも嬉しいです。
なぜCrieitを作ろうと思ったか

また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!

こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください!

ボードとは?

関連記事

コメント