パート1: 最終コード
パート1: 最終コード
オープンベータ版ドキュメント:本テクニカルドキュメントは、リリース前のオープンベータ版の一部としてAmazonから提供されるものです。ここで説明されている機能は、Amazonがフィードバックを受け取り、機能の開発を繰り返す過程で変更される可能性があります。最新の機能の情報については、リリースノートを参照してください。
パート1の最終コードは次のとおりです。
フォルダ構造
src/
├── components/
│ ├── Header.tsx
│ └── VideoCard.tsx
├── screens
│ ├── LandingScreen.tsx
└── App.tsx
コンポーネント
Header.tsx
import * as React from 'react';
import {StyleSheet, Text, View} from 'react-native';
const Header = () => {
return (
<View style={styles.headerContainer}>
<Text style={styles.headerText}>Vegaへようこそ!</Text>
</View>
);
};
const styles = StyleSheet.create({
headerContainer: {
padding: 10,
alignItems: 'center',
backgroundColor: '#232F3E',
width: '100%',
},
headerText: {
fontSize: 50,
fontWeight: '700',
color: '#FF9900',
},
});
export default Header;
VideoCard.tsx
import React, {useState} from 'react';
import {StyleSheet, Text, TouchableOpacity, Image, View} from 'react-native';
interface IProps {
title: string;
imgURL: string;
description: string;
pressFunction: Function;
}
const VideoCard = ({title, imgURL, description, pressFunction}: IProps) => {
const [focused, setFocused] = useState(false);
return (
<TouchableOpacity
style={[
styles.videoCardContainer,
focused ? styles.focused : styles.unfocused,
]}
onPress={() => pressFunction()}
onFocus={() => setFocused(true)}
onBlur={() => setFocused(false)}>
<Image style={styles.videoImage} source={{uri: imgURL}} />
<View style={styles.videoTextContainer}>
<Text style={styles.videoTitle}>{title}</Text>
<Text style={styles.videoDescription}>{description}</Text>
</View>
</TouchableOpacity>
);
};
const styles = StyleSheet.create({
videoCardContainer: {
height: 400,
width: 550,
margin: 10,
borderRadius: 5,
},
unfocused: {
borderWidth: 1,
borderColor: 'white',
},
focused: {
borderWidth: 5,
borderColor: 'yellow',
},
videoTextContainer: {
height: '25%',
display: 'flex',
justifyContent: 'space-around',
padding: 10,
},
videoImage: {
height: '75%',
},
videoTitle: {
fontSize: 20,
fontWeight: 'bold',
color: 'white',
},
videoDescription: {
color: 'white',
},
});
export default VideoCard;
画面
LandingScreen.tsx
import React, {useState, useEffect} from 'react';
import {FlatList, StyleSheet, View, Text} from 'react-native';
import Header from '../components/Header';
import VideoCard from '../components/VideoCard';
import {TVFocusGuideView} from '@amazon-devices/react-native-kepler';
interface IVideo {
id: string;
title: string;
description: string;
duration: number;
thumbURL: string;
imgURL: string;
videoURL: string;
categories: Array<string>;
channel_id: number;
}
const LandingScreen = () => {
const [islandVideos, setIslandVideos] = useState<IVideo[]>([]);
const [underwaterVideos, setUnderwaterVideos] = useState<IVideo[]>([]);
const url = 'https://d2ob7xfxpe6plv.cloudfront.net/TestData.json';
const getAllVideos = () => {
fetch(url)
.then((response) => response.json())
.then((data) => {
// 各カテゴリの動画をフィルタリングします
const islands = data.testData.filter(
(video: IVideo) =>
video.categories && video.categories.includes('コスタリカの島々'),
);
const underwater = data.testData.filter(
(video: IVideo) =>
video.categories &&
video.categories.includes('コスタリカの水中'),
);
setIslandVideos(islands);
setUnderwaterVideos(underwater);
})
.catch((error) => {
console.log(error);
});
};
useEffect(() => {
getAllVideos();
}, []);
return (
<>
<Header />
<TVFocusGuideView autoFocus={true}>
<Text style={styles.categoryTitle}>コスタリカの島々</Text>
<FlatList
style={styles.flatList}
horizontal
data={islandVideos}
renderItem={({item}) => (
<View style={styles.itemContainer}>
<VideoCard
title={item.title}
description={
item.description.split(' ').slice(0, 20).join(' ') + '...'
}
imgURL={item.imgURL}
pressFunction={() => {}}
/>
</View>
)}
/>
</TVFocusGuideView>
<TVFocusGuideView autoFocus={true}>
<Text style={styles.categoryTitle}>コスタリカの水中</Text>
<FlatList
style={styles.flatList}
horizontal
data={underwaterVideos}
renderItem={({item}) => (
<View style={styles.itemContainer}>
<VideoCard
title={item.title}
description={
item.description.split(' ').slice(0, 20).join(' ') + '...'
}
imgURL={item.imgURL}
pressFunction={() => {}}
/>
</View>
)}
/>
</TVFocusGuideView>
</>
);
};
const styles = StyleSheet.create({
flatList: {
padding: 10,
},
itemContainer: {
margin: 10,
},
categoryTitle: {
fontSize: 24,
fontWeight: 'bold',
color: 'white',
marginLeft: 30,
},
});
export default LandingScreen;
App.tsx
import * as React from 'react';
import { View, StyleSheet } from 'react-native';
import LandingScreen from './screens/LandingScreen';
export const App = () => {
return (
<View style={styles.container}>
<LandingScreen />
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#232F3E',
},
});

