Navigation Drawer

pull/3/head
Arthur VALIN 2 years ago
parent 938502d078
commit c652ef7eaa

@ -5,12 +5,12 @@ plugins {
android { android {
namespace 'fr.iut.alldev.allin' namespace 'fr.iut.alldev.allin'
compileSdk 33 compileSdk 34
defaultConfig { defaultConfig {
applicationId "fr.iut.alldev.allin" applicationId "fr.iut.alldev.allin"
minSdk 21 minSdk 21
targetSdk 33 targetSdk 34
versionCode 1 versionCode 1
versionName "1.0" versionName "1.0"
@ -48,13 +48,16 @@ android {
dependencies { dependencies {
implementation 'androidx.core:core-ktx:1.7.0' implementation 'androidx.core:core-ktx:1.12.0'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1' implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.6.2'
implementation 'androidx.activity:activity-compose:1.3.1' implementation 'androidx.activity:activity-compose:1.7.2'
implementation "androidx.compose.ui:ui:$compose_version" implementation "androidx.compose.ui:ui:$compose_version"
implementation "androidx.compose.ui:ui-tooling-preview:$compose_version" implementation "androidx.compose.ui:ui-tooling-preview:$compose_version"
implementation 'androidx.compose.material3:material3:1.0.0-alpha11' implementation 'androidx.compose.material3:material3:1.2.0-alpha07'
implementation "androidx.navigation:navigation-compose:2.7.2"
testImplementation 'junit:junit:4.13.2' testImplementation 'junit:junit:4.13.2'
implementation 'androidx.compose.material:material-icons-core'
implementation 'androidx.compose.material:material-icons-extended'
androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version" androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version"

@ -3,41 +3,19 @@ package fr.iut.alldev.allin
import android.os.Bundle import android.os.Bundle
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme import fr.iut.alldev.allin.ui.core.AllInDrawer
import androidx.compose.material3.Surface import fr.iut.alldev.allin.ui.theme.AllInTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import fr.iut.alldev.allin.ui.theme.AllinTheme
class MainActivity : ComponentActivity() { class MainActivity : ComponentActivity() {
@OptIn(ExperimentalMaterial3Api::class)
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContent { setContent {
AllinTheme { AllInTheme {
// A surface container using the 'background' color from the theme AllInDrawer()
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
Greeting("Android")
} }
}
}
}
}
@Composable }
fun Greeting(name: String) {
Text(text = "Hello $name!")
}
@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
AllinTheme {
Greeting("Android")
} }
} }

@ -0,0 +1,44 @@
package fr.iut.alldev.allin.ui.core
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ShoppingCart
import androidx.compose.material3.Card
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import fr.iut.alldev.allin.ui.theme.AllInTheme
@Composable
fun CoinCounter(amount:Int, modifier: Modifier = Modifier) {
Card(modifier = modifier.wrapContentSize(), shape = RoundedCornerShape(topStartPercent = 50, bottomStartPercent = 50)) {
Row(modifier = Modifier.background(AllInTheme.colors.white)
.padding(horizontal = 13.dp, vertical = 5.dp),
verticalAlignment = Alignment.CenterVertically) {
Icon(Icons.Default.ShoppingCart,
tint = AllInTheme.colors.allIn_Dark,
contentDescription = null,
modifier = Modifier.padding(end = 8.dp))
Text(text = amount.toString(),
color = AllInTheme.colors.allIn_Dark,
fontWeight = FontWeight.W800,
fontSize = 20.sp)
}
}
}
@Preview
@Composable
private fun CoinCounterPreview() {
CoinCounter(547)
}

@ -0,0 +1,118 @@
package fr.iut.alldev.allin.ui.core
import androidx.compose.foundation.layout.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Settings
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.navigation.NavHostController
import androidx.navigation.compose.rememberNavController
import fr.iut.alldev.allin.ui.theme.AllInTheme
import kotlinx.coroutines.launch
import kotlin.math.abs
sealed class TopLevelDestination(
val route: String,
val title: String,
val subtitle: String,
) {
object BET : TopLevelDestination(route = "BET", title = "CREER UN BET", subtitle = "Créez un nouveau BET et faites participer vos amis.")
object BET_HISTORY : TopLevelDestination(route = "BET_HISTORY", title = "HISTORIQUE DES BETS", subtitle = "Consultez vos paris en cours et terminés.")
object FRIENDS : TopLevelDestination(route = "FRIENDS", title = "AMIS", subtitle = "Défiez vos porches en les ajoutant en amis.")
object CURRENT_BETS : TopLevelDestination(route = "CURRENT_BETS", title = "BETS EN COURS", subtitle = "Gérez vos bets et récompensez les gagnants.")
}
val topLevelDestinations = listOf(
TopLevelDestination.BET,
TopLevelDestination.BET_HISTORY,
TopLevelDestination.FRIENDS,
TopLevelDestination.CURRENT_BETS
)
@Composable
fun AllInDrawer(
navController: NavHostController = rememberNavController(),
drawerState: DrawerState = rememberDrawerState(initialValue = DrawerValue.Closed)
) {
val scope = rememberCoroutineScope()
val drawerOffset = derivedStateOf { drawerState.offset.value }
var drawerWidth by remember {
mutableStateOf(drawerState.offset.value)
}
LaunchedEffect(drawerWidth == 0f) {
drawerWidth = drawerState.offset.value
}
ModalNavigationDrawer(
drawerState = drawerState,
drawerContent = {
ModalDrawerSheet(
drawerShape = RectangleShape,
drawerContainerColor = AllInTheme.colors.allIn_Dark
) {
Column(
Modifier
.padding(top = 39.dp, bottom = 26.dp)
.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally){
ProfilePicture()
Spacer(modifier = Modifier.height(12.dp))
Text(text = "Pseudo",
fontSize = 20.sp,
color = AllInTheme.colors.allIn_LighterGrey,
textAlign = TextAlign.Center,
fontWeight = FontWeight.W700)
}
topLevelDestinations.forEach { item ->
DrawerCell(
title = item.title,
subtitle = item.subtitle,
emoji = null,
onClick = { scope.launch { drawerState.close() } },
modifier = Modifier.padding(vertical = 5.dp, horizontal = 13.dp)
)
}
Box(
Modifier
.fillMaxSize()
.padding(start = 19.dp, bottom = 10.dp)) {
IconButton(onClick = { /*TODO*/ },
modifier = Modifier.align(Alignment.BottomStart)){
Icon(imageVector = Icons.Filled.Settings,
modifier = Modifier.size(40.dp),
tint = AllInTheme.colors.allIn_DarkGrey,
contentDescription = null)
}
}
}
}
) {
Scaffold(
modifier = Modifier.offset( x = with(LocalDensity.current) {
(abs(drawerWidth) + drawerOffset.value).toDp()
}),
topBar = { AllInTopBar(onMenuClicked = { scope.launch { drawerState.open() } }, coinAmount = 541) }// TODO: CoinAmount
) {
Column(
modifier = Modifier
.padding(it)
.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally
) {
}
}
}
}

@ -0,0 +1,67 @@
package fr.iut.alldev.allin.ui.core
import android.media.Image
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ChevronRight
import androidx.compose.material.icons.filled.Face
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import fr.iut.alldev.allin.ui.theme.AllInTheme
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun DrawerCell(
title: String,
subtitle: String,
emoji: Image?,
onClick: ()->Unit,
modifier: Modifier = Modifier
) {
Card(onClick = onClick,
modifier = modifier,
border = BorderStroke(width = 1.dp, color = AllInTheme.colors.allIn_DarkGrey),
shape = RoundedCornerShape(20),
colors = CardDefaults.cardColors(containerColor = AllInTheme.colors.allIn_DarkerGrey)) {
Row(modifier = Modifier.padding(horizontal = 10.dp, vertical = 17.dp)) {
Icon(imageVector = Icons.Default.Face,
contentDescription = null,
modifier = Modifier.padding(end = 11.dp))
Column(modifier = Modifier.weight(1f)) {
Text(
text = title,
fontSize = 13.sp,
color = AllInTheme.colors.white,
fontWeight = FontWeight.W700
)
Text(text = subtitle,
fontSize = 9.sp,
color = AllInTheme.colors.allIn_LightGrey)
}
Icon(imageVector = Icons.Default.ChevronRight,
tint = AllInTheme.colors.allIn_DarkGrey,
contentDescription = null)
}
}
}
@Preview
@Composable
private fun DrawerCellPreview() {
DrawerCell(
title = "CREER UN BET",
subtitle = "Créez un nouveau BET",
emoji = null,
onClick = {}
)
}

@ -0,0 +1,35 @@
package fr.iut.alldev.allin.ui.core
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Camera
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.Icon
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import fr.iut.alldev.allin.ui.theme.AllInTheme
@Composable
@Preview
fun ProfilePicture() {
Card(
modifier = Modifier.size(80.dp),
shape = RoundedCornerShape(100),
colors = CardDefaults.cardColors(containerColor = AllInTheme.colors.allIn_DarkerGrey),
border = BorderStroke(1.dp, AllInTheme.colors.allIn_DarkGrey)
) {
Box(Modifier.fillMaxSize()) {
Icon(imageVector = Icons.Filled.Camera,
contentDescription = null,
modifier = Modifier.align(Alignment.Center))
}
}
}

@ -0,0 +1,44 @@
package fr.iut.alldev.allin.ui.core
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Menu
import androidx.compose.material.icons.filled.Star
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import fr.iut.alldev.allin.ui.theme.AllInTheme
@Composable
fun AllInTopBar(
onMenuClicked: ()->Unit,
coinAmount: Int
) {
Box(modifier = Modifier.height(86.dp).fillMaxWidth()
.background(brush = AllInTheme.colors.allIn_gradient)) {
IconButton(onClick = onMenuClicked,
modifier = Modifier.align(Alignment.CenterStart)) {
Icon(Icons.Default.Menu,
contentDescription = null,
tint = Color.White)
}
Icon(Icons.Default.Star,
contentDescription = null,
tint = AllInTheme.colors.white,
modifier = Modifier.size(50.dp)
.align(Alignment.Center))
CoinCounter(amount = coinAmount, modifier = Modifier.align(Alignment.CenterEnd))
}
}
@Preview
@Composable
private fun AllInTopBarPreview(){
AllInTopBar(onMenuClicked = { }, coinAmount = 541)
}

@ -0,0 +1,9 @@
package fr.iut.alldev.allin.ui.home
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
@Composable
fun Home(){
Text(text = "HOME")
}

@ -0,0 +1,33 @@
package fr.iut.alldev.allin.ui.navigation
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import fr.iut.alldev.allin.ui.home.Home
import fr.iut.alldev.allin.ui.profile.Profile
object Routes {
const val HOME = "home"
const val PROFILE = "profile"
}
@Composable
fun AllInNavHost(modifier: Modifier = Modifier,
navController: NavHostController = rememberNavController(),
startDestination: String = Routes.PROFILE
) {
NavHost(
navController = navController,
startDestination = startDestination,
modifier = modifier.fillMaxSize()
) {
composable(route = Routes.HOME){ Home() }
composable(route = Routes.PROFILE){ Profile() }
}
}

@ -0,0 +1,9 @@
package fr.iut.alldev.allin.ui.profile
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
@Composable
fun Profile(){
Text(text = "PROFILE")
}

@ -1,11 +1,42 @@
package fr.iut.alldev.allin.ui.theme package fr.iut.alldev.allin.ui.theme
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.staticCompositionLocalOf
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
val Purple80 = Color(0xFFD0BCFF) @Immutable
val PurpleGrey80 = Color(0xFFCCC2DC) data class AllInColors(
val Pink80 = Color(0xFFEFB8C8) val allIn_Dark: Color,
val allIn_DarkerGrey: Color,
val allIn_DarkGrey: Color,
val allIn_Grey: Color,
val allIn_LightGrey: Color,
val allIn_LighterGrey: Color,
val allIn_White: Color,
val white: Color,
val allIn_Pink: Color,
val allIn_gradient: Brush
)
val Purple40 = Color(0xFF6650a4) internal val LocalColors = staticCompositionLocalOf {
val PurpleGrey40 = Color(0xFF625b71) AllInColors(
val Pink40 = Color(0xFF7D5260) allIn_Dark = Color(0xFF2A2A2A),
allIn_DarkerGrey = Color(0xFF393939),
allIn_DarkGrey = Color(0xFF454545),
allIn_Grey = Color(0xFF525252),
allIn_LightGrey = Color(0XFFAAAAAA),
allIn_LighterGrey = Color(0XFFC5C5C5),
allIn_White = Color(0xFFEBEBF6),
white = Color(0xFFFFFFFF),
allIn_Pink = Color(0xFFFF2A89),
allIn_gradient = Brush.linearGradient(
0.0f to Color(0xFFf951a8),
0.5f to Color(0xFFaa7ef3),
1.1f to Color(0xFF199fee),
start = Offset(0f, Float.POSITIVE_INFINITY),
end = Offset(Float.POSITIVE_INFINITY, 0f)
)
)
}

@ -1,68 +1,20 @@
package fr.iut.alldev.allin.ui.theme package fr.iut.alldev.allin.ui.theme
import android.app.Activity
import android.os.Build
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.dynamicDarkColorScheme
import androidx.compose.material3.dynamicLightColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.graphics.toArgb import androidx.compose.runtime.ReadOnlyComposable
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalView
import androidx.core.view.ViewCompat
private val DarkColorScheme = darkColorScheme(
primary = Purple80,
secondary = PurpleGrey80,
tertiary = Pink80
)
private val LightColorScheme = lightColorScheme(
primary = Purple40,
secondary = PurpleGrey40,
tertiary = Pink40
/* Other default colors to override
background = Color(0xFFFFFBFE),
surface = Color(0xFFFFFBFE),
onPrimary = Color.White,
onSecondary = Color.White,
onTertiary = Color.White,
onBackground = Color(0xFF1C1B1F),
onSurface = Color(0xFF1C1B1F),
*/
)
@Composable @Composable
fun AllinTheme( fun AllInTheme(content: @Composable () -> Unit) {
darkTheme: Boolean = isSystemInDarkTheme(), CompositionLocalProvider(
// Dynamic color is available on Android 12+ LocalColors provides LocalColors.current,
dynamicColor: Boolean = true,
content: @Composable () -> Unit
) {
val colorScheme = when {
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
val context = LocalContext.current
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
}
darkTheme -> DarkColorScheme
else -> LightColorScheme
}
val view = LocalView.current
if (!view.isInEditMode) {
SideEffect {
(view.context as Activity).window.statusBarColor = colorScheme.primary.toArgb()
ViewCompat.getWindowInsetsController(view)?.isAppearanceLightStatusBars = darkTheme
}
}
MaterialTheme(
colorScheme = colorScheme,
typography = Typography,
content = content content = content
) )
} }
object AllInTheme {
val colors: AllInColors
@Composable
@ReadOnlyComposable
get() = LocalColors.current
}
Loading…
Cancel
Save