add navigation bar with fragments

master
Julien THEME 2 years ago
parent 4d34f8db47
commit dca834b7fc

@ -23,6 +23,11 @@ android {
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
buildFeatures {
viewBinding true
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8

@ -5,49 +5,39 @@ import android.os.Bundle
import android.widget.TextView
import androidx.activity.compose.setContent
import androidx.compose.material.MaterialTheme
import androidx.fragment.app.Fragment
import com.android.volley.VolleyError
import com.android.volley.toolbox.StringRequest
import com.android.volley.toolbox.Volley
import com.example.cinapp.databinding.ActivityMainBinding
import com.example.cinapp.model.Movie
import com.example.cinapp.navigation.MainScreen
import com.example.cinapp.navigation.MovieFragment
import com.example.cinapp.navigation.SearchFragment
import com.example.cinapp.navigation.SerieFragment
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//setContentView(R.layout.activity_main)
setContent {
MaterialTheme { MainScreen() }
}
/*
// TextView
val textView = findViewById<TextView>(R.id.text)
// Instantiate the RequestQueue.
val queue = Volley.newRequestQueue(this)
val url = "https://api.themoviedb.org/3/search/tv?api_key=e53e59cf1e29b9afff93d9ca1208f0cf&query=One%20Piece&language=fr"
private lateinit var binding : ActivityMainBinding
// Request a string response from the provided URL.
val stringRequest = StringRequest(url,
{ response ->
// Display the first 500 characters of the response string.
textView.text = "Response is: ${response.substring(0, 500)}"
},
{ error: VolleyError ->
textView.text = "That didn't work!"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
replaceFragment(MovieFragment())
binding.bottomNavigation.setOnItemSelectedListener {
when(it.itemId){
R.id.movie -> replaceFragment(MovieFragment())
R.id.serie -> replaceFragment(SerieFragment())
R.id.search -> replaceFragment(SearchFragment())
else -> false
}
)
// Add the request to the RequestQueue.
queue.add(stringRequest)
//bottom navigation with jetpack compose
*/
true
}
}
private fun replaceFragment(fragment: Fragment){
supportFragmentManager.beginTransaction().replace(R.id.frame_layout, fragment).commit()
}
}

@ -1,24 +0,0 @@
package com.example.cinapp.navigation
import androidx.compose.runtime.Composable
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
@Composable
fun BottomNavGraph(navController: NavHostController){
NavHost(
navController = navController,
startDestination = BottomNavigation.Movie.route
) {
composable(BottomNavigation.Movie.route) {
MovieScreen()
}
composable(BottomNavigation.Search.route) {
SearchScreen()
}
composable(BottomNavigation.Serie.route) {
SerieScreen()
}
}
}

@ -1,30 +0,0 @@
package com.example.cinapp.navigation
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Home
import androidx.compose.material.icons.filled.LiveTv
import androidx.compose.material.icons.filled.Movie
import androidx.compose.material.icons.filled.Search
import androidx.compose.ui.graphics.vector.ImageVector
sealed class BottomNavigation(
val route: String,
val icon: ImageVector,
val title: String
) {
object Movie : BottomNavigation(
route = "movie",
//icon = R.drawable.ic_baseline_movie_24,
icon = Icons.Filled.Movie,
title = "Movie")
object Search : BottomNavigation(
route = "search",
//icon = R.drawable.ic_baseline_search_24,
icon = Icons.Filled.Search,
title = "Search")
object Serie : BottomNavigation(
route = "serie",
//icon = R.drawable.ic_baseline_live_tv_24,
icon = Icons.Filled.LiveTv,
title = "Serie")
}

@ -1,78 +0,0 @@
package com.example.cinapp.navigation
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.padding
import androidx.compose.material.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.navigation.compose.rememberNavController
import androidx.compose.ui.Modifier
import androidx.navigation.NavDestination
import androidx.navigation.NavDestination.Companion.hierarchy
import androidx.navigation.NavGraph.Companion.findStartDestination
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.ui.setupWithNavController
@Composable
fun MainScreen() {
val navController = rememberNavController()
Scaffold(
bottomBar = { BottomBar(navController = navController) }
) {
BottomNavGraph(navController = navController)
}
}
@Composable
fun BottomBar(navController: NavHostController) {
val screens = listOf(
BottomNavigation.Movie,
BottomNavigation.Serie,
BottomNavigation.Search,
)
val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentDestination = navBackStackEntry?.destination
BottomNavigation {
screens.forEach { screen ->
AddItem(
screen = screen,
currentDestination = currentDestination,
navController = navController
)
}
}
}
@Composable
fun RowScope.AddItem(
screen: BottomNavigation,
currentDestination: NavDestination?,
navController: NavHostController
) {
BottomNavigationItem(
label = {
Text(text = screen.title)
},
icon = {
Icon(
imageVector = screen.icon,
contentDescription = "Navigation Icon"
)
},
selected = currentDestination?.hierarchy?.any {
it.route == screen.route
} == true,
unselectedContentColor = LocalContentColor.current.copy(alpha = ContentAlpha.disabled),
onClick = {
navController.navigate(screen.route) {
popUpTo(navController.graph.findStartDestination().id)
launchSingleTop = true
}
}
)
}

@ -1,8 +0,0 @@
package com.example.cinapp.navigation
import androidx.compose.runtime.Composable
@Composable
fun MovieScreen() {
}

@ -0,0 +1,60 @@
package com.example.cinapp.navigation
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.example.cinapp.R
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private const val ARG_PARAM1 = "param1"
private const val ARG_PARAM2 = "param2"
/**
* A simple [Fragment] subclass.
* Use the [MovieFragment.newInstance] factory method to
* create an instance of this fragment.
*/
class MovieFragment : Fragment() {
// TODO: Rename and change types of parameters
private var param1: String? = null
private var param2: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
param1 = it.getString(ARG_PARAM1)
param2 = it.getString(ARG_PARAM2)
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_movie, container, false)
}
companion object {
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment MovieFragment.
*/
// TODO: Rename and change types and number of parameters
@JvmStatic
fun newInstance(param1: String, param2: String) =
MovieFragment().apply {
arguments = Bundle().apply {
putString(ARG_PARAM1, param1)
putString(ARG_PARAM2, param2)
}
}
}
}

@ -1,8 +0,0 @@
package com.example.cinapp.navigation
import androidx.compose.runtime.Composable
@Composable
fun SerieScreen() {
}

@ -0,0 +1,60 @@
package com.example.cinapp.navigation
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.example.cinapp.R
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private const val ARG_PARAM1 = "param1"
private const val ARG_PARAM2 = "param2"
/**
* A simple [Fragment] subclass.
* Use the [SearchFragment.newInstance] factory method to
* create an instance of this fragment.
*/
class SearchFragment : Fragment() {
// TODO: Rename and change types of parameters
private var param1: String? = null
private var param2: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
param1 = it.getString(ARG_PARAM1)
param2 = it.getString(ARG_PARAM2)
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_search, container, false)
}
companion object {
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment SearchFragment.
*/
// TODO: Rename and change types and number of parameters
@JvmStatic
fun newInstance(param1: String, param2: String) =
SearchFragment().apply {
arguments = Bundle().apply {
putString(ARG_PARAM1, param1)
putString(ARG_PARAM2, param2)
}
}
}
}

@ -1,8 +0,0 @@
package com.example.cinapp.navigation
import androidx.compose.runtime.Composable
@Composable
fun SearchScreen() {
}

@ -0,0 +1,60 @@
package com.example.cinapp.navigation
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.example.cinapp.R
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private const val ARG_PARAM1 = "param1"
private const val ARG_PARAM2 = "param2"
/**
* A simple [Fragment] subclass.
* Use the [SerieFragment.newInstance] factory method to
* create an instance of this fragment.
*/
class SerieFragment : Fragment() {
// TODO: Rename and change types of parameters
private var param1: String? = null
private var param2: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
param1 = it.getString(ARG_PARAM1)
param2 = it.getString(ARG_PARAM2)
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_serie, container, false)
}
companion object {
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment SerieFragment.
*/
// TODO: Rename and change types and number of parameters
@JvmStatic
fun newInstance(param1: String, param2: String) =
SerieFragment().apply {
arguments = Bundle().apply {
putString(ARG_PARAM1, param1)
putString(ARG_PARAM2, param2)
}
}
}
}

@ -6,14 +6,24 @@
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
<FrameLayout
android:id="@+id/frame_layout"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@+id/bottom_navigation"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</FrameLayout>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_navigation"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
app:menu="@menu/bottom_nav" />
</androidx.constraintlayout.widget.ConstraintLayout>

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/material_dynamic_secondary30"
tools:context=".navigation.MovieFragment">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Movie"
android:textSize="26dp"
android:layout_gravity="center"/>
</FrameLayout>

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/purple_700"
tools:context=".navigation.SearchFragment">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Search"
android:textSize="26dp"
android:layout_gravity="center"/>
</FrameLayout>

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/purple_200"
tools:context=".navigation.SerieFragment">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Serie"
android:textSize="26dp"
android:layout_gravity="center"/>
</FrameLayout>

@ -1,37 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="409dp"
android:layout_height="43dp"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.428"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.997">
<Button
android:id="@+id/button4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button" />
<Button
android:id="@+id/button6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button" />
<Button
android:id="@+id/button5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:title="Movie"
android:id="@+id/movie"
android:icon="@drawable/ic_baseline_movie_24" />
<item android:title="Serie"
android:id="@+id/serie"
android:icon="@drawable/ic_baseline_live_tv_24" />
<item android:title="Search"
android:id="@+id/search"
android:icon="@drawable/ic_baseline_search_24" />
</menu>

@ -1,3 +1,5 @@
<resources>
<string name="app_name">Cin\'app</string>
<!-- TODO: Remove or change this placeholder text -->
<string name="hello_blank_fragment">Hello blank fragment</string>
</resources>
Loading…
Cancel
Save