在这个实践案例中,我们将使用Jetpack Navigation创建一个简单的新闻应用。这个应用将包含以下功能:
- 新闻列表页面:显示一组新闻文章。
- 新闻详情页面:显示选定新闻文章的详细信息。
- 用户资料页面:显示用户的资料信息。
我们将通过导航图、传递数据、处理返回操作和集成底部导航来展示Jetpack Navigation的强大功能。
第一步:项目设置
添加依赖项
在build.gradle
文件中添加必要的依赖项:
dependencies {
def nav_version = "2.4.0"
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
implementation "com.google.android.material:material:1.4.0"
}
创建导航图
在res/navigation
目录中创建一个新的导航图文件nav_graph.xml
。
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
app:startDestination="@id/newsListFragment">
<fragment
android:id="@+id/newsListFragment"
android:name="com.example.newsapp.NewsListFragment"
android:label="News List"
tools:layout="@layout/fragment_news_list" >
<action
android:id="@+id/action_newsListFragment_to_newsDetailFragment"
app:destination="@id/newsDetailFragment" />
<action
android:id="@+id/action_newsListFragment_to_userProfileFragment"
app:destination="@id/userProfileFragment" />
</fragment>
<fragment
android:id="@+id/newsDetailFragment"
android:name="com.example.newsapp.NewsDetailFragment"
android:label="News Detail"
tools:layout="@layout/fragment_news_detail" >
<argument
android:name="articleId"
app:argType="integer" />
</fragment>
<fragment
android:id="@+id/userProfileFragment"
android:name="com.example.newsapp.UserProfileFragment"
android:label="User Profile"
tools:layout="@layout/fragment_user_profile" />
</navigation>
主Activity布局
创建主Activity布局文件activity_main.xml
,包含一个NavHostFragment
和BottomNavigationView
。
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_graph"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/bottom_nav"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_nav"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="start"
app:menu="@menu/bottom_nav_menu"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.drawerlayout.widget.DrawerLayout>
BottomNavigationView菜单
在res/menu
目录中创建bottom_nav_menu.xml
。
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/newsListFragment"
android:icon="@drawable/ic_news"
android:title="News" />
<item
android:id="@+id/userProfileFragment"
android:icon="@drawable/ic_profile"
android:title="Profile" />
</menu>
主Activity
在MainActivity.kt
中设置NavController
和BottomNavigationView
。
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val navController = findNavController(R.id.nav_host_fragment)
val bottomNavigationView = findViewById<BottomNavigationView>(R.id.bottom_nav)
bottomNavigationView.setupWithNavController(navController)
}
override fun onSupportNavigateUp(): Boolean {
val navController = findNavController(R.id.nav_host_fragment)
return navController.navigateUp() || super.onSupportNavigateUp()
}
}
第二步:创建Fragment
新闻列表Fragment
创建NewsListFragment.kt
,显示一组新闻文章。
class NewsListFragment : Fragment(R.layout.fragment_news_list) {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val navController = findNavController()
// 示例数据
val articles = listOf("Article 1", "Article 2", "Article 3")
val adapter = ArrayAdapter(requireContext(), android.R.layout.simple_list_item_1, articles)
view.findViewById<ListView>(R.id.newsListView).adapter = adapter
view.findViewById<ListView>(R.id.newsListView).setOnItemClickListener { _, _, position, _ ->
val action = NewsListFragmentDirections.actionNewsListFragmentToNewsDetailFragment(position)
navController.navigate(action)
}
}
}
新闻详情Fragment
创建NewsDetailFragment.kt
,显示选定新闻文章的详细信息。
class NewsDetailFragment : Fragment(R.layout.fragment_news_detail) {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val args: NewsDetailFragmentArgs by navArgs()
val articleId = args.articleId
view.findViewById<TextView>(R.id.articleTextView).text = "Displaying details for article $articleId"
}
}
用户资料Fragment
创建UserProfileFragment.kt
,显示用户的资料信息。
class UserProfileFragment : Fragment(R.layout.fragment_user_profile) {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// 示例用户信息
view.findViewById<TextView>(R.id.userNameTextView).text = "John Doe"
view.findViewById<TextView>(R.id.userEmailTextView).text = "john.doe@example.com"
}
}
第三步:运行和测试
现在,我们已经完成了所有必要的步骤,可以运行应用程序并测试导航功能。
- 启动应用程序,底部导航栏将显示新闻列表和用户资料页面。
- 在新闻列表页面,点击任意文章将导航到新闻详情页面,并显示选定文章的详细信息。
- 点击底部导航栏中的用户资料图标,将导航到用户资料页面,显示用户的相关信息。
结论
通过这个实践案例,我们展示了如何使用Jetpack Navigation创建一个简单的新闻应用。我们涵盖了设置导航图、在Fragment之间导航、传递数据、处理返回操作以及集成底部导航。Jetpack Navigation提供了强大且灵活的解决方案,使得管理复杂的导航场景变得更加简单和高效。
Best regards!