добавление nullable функционала к компонентам. Переписанный каледарь, почти даже работает
This commit is contained in:
+9
-1
@@ -4,7 +4,7 @@ plugins {
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdk 32
|
||||
compileSdk 33
|
||||
|
||||
defaultConfig {
|
||||
applicationId "ru.megboyzz.dnevnik"
|
||||
@@ -17,6 +17,7 @@ android {
|
||||
vectorDrawables {
|
||||
useSupportLibrary true
|
||||
}
|
||||
multiDexEnabled true
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
@@ -32,6 +33,7 @@ android {
|
||||
}
|
||||
kotlinOptions {
|
||||
jvmTarget = '1.8'
|
||||
freeCompilerArgs = ['-Xjvm-default=compatibility']
|
||||
}
|
||||
buildFeatures {
|
||||
compose true
|
||||
@@ -75,4 +77,10 @@ dependencies {
|
||||
|
||||
//Библиотечка для рисования круговых диаграмок
|
||||
implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0'
|
||||
|
||||
//LazyHorizontalGrid
|
||||
implementation 'androidx.compose.foundation:foundation:1.3.1'
|
||||
|
||||
// The compose calendar library
|
||||
implementation 'com.kizitonwose.calendar:compose:2.1.1'
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import ru.megboyzz.dnevnik.navigation.AppNavHost
|
||||
import ru.megboyzz.dnevnik.ui.theme.*
|
||||
|
||||
class MainActivity : ComponentActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
@@ -1,131 +0,0 @@
|
||||
package ru.megboyzz.dnevnik
|
||||
|
||||
import androidx.compose.animation.ExperimentalAnimationApi
|
||||
import androidx.compose.foundation.BorderStroke
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.Card
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.material.rememberScaffoldState
|
||||
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 com.google.accompanist.navigation.animation.rememberAnimatedNavController
|
||||
import ru.megboyzz.dnevnik.screens.ui.*
|
||||
import ru.megboyzz.dnevnik.ui.theme.mainBlue
|
||||
import ru.megboyzz.dnevnik.ui.theme.white
|
||||
|
||||
//Файл со всеми превьюшками
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun text() {
|
||||
Row(Modifier.fillMaxWidth()) {
|
||||
AlmostOutlinedText(text = "Здарова карова")
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalAnimationApi::class)
|
||||
@Preview
|
||||
@Composable
|
||||
fun DrawerPrev() {
|
||||
val scaffoldState = rememberScaffoldState()
|
||||
val navController = rememberAnimatedNavController()
|
||||
Box(Modifier.background(mainBlue)) {
|
||||
DrawerContent(navController = navController, scaffoldState = scaffoldState)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun CardWithAveragePrev() {
|
||||
CardWithAverage(
|
||||
averageMark = 4.33f,
|
||||
resultMark = 4f
|
||||
) {
|
||||
Box(Modifier.padding(10.dp)){
|
||||
Text("hehe")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun BaseCardPrev() {
|
||||
Box(
|
||||
Modifier
|
||||
.fillMaxSize()
|
||||
){
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(10.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 20.dp)
|
||||
) {
|
||||
|
||||
Card(
|
||||
backgroundColor = white,
|
||||
shape = RoundedCornerShape(10.dp),
|
||||
border = BorderStroke(
|
||||
width = 1.dp,
|
||||
color = mainBlue
|
||||
),
|
||||
modifier = Modifier.defaultMinSize(minWidth = 300.dp)
|
||||
) {
|
||||
Box(
|
||||
Modifier
|
||||
.size(50.dp)
|
||||
.background(Color.Red)){}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun MonthTglPrev() {
|
||||
MonthToggle(
|
||||
startMonth = Month.January, startYear = 2023
|
||||
){
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun UnderlinedTextPrev() {
|
||||
Box(Modifier.background(white)){
|
||||
UnderlinedText(text = "Общая сводка")
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun CirclePrev() {
|
||||
val list = listOf(
|
||||
PieChartData(legend = "История", value=5),
|
||||
PieChartData(legend = "Русский язык", value=4),
|
||||
PieChartData(legend = "Химия", value=1),
|
||||
PieChartData(legend = "Математика", value=3)
|
||||
)
|
||||
PieChart(list)
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun GoodPieChartPrev() {
|
||||
val list = listOf(
|
||||
PieChartData(legend = "История", value=5),
|
||||
PieChartData(legend = "Русский язык", value=4),
|
||||
PieChartData(legend = "Химия", value=1),
|
||||
PieChartData(legend = "Математика", value=3),
|
||||
)
|
||||
PieChart(diagramData = list)
|
||||
}
|
||||
@@ -31,6 +31,7 @@ import java.time.DayOfWeek
|
||||
import java.time.LocalDate
|
||||
import java.time.Year
|
||||
import java.time.temporal.TemporalAdjusters
|
||||
import java.util.*
|
||||
|
||||
@Composable
|
||||
fun Int.AsPainter() = painterResource(this)
|
||||
@@ -136,3 +137,5 @@ fun Modifier.mainClickable(
|
||||
),
|
||||
onClick = onClick
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import androidx.navigation.NavController
|
||||
import ru.megboyzz.dnevnik.navigation.AppNavRoute
|
||||
import ru.megboyzz.dnevnik.screens.ui.LoginScreenContent
|
||||
|
||||
//TODO Переверстать экран входа
|
||||
@Composable
|
||||
fun LoginScreen(navController: NavController) {
|
||||
|
||||
|
||||
@@ -0,0 +1,206 @@
|
||||
package ru.megboyzz.dnevnik.screens.ui
|
||||
|
||||
import android.util.Log
|
||||
import androidx.compose.foundation.*
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.Card
|
||||
import androidx.compose.material.Divider
|
||||
import androidx.compose.material.IconButton
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.kizitonwose.calendar.compose.CalendarState
|
||||
import com.kizitonwose.calendar.compose.HorizontalCalendar
|
||||
import com.kizitonwose.calendar.compose.WeekCalendar
|
||||
import com.kizitonwose.calendar.compose.rememberCalendarState
|
||||
import com.kizitonwose.calendar.compose.weekcalendar.rememberWeekCalendarState
|
||||
import com.kizitonwose.calendar.core.CalendarDay
|
||||
import com.kizitonwose.calendar.core.CalendarMonth
|
||||
import com.kizitonwose.calendar.core.DayPosition
|
||||
import com.kizitonwose.calendar.core.firstDayOfWeekFromLocale
|
||||
import ru.megboyzz.dnevnik.AsPainter
|
||||
import ru.megboyzz.dnevnik.AsString
|
||||
import ru.megboyzz.dnevnik.R
|
||||
import ru.megboyzz.dnevnik.ui.theme.*
|
||||
import java.time.DayOfWeek
|
||||
import java.time.LocalDate
|
||||
import java.time.YearMonth
|
||||
import java.time.format.TextStyle
|
||||
import java.util.*
|
||||
|
||||
@Composable
|
||||
fun MonthToggler(calendarState: CalendarState) {
|
||||
|
||||
//TODO убрать это куда нибудь
|
||||
var listOfMonth = listOf(
|
||||
R.string.title_january.AsString(),
|
||||
R.string.title_february.AsString(),
|
||||
R.string.title_march.AsString(),
|
||||
R.string.title_april.AsString(),
|
||||
R.string.title_may.AsString(),
|
||||
R.string.title_june.AsString(),
|
||||
R.string.title_july.AsString(),
|
||||
R.string.title_august.AsString(),
|
||||
R.string.title_september.AsString(),
|
||||
R.string.title_october.AsString(),
|
||||
R.string.title_november.AsString(),
|
||||
R.string.title_december.AsString()
|
||||
)
|
||||
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(0.dp, 20.dp),
|
||||
horizontalArrangement = Arrangement.Center
|
||||
) {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.SpaceEvenly,
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
IconButton(onClick = { calendarState.startMonth = calendarState.startMonth.minusMonths(1) }) {
|
||||
Image(
|
||||
painter = R.drawable.ic_month_swipe_left.AsPainter(),
|
||||
contentDescription = "left",
|
||||
alignment = Alignment.Center
|
||||
)
|
||||
}
|
||||
for(style in TextStyle.values())
|
||||
Log.i("check", calendarState.startMonth.month.getDisplayName(style, Locale.getDefault()))
|
||||
Text(
|
||||
//TODO Возможно стоит сделать эту строчку меньше((
|
||||
text = "${listOfMonth[calendarState.startMonth.month.ordinal]} ${calendarState.startMonth.year}",
|
||||
style = H1,
|
||||
color = dark
|
||||
)
|
||||
IconButton(
|
||||
onClick = { calendarState.startMonth = calendarState.startMonth.plusMonths(1) }
|
||||
) {
|
||||
Image(
|
||||
painter = R.drawable.ic_month_swipe_right.AsPainter(),
|
||||
contentDescription = "right",
|
||||
alignment = Alignment.Center
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Composable
|
||||
fun NiceCalendar(
|
||||
startMonth: YearMonth,
|
||||
onClick: (day: CalendarDay, month: YearMonth, year: Int) -> Unit
|
||||
) {
|
||||
val endMonth = startMonth.plusMonths(100) // Adjust as needed
|
||||
val firstDayOfWeek = remember { firstDayOfWeekFromLocale() } // Available from the library
|
||||
|
||||
val state = rememberCalendarState(
|
||||
startMonth = startMonth,
|
||||
endMonth = endMonth,
|
||||
firstVisibleMonth = startMonth,
|
||||
firstDayOfWeek = firstDayOfWeek
|
||||
)
|
||||
|
||||
val weekState = rememberWeekCalendarState(
|
||||
startDate = startMonth.atDay(1),
|
||||
endDate = startMonth.atDay(7),
|
||||
firstVisibleWeekDate = startMonth.atDay(1),
|
||||
firstDayOfWeek = firstDayOfWeek
|
||||
)
|
||||
|
||||
var selectedDate by remember { mutableStateOf<LocalDate?>(null) }
|
||||
|
||||
Column() {
|
||||
|
||||
MonthToggler(calendarState = state)
|
||||
|
||||
Card(
|
||||
shape = RoundedCornerShape(10.dp),
|
||||
modifier = Modifier.defaultMinSize(300.dp)
|
||||
) {
|
||||
if(selectedDate == null)
|
||||
HorizontalCalendar(
|
||||
state = state,
|
||||
dayContent = { day ->
|
||||
Day(day, isSelected = selectedDate == day.date) { day ->
|
||||
selectedDate = if (selectedDate == day.date) null else day.date
|
||||
onClick(day, startMonth, startMonth.year)
|
||||
}
|
||||
},
|
||||
monthHeader = { month ->
|
||||
DaysOfWeekTitle(daysOfWeek = DayOfWeek.values().asList())
|
||||
},
|
||||
modifier = Modifier.padding(10.dp)
|
||||
)
|
||||
else
|
||||
WeekCalendar(
|
||||
state = weekState,
|
||||
weekHeader = { _ ->
|
||||
DaysOfWeekTitle(daysOfWeek = DayOfWeek.values().asList())
|
||||
},
|
||||
dayContent = { day ->
|
||||
Day(CalendarDay(day.date, DayPosition.InDate), isSelected = selectedDate == day.date) { day ->
|
||||
selectedDate = if (selectedDate == day.date) null else day.date
|
||||
onClick(day, startMonth, startMonth.year)
|
||||
}
|
||||
},
|
||||
modifier = Modifier.padding(10.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun DaysOfWeekTitle(daysOfWeek: List<DayOfWeek>) {
|
||||
Column {
|
||||
Row(modifier = Modifier.fillMaxWidth()) {
|
||||
for (dayOfWeek in daysOfWeek) {
|
||||
Text(
|
||||
modifier = Modifier.weight(1f),
|
||||
textAlign = TextAlign.Center,
|
||||
text = dayOfWeek.getDisplayName(TextStyle.SHORT, Locale.getDefault()).uppercase(),
|
||||
style = MainText
|
||||
)
|
||||
}
|
||||
}
|
||||
Divider(
|
||||
thickness = 1.dp,
|
||||
color = dark,
|
||||
modifier = Modifier.padding(vertical = 10.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
@Composable
|
||||
fun Day(day: CalendarDay, isSelected: Boolean, onClick: (CalendarDay) -> Unit) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.aspectRatio(ratio = 1f) // This is important for square sizing!
|
||||
.clip(CircleShape)
|
||||
.background(color = if (isSelected) lightGray else Color.Transparent)
|
||||
.border(
|
||||
border = BorderStroke(
|
||||
width = 1.dp,
|
||||
color = if (isSelected) mainBlue else Color.Transparent
|
||||
),
|
||||
shape = CircleShape
|
||||
)
|
||||
.clickable(
|
||||
enabled = day.position == DayPosition.MonthDate,
|
||||
onClick = { onClick(day) }
|
||||
),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Text(
|
||||
text = day.date.dayOfMonth.toString(),
|
||||
style = MainText,
|
||||
color = if (day.position == DayPosition.MonthDate) dark else Color.Gray
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,13 @@
|
||||
package ru.megboyzz.dnevnik.screens.ui
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import androidx.compose.animation.*
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.foundation.*
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.grid.GridCells
|
||||
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
||||
import androidx.compose.foundation.lazy.grid.items
|
||||
import androidx.compose.foundation.selection.toggleable
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
@@ -24,9 +26,6 @@ import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.focus.FocusRequester
|
||||
import androidx.compose.ui.focus.focusRequester
|
||||
import androidx.compose.ui.focus.onFocusChanged
|
||||
import androidx.compose.ui.geometry.CornerRadius
|
||||
import androidx.compose.ui.geometry.RoundRect
|
||||
import androidx.compose.ui.geometry.Size
|
||||
import androidx.compose.ui.graphics.*
|
||||
import androidx.compose.ui.graphics.painter.Painter
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
@@ -38,11 +37,9 @@ import androidx.compose.ui.text.input.PasswordVisualTransformation
|
||||
import androidx.compose.ui.text.input.VisualTransformation
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.*
|
||||
import androidx.compose.ui.viewinterop.AndroidView
|
||||
import androidx.navigation.NavController
|
||||
import com.google.accompanist.navigation.animation.rememberAnimatedNavController
|
||||
import kotlinx.coroutines.launch
|
||||
import ru.megboyzz.dnevnik.*
|
||||
import ru.megboyzz.dnevnik.R
|
||||
@@ -177,7 +174,10 @@ fun BottomNavButton(
|
||||
onClick: () -> Unit,
|
||||
) {
|
||||
//Возможно стоит убрать анимацию клика
|
||||
Box(Modifier.mainClickable(onClick = onClick, radius = 20.dp).padding(10.dp)) {
|
||||
Box(
|
||||
Modifier
|
||||
.mainClickable(onClick = onClick, radius = 20.dp)
|
||||
.padding(10.dp)) {
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.Center
|
||||
@@ -655,8 +655,8 @@ fun AverageText(
|
||||
|
||||
@Composable
|
||||
fun CardWithAverage(
|
||||
averageMark: Float,
|
||||
resultMark: Float,
|
||||
averageMark: Float?,
|
||||
resultMark: Float?,
|
||||
minWidth: Dp = 300.dp,
|
||||
content: @Composable () -> Unit
|
||||
) {
|
||||
@@ -673,7 +673,10 @@ fun CardWithAverage(
|
||||
modifier = Modifier.size(50.dp),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
AverageText(title = R.string.title_average_mark.AsString(), mark = averageMark.toString())
|
||||
AverageText(
|
||||
title = R.string.title_average_mark.AsString(),
|
||||
mark = if(averageMark != null) "%.2f".format(averageMark).replace(",", ".") else "-"
|
||||
)
|
||||
}
|
||||
}
|
||||
Box(
|
||||
@@ -686,7 +689,7 @@ fun CardWithAverage(
|
||||
){
|
||||
AverageText(
|
||||
title = R.string.title_result_mark.AsString(),
|
||||
mark = resultMark.toString()
|
||||
mark = if(resultMark != null) resultMark.toString() else "-"
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -701,15 +704,7 @@ fun LastMarkCard(
|
||||
teacher: String,
|
||||
reason: String = "null"
|
||||
) {
|
||||
Card(
|
||||
backgroundColor = white,
|
||||
shape = RoundedCornerShape(10.dp),
|
||||
border = BorderStroke(
|
||||
width = 1.dp,
|
||||
color = mainBlue
|
||||
),
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
BaseCard {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
modifier = Modifier.padding(15.dp)
|
||||
@@ -766,6 +761,84 @@ enum class Month{
|
||||
December,
|
||||
}
|
||||
|
||||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
fun NewCardCalendar(
|
||||
month: Month,
|
||||
year: Int,
|
||||
onClick: (day: Int) -> Unit,
|
||||
) {
|
||||
val listOfDays = listOf(
|
||||
R.string.title_mon.AsString(),
|
||||
R.string.title_tue.AsString(),
|
||||
R.string.title_wed.AsString(),
|
||||
R.string.title_thu.AsString(),
|
||||
R.string.title_fri.AsString(),
|
||||
R.string.title_sat.AsString(),
|
||||
)
|
||||
|
||||
//TODO Сделать сворачивание календаря
|
||||
val expanded = remember {
|
||||
mutableStateOf(true)
|
||||
}
|
||||
|
||||
Card(
|
||||
backgroundColor = white,
|
||||
modifier = Modifier.defaultMinSize(minWidth = 300.dp),
|
||||
shape = RoundedCornerShape(10.dp),
|
||||
elevation = 5.dp
|
||||
){
|
||||
Column(
|
||||
modifier = Modifier.padding(0.dp)
|
||||
) {
|
||||
/*LazyRow(
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
modifier = Modifier
|
||||
.padding(10.dp, 10.dp, 10.dp, 5.dp)
|
||||
.defaultMinSize(minWidth = 300.dp)
|
||||
){
|
||||
items(listOfDays){
|
||||
Text(
|
||||
text = it,
|
||||
style = MainText,
|
||||
color = dark
|
||||
)
|
||||
}
|
||||
}
|
||||
Box(
|
||||
Modifier
|
||||
.defaultMinSize(minWidth = 320.dp)
|
||||
.height(1.dp)
|
||||
.background(Color.Black))*/
|
||||
LazyVerticalGrid(
|
||||
columns = GridCells.Fixed(count = 6),
|
||||
horizontalArrangement = Arrangement.spacedBy(0.dp),
|
||||
){
|
||||
items(listOfDays){
|
||||
Text(
|
||||
text = it,
|
||||
style = MainText,
|
||||
color = dark
|
||||
)
|
||||
}
|
||||
items((1..30).toList()){
|
||||
NumberOnCalendar(
|
||||
isClicked = remember { mutableStateOf(false) },
|
||||
number = it.toString()
|
||||
) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val offset = 8 - getMonthDaysBy(year, month, DayOfWeek.MONDAY)[0]
|
||||
|
||||
val clicked = mutableListOf<MutableState<Boolean>>()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun CardCalendar(
|
||||
month: Month,
|
||||
@@ -785,11 +858,10 @@ fun CardCalendar(
|
||||
val expanded = remember {
|
||||
mutableStateOf(true)
|
||||
}
|
||||
val expandedModifier = if(expanded.value) Modifier else Modifier.height(100.dp)
|
||||
|
||||
Card(
|
||||
backgroundColor = white,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
modifier = Modifier.defaultMinSize(minWidth = 200.dp),
|
||||
shape = RoundedCornerShape(10.dp),
|
||||
elevation = 5.dp
|
||||
){
|
||||
@@ -824,6 +896,8 @@ fun CardCalendar(
|
||||
val offset = 8 - getMonthDaysBy(year, month, DayOfWeek.MONDAY)[0]
|
||||
|
||||
val clicked = mutableListOf<MutableState<Boolean>>()
|
||||
var lastClicked = 0
|
||||
var lastInd = 0
|
||||
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
@@ -831,6 +905,7 @@ fun CardCalendar(
|
||||
.fillMaxWidth()
|
||||
.padding(0.dp, 10.dp, 0.dp, 5.dp)
|
||||
) {
|
||||
if(expanded.value)
|
||||
for(day in DayOfWeek.values()){
|
||||
if(day != DayOfWeek.SUNDAY) Column {
|
||||
val list = getMonthDaysBy(year, month, day)
|
||||
@@ -848,6 +923,8 @@ fun CardCalendar(
|
||||
number = data.toString()
|
||||
) {
|
||||
expanded.value != expanded.value
|
||||
lastClicked = data
|
||||
lastInd = i
|
||||
for(click in clicked)
|
||||
if(click != isClicked)
|
||||
click.value = false
|
||||
@@ -860,9 +937,10 @@ fun CardCalendar(
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -955,7 +1033,7 @@ fun MonthToggle(
|
||||
|
||||
val isNormal = screenWidth < 500
|
||||
if(!isNormal) defaultPadding *= 4
|
||||
Column(Modifier.padding(defaultPadding, 0.dp)) {
|
||||
Column() {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
@@ -1036,53 +1114,133 @@ fun UnderlinedText(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Класс для предоставления данных для круговых диаграм
|
||||
* Идея предоставить диаграмме массив именованных данных
|
||||
* напрмер кол-во оцеок отлично по всем предметам:
|
||||
* CircleDiagramData(parameterName = "История", count=5) = 38%
|
||||
* CircleDiagramData(parameterName = "Русский язык", count=4) = 31%
|
||||
* CircleDiagramData(parameterName = "Химия", count=1) = 8%
|
||||
* CircleDiagramData(parameterName = "Математика", count=3) = 23%
|
||||
*/
|
||||
@OptIn(ExperimentalGraphicsApi::class)
|
||||
data class PieChartData(
|
||||
val legend: String,
|
||||
val value: Int
|
||||
){
|
||||
val color: Color
|
||||
init {
|
||||
val hue = (0..360).random(kotlin.random.Random(System.nanoTime())).toFloat()
|
||||
Thread.sleep(10)
|
||||
color = Color.hsl(hue, 0.5f, 0.6f)
|
||||
@Composable
|
||||
fun AllMarksCard(
|
||||
subjectName: String,
|
||||
teacher: String?,
|
||||
marks: List<Int>?,
|
||||
resultMark: Float?
|
||||
) {
|
||||
CardWithAverage(
|
||||
averageMark = marks?.average()?.toFloat(),
|
||||
resultMark = resultMark
|
||||
) {
|
||||
Box(Modifier.padding(15.dp, 15.dp)) {
|
||||
Column {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(10.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Image(
|
||||
painter = R.drawable.ic_subject.AsPainter(),
|
||||
contentDescription = ""
|
||||
)
|
||||
Column(
|
||||
verticalArrangement = Arrangement.Center
|
||||
) {
|
||||
Text(
|
||||
text = subjectName,
|
||||
color = dark,
|
||||
style = MainText,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
Text(
|
||||
text = teacher ?: "-",
|
||||
color = dark,
|
||||
style = MainText,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Divider(
|
||||
color = dark,
|
||||
thickness = 1.dp,
|
||||
modifier = Modifier.padding(
|
||||
top = 15.dp,
|
||||
bottom = 10.dp,
|
||||
)
|
||||
)
|
||||
|
||||
if(marks != null)
|
||||
LazyVerticalGrid(
|
||||
columns = GridCells.Adaptive(minSize = 20.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(10.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(10.dp)
|
||||
) {
|
||||
items(marks){
|
||||
MarkInBox(mark = it)
|
||||
}
|
||||
}
|
||||
else {
|
||||
Box(
|
||||
contentAlignment = Alignment.Center,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
){
|
||||
EmptyMessage(message = R.string.title_no_marks.AsString())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun PieChart(
|
||||
diagramData: List<PieChartData>
|
||||
fun MarkInBox(mark: Int) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(19.dp)
|
||||
.fillMaxSize()
|
||||
.background(
|
||||
color = mainBlue,
|
||||
shape = RoundedCornerShape(2.dp)
|
||||
),
|
||||
contentAlignment = Alignment.Center
|
||||
){
|
||||
Text(
|
||||
text = mark.toString(),
|
||||
color = white
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ContentMessage(
|
||||
message: String,
|
||||
isFine: Boolean = true
|
||||
) {
|
||||
lateinit var chart: DataPieChart
|
||||
Column {
|
||||
AndroidView(
|
||||
factory = { context ->
|
||||
chart = DataPieChart(context)
|
||||
chart
|
||||
},
|
||||
modifier = Modifier
|
||||
.wrapContentSize()
|
||||
.padding(5.dp),
|
||||
update = { chart.updatePieChartWithData(diagramData) }
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.defaultMinSize(200.dp)
|
||||
.padding(25.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Image(
|
||||
painter = if(isFine) R.drawable.ic_smile.AsPainter() else R.drawable.ic_sad_smile.AsPainter(),
|
||||
contentDescription = ""
|
||||
)
|
||||
SpacerHeight(height = 10.dp)
|
||||
Text(
|
||||
text = message,
|
||||
style = MainText,
|
||||
color = dark
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Composable
|
||||
fun PieChartCard(
|
||||
title: String,
|
||||
data: List<PieChartData>
|
||||
fun EmptyMessage(message: String) = ContentMessage(message = message, isFine = false)
|
||||
|
||||
@Composable
|
||||
fun FineMessage(message: String) = ContentMessage(message = message)
|
||||
|
||||
@Composable
|
||||
fun MessageCard(
|
||||
message: String,
|
||||
content: @Composable () -> Unit
|
||||
) {
|
||||
BaseCard {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,9 +22,10 @@ class DataPieChart(context: Context) : PieChart(context) {
|
||||
LayoutParams.MATCH_PARENT,
|
||||
)
|
||||
setUsePercentValues(true)
|
||||
setEntryLabelTextSize(10f)
|
||||
|
||||
description.isEnabled = false
|
||||
isDrawHoleEnabled = false
|
||||
|
||||
legend.isEnabled = false
|
||||
legend.orientation = Legend.LegendOrientation.VERTICAL
|
||||
legend.horizontalAlignment =
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
package ru.megboyzz.dnevnik.screens.ui
|
||||
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material.Text
|
||||
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.unit.dp
|
||||
import androidx.compose.ui.viewinterop.AndroidView
|
||||
import ru.megboyzz.dnevnik.AsString
|
||||
import ru.megboyzz.dnevnik.ui.theme.H2
|
||||
import ru.megboyzz.dnevnik.ui.theme.dark
|
||||
import ru.megboyzz.dnevnik.R
|
||||
|
||||
/**
|
||||
* Класс для предоставления данных для круговых диаграм
|
||||
* Идея предоставить диаграмме массив именованных данных
|
||||
* напрмер кол-во оцеок отлично по всем предметам:
|
||||
* CircleDiagramData(parameterName = "История", count=5) = 38%
|
||||
* CircleDiagramData(parameterName = "Русский язык", count=4) = 31%
|
||||
* CircleDiagramData(parameterName = "Химия", count=1) = 8%
|
||||
* CircleDiagramData(parameterName = "Математика", count=3) = 23%
|
||||
*/
|
||||
data class PieChartData(
|
||||
val legend: String,
|
||||
val value: Int
|
||||
){
|
||||
val color: Color
|
||||
init {
|
||||
val hue = (0..360).random(kotlin.random.Random(System.nanoTime())).toFloat()
|
||||
Thread.sleep(10)
|
||||
color = Color.hsl(hue, 0.5f, 0.6f)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun PieChart(
|
||||
diagramData: List<PieChartData>
|
||||
) {
|
||||
lateinit var chart: DataPieChart
|
||||
Column(Modifier.size(200.dp)) {
|
||||
AndroidView(
|
||||
factory = { context ->
|
||||
chart = DataPieChart(context)
|
||||
chart
|
||||
},
|
||||
modifier = Modifier
|
||||
.wrapContentSize()
|
||||
.padding(5.dp),
|
||||
update = { chart.updatePieChartWithData(diagramData) }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Composable
|
||||
fun PieChartCard(
|
||||
title: String,
|
||||
data: List<PieChartData>?
|
||||
) {
|
||||
BaseCard {
|
||||
Column(
|
||||
modifier = Modifier.padding(15.dp, 10.dp),
|
||||
){
|
||||
Text(
|
||||
text = title,
|
||||
style = H2,
|
||||
color = dark
|
||||
)
|
||||
Box(
|
||||
modifier = Modifier.defaultMinSize(300.dp),
|
||||
contentAlignment = Alignment.Center
|
||||
){
|
||||
if(data != null)
|
||||
PieChart(diagramData = data)
|
||||
else
|
||||
EmptyMessage(message = R.string.title_no_marks.AsString())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,266 @@
|
||||
package ru.megboyzz.dnevnik
|
||||
|
||||
import androidx.compose.animation.ExperimentalAnimationApi
|
||||
import androidx.compose.foundation.BorderStroke
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.*
|
||||
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 com.google.accompanist.navigation.animation.rememberAnimatedNavController
|
||||
import ru.megboyzz.dnevnik.screens.ui.*
|
||||
import ru.megboyzz.dnevnik.ui.theme.mainBlue
|
||||
import ru.megboyzz.dnevnik.ui.theme.white
|
||||
import java.time.YearMonth
|
||||
import java.util.*
|
||||
|
||||
//Файл со всеми превьюшками
|
||||
|
||||
@Composable
|
||||
fun NicePreviewContainer(
|
||||
content: @Composable () -> Unit
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.verticalScroll(rememberScrollState()).height(1500.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.spacedBy(10.dp)
|
||||
) { content() }
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun text() {
|
||||
Row(Modifier.fillMaxWidth()) {
|
||||
AlmostOutlinedText(text = "Здарова карова")
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalAnimationApi::class)
|
||||
@Preview
|
||||
@Composable
|
||||
fun DrawerPrev() {
|
||||
val scaffoldState = rememberScaffoldState()
|
||||
val navController = rememberAnimatedNavController()
|
||||
Box(Modifier.background(mainBlue)) {
|
||||
DrawerContent(navController = navController, scaffoldState = scaffoldState)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun CardWithAveragePrev() {
|
||||
CardWithAverage(
|
||||
averageMark = 4.33f,
|
||||
resultMark = 4f
|
||||
) {
|
||||
Box(Modifier.padding(10.dp)){
|
||||
Text("hehe")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun BaseCardPrev() {
|
||||
Box(
|
||||
Modifier
|
||||
.fillMaxSize()
|
||||
){
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(10.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 20.dp)
|
||||
) {
|
||||
|
||||
Card(
|
||||
backgroundColor = white,
|
||||
shape = RoundedCornerShape(10.dp),
|
||||
border = BorderStroke(
|
||||
width = 1.dp,
|
||||
color = mainBlue
|
||||
),
|
||||
modifier = Modifier.defaultMinSize(minWidth = 300.dp)
|
||||
) {
|
||||
Box(
|
||||
Modifier
|
||||
.size(50.dp)
|
||||
.background(Color.Red)){}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun MonthTglPrev() {
|
||||
MonthToggle(
|
||||
startMonth = Month.January, startYear = 2023
|
||||
){
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun UnderlinedTextPrev() {
|
||||
Box(Modifier.background(white)){
|
||||
UnderlinedText(text = "Общая сводка")
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun CirclePrev() {
|
||||
val list = listOf(
|
||||
PieChartData(legend = "История", value=5),
|
||||
PieChartData(legend = "Русский язык", value=4),
|
||||
PieChartData(legend = "Химия", value=1),
|
||||
PieChartData(legend = "Математика", value=3)
|
||||
)
|
||||
PieChart(list)
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun GoodPieChartPrev() {
|
||||
val list = listOf(
|
||||
PieChartData(legend = "История", value=5),
|
||||
PieChartData(legend = "Русский язык", value=4),
|
||||
PieChartData(legend = "Химия", value=1),
|
||||
PieChartData(legend = "Математика", value=3),
|
||||
)
|
||||
PieChart(diagramData = list)
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun PieChartCardPrev() {
|
||||
val list = listOf(
|
||||
PieChartData(legend = "История", value=5),
|
||||
PieChartData(legend = "Русский язык", value=4),
|
||||
PieChartData(legend = "Химия", value=1),
|
||||
PieChartData(legend = "Математика", value=3),
|
||||
)
|
||||
PieChartCard(
|
||||
title = "Сводка по оценкам отлично",
|
||||
data = list
|
||||
)
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun LastMarkCardPrev() {
|
||||
LastMarkCard(
|
||||
subjectName = "Русский язык",
|
||||
mark = 5,
|
||||
date = "18.02.2023",
|
||||
teacher = "Степанова А.С.",
|
||||
reason = "контрольная"
|
||||
)
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun AllMarksCardPrev1() {
|
||||
NicePreviewContainer {
|
||||
AllMarksCard(
|
||||
subjectName = "Математика",
|
||||
teacher = "Степанова С.А.",
|
||||
marks = listOf(4, 5, 5, 5, 5, 5, 4, 5, 3, 2),
|
||||
resultMark = 4f
|
||||
)
|
||||
AllMarksCard(
|
||||
subjectName = "Русский язык",
|
||||
teacher = "Степанова С.А.",
|
||||
marks = listOf(4, 5, 5, 5, 5, 5, 4, 5, 3, 2),
|
||||
resultMark = null
|
||||
)
|
||||
AllMarksCard(
|
||||
subjectName = "Русский язык",
|
||||
teacher = "Степанова С.А.",
|
||||
marks = null,
|
||||
resultMark = 4.2f
|
||||
)
|
||||
AllMarksCard(
|
||||
subjectName = "Русский язык",
|
||||
teacher = null,
|
||||
marks = listOf(4, 5, 5, 5, 5, 5, 4, 5, 3, 2),
|
||||
resultMark = 4.2f
|
||||
)
|
||||
|
||||
AllMarksCard(
|
||||
subjectName = "Математика",
|
||||
teacher = "Степанова С.А.",
|
||||
marks = null,
|
||||
resultMark = null
|
||||
)
|
||||
|
||||
AllMarksCard(
|
||||
subjectName = "Математика",
|
||||
teacher = null,
|
||||
marks = null,
|
||||
resultMark = null
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun NewCalendarPrev() {
|
||||
NewCardCalendar(
|
||||
month = Month.January,
|
||||
year = 2023
|
||||
){
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun NiceCalendarPrev() {
|
||||
NiceCalendar(
|
||||
startMonth = YearMonth.now()
|
||||
){ day, month, year ->
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun EmptyPrev() {
|
||||
ContentMessage(message = "Таких оценок нет")
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun PieChartNullPrev() {
|
||||
val list = listOf(
|
||||
PieChartData(legend = "История", value=5),
|
||||
PieChartData(legend = "Русский язык", value=4),
|
||||
PieChartData(legend = "Химия", value=1),
|
||||
PieChartData(legend = "Математика", value=3),
|
||||
)
|
||||
NicePreviewContainer {
|
||||
PieChartCard(
|
||||
title = "Сводка по оценкам отлично",
|
||||
data = list
|
||||
)
|
||||
PieChartCard(
|
||||
title = "Сводка по оценкам хорошо",
|
||||
data = null
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user