我们生活在一个事物不断变化的世界中。因此,如果你想了解正在发生的事情,你会想要一个好的新闻应用程序。
为了帮助你学习一些很酷的技术并保持现状,在这篇博文中,我们将使用React Native为Android建立一个新闻应用程序。它将从不同的新闻频道获取头条新闻并按类别显示。
这就是我们完成后的应用程序的样子。所以,让我们直接开始吧。
如何安装Expo
那么,Expo是什么?Expo是一个框架,可以帮助你快速、轻松地建立和部署React Native应用。
让我们来安装它。
npm install --global expo-cli
安装Expo
在你的终端运行这个命令来安装Expo CLI。在这里,我们使用--global
,以确保它安装在任何地方。
安装完成后,我们需要创建一个Expo项目。
expo init News-Application
创建一个Expo项目
使用上面的命令来初始化这个项目。它会问你几个问题,比如你的应用程序的名称,你是否想在你的项目中添加TypeScript,或者从一个空白项目开始。只要选择空白,然后按回车。
然后,它将下载文件夹中的所有软件包和依赖项。
现在,完成后,导航到项目文件夹中。要启动该应用程序,输入expo start。它将在浏览器中打开开发者工具。
世博开发者工具
在这里你会看到左边有很多选项,比如在安卓设备/模拟器上运行,或者在iOS模拟器上运行。我们将在网络浏览器上运行应用程序,所以点击在网络浏览器中运行选项。
import { StatusBar } from 'expo-status-bar';
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
export default function App() {
return (
<View style={styles.container}>
<Text>Open up App.js to start working on your app!</Text>
<StatusBar style="auto" />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
我们的App.js
这是我们的App.js文件,它包含了默认的模板。
我们的输出
现在我们的应用程序正在运行。
如何使用React Navigation创建不同的屏幕
现在,让我们为我们的应用程序创建各种不同的屏幕。为此,我们将使用React Navigation。所以,让我们来安装它。
前往reactnavigation.org/,点击阅读文档。它将打开文档页面。
让我们使用下面的命令来安装React Navigation。
npm install @react-navigation/native
expo install react-native-screens react-native-safe-area-context
安装React Navigation
现在,我们的React Navigation已经安装完毕。
我们将使用bottomTabNavigator
。因此,从左边的菜单中,选择API参考,然后是导航器,然后是底部标签。
选择底部标签
让我们使用下面的命令来安装底部标签。
npm install @react-navigation/bottom-tabs
安装底部标签
现在,在我们的App.js文件中,我们需要导入Bottom Tabs,以便使用它。
所以,像这样导入它。
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
导入Bottom Tabs
现在,让我们导入标签屏幕。
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { NavigationContainer } from '@react-navigation/native';
const Tab = createBottomTabNavigator();
function MyTabs() {
return (
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Settings" component={SettingsScreen} />
</Tab.Navigator>
);
}
导入标签导航屏幕
这就是我们创建底部标签的方法。
在我们的案例中,我们需要做这样的事情。
<Tab.Navigator>
<Tab.Screen name="All" component={All} />
<Tab.Screen name="Business" component={Business} />
<Tab.Screen name="Health" component={HealthScreen} />
<Tab.Screen name="Sports" component={SportsScreen} />
<Tab.Screen name="Tech" component={TechScreen} />
</Tab.Navigator>
我们需要为以下标签创建这些屏幕。所有新闻,商业新闻,体育新闻,健康新闻,以及科技新闻。同时,在项目中为每个屏幕创建一个组件。
我们需要把这个TabNavigtor
,像这样包装成一个NavigationContainer
。
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen name="All" component={All} />
<Tab.Screen name="Business" component={Business} />
<Tab.Screen name="Health" component={HealthScreen} />
<Tab.Screen name="Sports" component={SportsScreen} />
<Tab.Screen name="Tech" component={TechScreen} />
</Tab.Navigator>
</NavigationContainer>
我们还需要导入这些所有的组件,所以在顶部导入它们。
import All from './screens/All';
import Business from './screens/Business';
import HealthScreen from './screens/Health';
import SportsScreen from './screens/Sports';
import TechScreen from './screens/Tech';
现在,如果我们把我们写的所有代码放在一起,我们将得到以下代码。
import React from 'react';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { NavigationContainer } from '@react-navigation/native';
import All from './screens/All';
import Business from './screens/Business';
import HealthScreen from './screens/Health';
import SportsScreen from './screens/Sports';
import TechScreen from './screens/Tech';
const Tab = createBottomTabNavigator();
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen name="All" component={All} />
<Tab.Screen name="Business" component={Business} />
<Tab.Screen name="Health" component={HealthScreen} />
<Tab.Screen name="Sports" component={SportsScreen} />
<Tab.Screen name="Tech" component={TechScreen} />
</Tab.Navigator>
</NavigationContainer>
);
}
屏幕的代码
这将是我们的输出。
我们的五个屏幕,即所有、商业、健康、体育和技术。
我们在这里有五个屏幕,分别是所有、商业、健康、体育和技术。
现在,让我们在这里做一些调整。我们需要改变底部标签的图标。
要做到这一点,我们将需要为我们的图标获得一个图标库。为此,我们将使用react-native-elements。
要安装它,请输入以下命令。
npm install react-native-elements
安装React Native Elements
这个图标包有很多图标选项可以选择。
React Native Elements中的可用图标
现在让我们在底部标签导航器中添加我们的图标。
<Tab.Screen name="All" component={All}
options={{
tabBarIcon: (props) => (
<Icon type='feather' name='home' color={props.color} />
),
}} />
添加主页的图标
这里我们为主页添加了名为 "home "的图标,并为类型添加了羽毛图标类。
带有主页图标的底部标签导航器
这将产生上述输出。同样地,让我们对所有的标签重复同样的过程。
<Tab.Navigator>
<Tab.Screen name="All" component={All}
options={{
tabBarIcon: (props) => (
<Icon type='feather' name='home' color={props.color} />
),
}} />
<Tab.Screen name="Business" component={Business}
options={{
tabBarIcon: (props) => (
<Icon type='feather' name='dollar-sign' color={props.color} />
),
}} />
<Tab.Screen name="Health" component={HealthScreen}
options={{
tabBarIcon: (props) => (
<Icon type='feather' name='heart' color={props.color} />
),
}} />
<Tab.Screen name="Sports" component={SportsScreen}
options={{
tabBarIcon: (props) => (
<Icon type='ionicon' name="tennisball-outline" color={props.color} />
),
}} />
<Tab.Screen name="Tech" component={TechScreen}
options={{
tabBarIcon: (props) => (
<Icon type='ionicon' name="hardware-chip-outline" color={props.color} />
),
}} />
</Tab.Navigator>
带有图标的所有底部标签
现在我们每个不同的标签或屏幕都完成了,它们都有自己独特的图标。
如何调用新闻API
现在,让我们从newsapi.org/中调用新闻API。
进入这个网站并注册。它将给你一个API密钥。
我们需要一个配置文件来存储所有的News常量,所以我们来创建它。
export const API_KEY = ``;
export const endpoint = `https://newsapi.org/v2/top-headlines`;
export const country = 'in'
我们的config.js
我们需要API_KEY、端点和国家代码。
现在,我们需要为我们的GET API请求创建一个服务**。**
创建一个名为services.js的文件*。*
在这里,在顶部导入API_KEY、端点和国家。
import { API_KEY, endpoint, country } from '../config/config';
Services.js
然后,我们将编写我们的服务主体。
export async function services(category = 'general') {
let articles = await fetch(`${endpoint}?country=${country}&category=${category}`, {
headers: {
'X-API-KEY': API_KEY
}
});
let result = await articles.json();
articles = null;
return result.articles;
}
我们的GET API服务
所以,我们通过使用我们的端点来获取新闻数据,并添加国家和类别。在函数中,我们将类别传递为一般,因为那是默认的类别。我们还在头文件中传递了API_key。
然后,我们将响应或传入的数据转换成JSON格式,并将其存储在一个结果变量中。
最后,我们使用return
关键字将其返回。
下面是整个文件供你参考。
import { API_KEY, endpoint, country } from '../config/config';
export async function services(category = 'general') {
let articles = await fetch(`${endpoint}?country=${country}&category=${category}`, {
headers: {
'X-API-KEY': API_KEY
}
});
let result = await articles.json();
articles = null;
return result.articles;
}
现在,我们需要将这个服务导入我们的All.js文件。
import { services } from '../services/services';
将服务导入All.js中
我们将需要使用useState
和useEffect
钩子。useEffect钩子将在All.js文件中调用这个服务,useState将创建一个状态,存储来自API的响应。
import React, { useEffect, useState } from 'react'
import { View } from 'react-native';
import { services } from '../services/services';
export default function All() {
const [newsData, setNewsData] = useState([])
useEffect(() => {
services('general')
.then(data => {
setNewsData(data)
})
.catch(error => {
alert(error)
})
}, [])
return (
<View>
</View>
)
}
使用useState和useEffect钩子
在这个文件中,我们在useEffect钩子中调用服务。然后我们将响应存储在newsData状态中,它是一个数组。我们还为类别传递了一个参数,它是一般的。
这个屏幕将获取所有的新闻,所以我们使用一般类别。它将在其他每个屏幕上改变。对于健康屏幕,它将是健康 ,对于体育,它将是体育 ,等等。
现在,我们需要在我们的界面上显示这些数据。为此,我们需要另一个叫做Native Base的包。所以,让我们来安装它。
输入下面的命令来安装Native Base。
yarn add native-base styled-components styled-system
expo install react-native-svg react-native-safe-area-context
安装Native Base
在All.js中,让我们从Native Base导入一些东西。
import React, { useEffect, useState } from 'react'
import { View, Text } from 'react-native';
import { NativeBaseProvider, FlatList, ScrollView, Divider, Image, Spinner } from 'native-base';
import { services } from '../services/services';
从Native Base导入东西
然后在返回中,我们将添加NativeBaseProvider
。
return (
<NativeBaseProvider>
</NativeBaseProvider>
)
在返回中添加NativeBaseProvider
然后,让我们添加Scroll View。如果新闻数据超出了我们的屏幕高度,这将让用户滚动。
<NativeBaseProvider>
<ScrollView height={850}>
</ScrollView>
</NativeBaseProvider>
添加ScrollView
现在,让我们添加FlatList
来显示我们的新闻数据。
<NativeBaseProvider>
<ScrollView height={850}>
<FlatList
data={newsData}
renderItem={({ item }) => (
<View>
</View>
)}
keyExtractor={(item) => item.id}
/>
</ScrollView>
</NativeBaseProvider>
使用FlatList
FlatList接收一个数据道具,也就是我们之前创建的newsData
状态,它从renderItems
,返回一个item
。
这类似于JavaScript中的map
,它遍历一个数组并返回一个项目。它也有一个keyExtractor
,我们用它来使每个项目都是独一无二的。
现在,让我们在视图中显示我们的数据。
像这样在父视图中再创建一个视图。
<NativeBaseProvider>
<ScrollView height={850}>
<FlatList
data={newsData}
renderItem={({ item }) => (
<View>
<View>
</View>
</View>
)}
keyExtractor={(item) => item.id}
/>
</ScrollView>
</NativeBaseProvider>
现在,让我们在子视图内添加一些文本。
<NativeBaseProvider>
<ScrollView height={850}>
<FlatList
data={newsData}
renderItem={({ item }) => (
<View>
<View>
<Text>
{item.title}
</Text>
<Text>
{item.publishedAt}
</Text>
<Text>
{item.description}
</Text>
</View>
</View>
)}
keyExtractor={(item) => item.id}
/>
</ScrollView>
</NativeBaseProvider>
这包含了我们的新闻标题,描述,和发布日期。
如何为我们的React Native新闻应用设计风格
这就是我们的应用程序现在的样子,包括新闻标题、描述和日期。为了使它看起来更漂亮,我们需要给它一些样式。
在顶部从React Native导入StyleSheet
,以便使用其样式。
import { View, Text, StyleSheet } from 'react-native';
从react-native导入StyleSheet
<View>
<View style={styles.newsContainer}>
<Text style={styles.title}>
{item.title}
</Text>
<Text style={styles.date}>
{item.publishedAt}
</Text>
<Text style={styles.newsDescription}>
{item.description}
</Text>
</View>
</View>
然后,像这样添加样式。而在底部,我们需要创建这些样式。
const styles = StyleSheet.create({
newsContainer: {
padding: 10
},
title: {
fontSize: 18,
marginTop: 10,
fontWeight: "600"
},
newsDescription: {
fontSize: 16,
marginTop: 10
},
date: {
fontSize: 14
},
});
我们在All.js中的StyleSheet
这就是得到一些样式后的应用程序现在的样子。你也可以向下滚动页面。
现在,我们需要将日期格式改为可读格式,因为我不明白**'2021-08-21T11:00:40Z'。**
我们将为此使用有用的moment.js包,所以让我们使用下面的命令来安装它。
npm install moment --save
安装Moment.js来格式化时间
然后,在我们的All.js界面中导入它。
<Text style={styles.date}>
{moment(item.publishedAt).format('LLL')}
</Text>
使用 moment.js 格式化日期和时间
像这样格式化日期。
Moment.js的时间和日期格式
moment文档给了我们这么多格式可供选择。我选择了*'LLL'*格式。
而现在我们的日期更容易让人读懂。
我们还需要一个分隔符,把新闻文章彼此分开,这样它们就不会都跑到一起。
<View>
<View style={styles.newsContainer}>
<Text style={styles.title}>
{item.title}
</Text>
<Text style={styles.date}>
{moment(item.publishedAt).format('LLL')}
</Text>
<Text style={styles.newsDescription}>
{item.description}
</Text>
</View>
<Divider my={2} bg="#e0e0e0" />
</View>
添加一个分隔符
因此,在子视图之后添加了一个分隔器,我们的应用程序看起来像这样。
现在我们的新闻标题被分割开来,看起来很不错。
这个新闻API也有一个图片。所以,让我们来添加它。
<View>
<View style={styles.newsContainer}>
<Image
width={550}
height={250}
resizeMode={"cover"}
source={{
uri: item.urlToImage,
}}
alt="Alternate Text"
/>
<Text style={styles.title}>
{item.title}
</Text>
<Text style={styles.date}>
{moment(item.publishedAt).format('LLL')}
</Text>
<Text style={styles.newsDescription}>
{item.description}
</Text>
</View>
<Divider my={2} bg="#e0e0e0" />
</View>
所以,我们已经添加了图片,我们使用了名为urlToImage
的键来做这个*。*
现在我们有新闻图片显示了。
如何添加一个旋转器来显示正在加载的新闻
让我们添加一个旋转器,在新闻加载时显示。
首先,我们将创建一个检查。如果newsData
状态的长度超过1,我们将显示我们的FlatList
,它包含我们的新闻数据。否则,我们将显示加载旋钮。
换句话说,如果newsData
状态的长度小于1,这意味着它是空的,API仍在被调用。一旦API调用结束,它将把数据存储到newsData
状态中,并且该状态的长度将变为大于1。
{newsData.length > 1 ? (
<FlatList
data={newsData}
renderItem={({ item }) => (
<View>
<View style={styles.newsContainer}>
<Image
width={550}
height={250}
resizeMode={"cover"}
source={{
uri: item.urlToImage,
}}
alt="Alternate Text"
/>
<Text style={styles.title}>
{item.title}
</Text>
<Text style={styles.date}>
{moment(item.publishedAt).format('LLL')}
</Text>
<Text style={styles.newsDescription}>
{item.description}
</Text>
</View>
<Divider my={2} bg="#e0e0e0" />
</View>
)}
keyExtractor={(item) => item.id}
/>
) : (
<View style={styles.spinner}>
<Spinner color="danger.400" />
</View>
)}
添加一个旋转器
在我们的样式中,为旋转器添加以下样式代码。
spinner: {
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: 400
}
旋转器的样式
这是下面的代码,供你参考。
import React, { useEffect, useState } from 'react'
import { View, Text, StyleSheet } from 'react-native';
import { NativeBaseProvider, FlatList, ScrollView, Divider, Image, Spinner } from 'native-base';
import { services } from '../services/services';
import moment from 'moment'
export default function All() {
const [newsData, setNewsData] = useState([])
useEffect(() => {
services('general')
.then(data => {
setNewsData(data)
})
.catch(error => {
alert(error)
})
}, [])
return (
<NativeBaseProvider>
<ScrollView height={850}>
{newsData.length > 1 ? (
<FlatList
data={newsData}
renderItem={({ item }) => (
<View>
<View style={styles.newsContainer}>
<Image
width={550}
height={250}
resizeMode={"cover"}
source={{
uri: item.urlToImage,
}}
alt="Alternate Text"
/>
<Text style={styles.title}>
{item.title}
</Text>
<Text style={styles.date}>
{moment(item.publishedAt).format('LLL')}
</Text>
<Text style={styles.newsDescription}>
{item.description}
</Text>
</View>
<Divider my={2} bg="#e0e0e0" />
</View>
)}
keyExtractor={(item) => item.id}
/>
) : (
<View style={styles.spinner}>
<Spinner color="danger.400" />
</View>
)}
</ScrollView>
</NativeBaseProvider>
)
}
const styles = StyleSheet.create({
newsContainer: {
padding: 10
},
title: {
fontSize: 18,
marginTop: 10,
fontWeight: "600"
},
newsDescription: {
fontSize: 16,
marginTop: 10
},
date: {
fontSize: 14
},
spinner: {
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: 400
}
});
我们的All.js屏幕现在已经完成了。
现在,我们也可以在所有其他屏幕上使用同样的代码。我们只需要在useEffect
Hook中改变我们在服务中传递的参数 。
因此,对于商业屏幕,我们将使用商业。对于健康,我们将使用健康,以此类推。
import React, { useEffect, useState } from 'react'
import { View, Text, StyleSheet } from 'react-native';
import { NativeBaseProvider, FlatList, ScrollView, Divider, Image, Spinner } from 'native-base';
import { services } from '../services/services';
import moment from 'moment'
export default function Business() {
const [newsData, setNewsData] = useState([])
useEffect(() => {
services('business')
.then(data => {
setNewsData(data)
})
.catch(error => {
alert(error)
})
}, [])
return (
<NativeBaseProvider>
<ScrollView height={850}>
{newsData.length > 1 ? (
<FlatList
data={newsData}
renderItem={({ item }) => (
<View>
<View style={styles.newsContainer}>
<Image
width={550}
height={250}
resizeMode={"cover"}
source={{
uri: item.urlToImage,
}}
alt="Alternate Text"
/>
<Text style={styles.title}>
{item.title}
</Text>
<Text style={styles.date}>
{moment(item.publishedAt).format('LLL')}
</Text>
<Text style={styles.newsDescription}>
{item.description}
</Text>
</View>
<Divider my={2} bg="#e0e0e0" />
</View>
)}
keyExtractor={(item) => item.id}
/>
) : (
<View style={styles.spinner}>
<Spinner color="danger.400" />
</View>
)}
</ScrollView>
</NativeBaseProvider>
)
}
const styles = StyleSheet.create({
newsContainer: {
padding: 10
},
title: {
fontSize: 18,
marginTop: 10,
fontWeight: "600"
},
newsDescription: {
fontSize: 16,
marginTop: 10
},
date: {
fontSize: 14
},
spinner: {
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: 400
}
});
业务屏幕
向下滚动商业屏幕,你会看到与商业有关的新闻。
你也可以对所有其他屏幕做同样的事情。
useEffect(() => {
services('business')
.then(data => {
setNewsData(data)
})
.catch(error => {
alert(error)
})
}, [])
对于商业
useEffect(() => {
services('health')
.then(data => {
setNewsData(data)
})
.catch(error => {
alert(error)
})
}, [])
健康
useEffect(() => {
services('sports')
.then(data => {
setNewsData(data)
})
.catch(error => {
alert(error)
})
}, [])
体育
useEffect(() => {
services('technology')
.then(data => {
setNewsData(data)
})
.catch(error => {
alert(error)
})
}, [])
科技
结语
恭喜你!现在我们的新闻应用已经完成。现在我们的新闻应用程序已经完成。
所以,继续吧,建立和实验一下。你有很多事情可以做。
你可以查看我的播放列表:使用React Native和Native Base构建一个新闻应用程序,这是在我的YouTube频道上。
欢迎在这里下载代码:https://github.com/nishant-666/React-Native-News
快乐学习。
我建立项目是为了学习代码的工作原理。当我不在编码的时候,我喜欢写诗和故事,弹钢琴,做美味的食物。
如果你读到这里,请发推特给作者,向他们表示你的关心。鸣谢
免费学习代码。freeCodeCamp的开源课程已经帮助超过40,000人获得了开发者的工作。开始吧