добавление nullable функционала к компонентам. Переписанный каледарь, почти даже работает

This commit is contained in:
2023-03-01 01:23:08 +03:00
parent cd03be5394
commit 7b2c04c595
10 changed files with 790 additions and 195 deletions
+9 -1
View File
@@ -4,7 +4,7 @@ plugins {
} }
android { android {
compileSdk 32 compileSdk 33
defaultConfig { defaultConfig {
applicationId "ru.megboyzz.dnevnik" applicationId "ru.megboyzz.dnevnik"
@@ -17,6 +17,7 @@ android {
vectorDrawables { vectorDrawables {
useSupportLibrary true useSupportLibrary true
} }
multiDexEnabled true
} }
buildTypes { buildTypes {
@@ -32,6 +33,7 @@ android {
} }
kotlinOptions { kotlinOptions {
jvmTarget = '1.8' jvmTarget = '1.8'
freeCompilerArgs = ['-Xjvm-default=compatibility']
} }
buildFeatures { buildFeatures {
compose true compose true
@@ -75,4 +77,10 @@ dependencies {
//Библиотечка для рисования круговых диаграмок //Библиотечка для рисования круговых диаграмок
implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' 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.* import ru.megboyzz.dnevnik.ui.theme.*
class MainActivity : ComponentActivity() { class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) 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.LocalDate
import java.time.Year import java.time.Year
import java.time.temporal.TemporalAdjusters import java.time.temporal.TemporalAdjusters
import java.util.*
@Composable @Composable
fun Int.AsPainter() = painterResource(this) fun Int.AsPainter() = painterResource(this)
@@ -136,3 +137,5 @@ fun Modifier.mainClickable(
), ),
onClick = onClick onClick = onClick
) )
@@ -7,6 +7,7 @@ import androidx.navigation.NavController
import ru.megboyzz.dnevnik.navigation.AppNavRoute import ru.megboyzz.dnevnik.navigation.AppNavRoute
import ru.megboyzz.dnevnik.screens.ui.LoginScreenContent import ru.megboyzz.dnevnik.screens.ui.LoginScreenContent
//TODO Переверстать экран входа
@Composable @Composable
fun LoginScreen(navController: NavController) { 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 package ru.megboyzz.dnevnik.screens.ui
import android.annotation.SuppressLint
import androidx.compose.animation.* import androidx.compose.animation.*
import androidx.compose.animation.core.tween import androidx.compose.animation.core.tween
import androidx.compose.foundation.* import androidx.compose.foundation.*
import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.* 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.selection.toggleable
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardOptions 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.focusRequester import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.focus.onFocusChanged 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.*
import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.layout.ContentScale 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.input.VisualTransformation
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.* import androidx.compose.ui.unit.*
import androidx.compose.ui.viewinterop.AndroidView import androidx.compose.ui.viewinterop.AndroidView
import androidx.navigation.NavController import androidx.navigation.NavController
import com.google.accompanist.navigation.animation.rememberAnimatedNavController
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import ru.megboyzz.dnevnik.* import ru.megboyzz.dnevnik.*
import ru.megboyzz.dnevnik.R import ru.megboyzz.dnevnik.R
@@ -177,7 +174,10 @@ fun BottomNavButton(
onClick: () -> Unit, 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( Column(
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center verticalArrangement = Arrangement.Center
@@ -655,8 +655,8 @@ fun AverageText(
@Composable @Composable
fun CardWithAverage( fun CardWithAverage(
averageMark: Float, averageMark: Float?,
resultMark: Float, resultMark: Float?,
minWidth: Dp = 300.dp, minWidth: Dp = 300.dp,
content: @Composable () -> Unit content: @Composable () -> Unit
) { ) {
@@ -673,7 +673,10 @@ fun CardWithAverage(
modifier = Modifier.size(50.dp), modifier = Modifier.size(50.dp),
contentAlignment = Alignment.Center 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( Box(
@@ -686,7 +689,7 @@ fun CardWithAverage(
){ ){
AverageText( AverageText(
title = R.string.title_result_mark.AsString(), 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, teacher: String,
reason: String = "null" reason: String = "null"
) { ) {
Card( BaseCard {
backgroundColor = white,
shape = RoundedCornerShape(10.dp),
border = BorderStroke(
width = 1.dp,
color = mainBlue
),
modifier = Modifier.fillMaxWidth()
) {
Row( Row(
horizontalArrangement = Arrangement.SpaceBetween, horizontalArrangement = Arrangement.SpaceBetween,
modifier = Modifier.padding(15.dp) modifier = Modifier.padding(15.dp)
@@ -766,6 +761,84 @@ enum class Month{
December, 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 @Composable
fun CardCalendar( fun CardCalendar(
month: Month, month: Month,
@@ -785,11 +858,10 @@ fun CardCalendar(
val expanded = remember { val expanded = remember {
mutableStateOf(true) mutableStateOf(true)
} }
val expandedModifier = if(expanded.value) Modifier else Modifier.height(100.dp)
Card( Card(
backgroundColor = white, backgroundColor = white,
modifier = Modifier.fillMaxWidth(), modifier = Modifier.defaultMinSize(minWidth = 200.dp),
shape = RoundedCornerShape(10.dp), shape = RoundedCornerShape(10.dp),
elevation = 5.dp elevation = 5.dp
){ ){
@@ -824,6 +896,8 @@ fun CardCalendar(
val offset = 8 - getMonthDaysBy(year, month, DayOfWeek.MONDAY)[0] val offset = 8 - getMonthDaysBy(year, month, DayOfWeek.MONDAY)[0]
val clicked = mutableListOf<MutableState<Boolean>>() val clicked = mutableListOf<MutableState<Boolean>>()
var lastClicked = 0
var lastInd = 0
Row( Row(
horizontalArrangement = Arrangement.SpaceBetween, horizontalArrangement = Arrangement.SpaceBetween,
@@ -831,6 +905,7 @@ fun CardCalendar(
.fillMaxWidth() .fillMaxWidth()
.padding(0.dp, 10.dp, 0.dp, 5.dp) .padding(0.dp, 10.dp, 0.dp, 5.dp)
) { ) {
if(expanded.value)
for(day in DayOfWeek.values()){ for(day in DayOfWeek.values()){
if(day != DayOfWeek.SUNDAY) Column { if(day != DayOfWeek.SUNDAY) Column {
val list = getMonthDaysBy(year, month, day) val list = getMonthDaysBy(year, month, day)
@@ -848,6 +923,8 @@ fun CardCalendar(
number = data.toString() number = data.toString()
) { ) {
expanded.value != expanded.value expanded.value != expanded.value
lastClicked = data
lastInd = i
for(click in clicked) for(click in clicked)
if(click != isClicked) if(click != isClicked)
click.value = false click.value = false
@@ -860,9 +937,10 @@ fun CardCalendar(
} }
} }
} }
else{
}
} }
} }
} }
} }
@@ -955,7 +1033,7 @@ fun MonthToggle(
val isNormal = screenWidth < 500 val isNormal = screenWidth < 500
if(!isNormal) defaultPadding *= 4 if(!isNormal) defaultPadding *= 4
Column(Modifier.padding(defaultPadding, 0.dp)) { Column() {
Row( Row(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
@@ -1036,53 +1114,133 @@ fun UnderlinedText(
} }
} }
/** @Composable
* Класс для предоставления данных для круговых диаграм fun AllMarksCard(
* Идея предоставить диаграмме массив именованных данных subjectName: String,
* напрмер кол-во оцеок отлично по всем предметам: teacher: String?,
* CircleDiagramData(parameterName = "История", count=5) = 38% marks: List<Int>?,
* CircleDiagramData(parameterName = "Русский язык", count=4) = 31% resultMark: Float?
* CircleDiagramData(parameterName = "Химия", count=1) = 8% ) {
* CircleDiagramData(parameterName = "Математика", count=3) = 23% CardWithAverage(
*/ averageMark = marks?.average()?.toFloat(),
@OptIn(ExperimentalGraphicsApi::class) resultMark = resultMark
data class PieChartData( ) {
val legend: String, Box(Modifier.padding(15.dp, 15.dp)) {
val value: Int Column {
){ Row(
val color: Color horizontalArrangement = Arrangement.spacedBy(10.dp),
init { verticalAlignment = Alignment.CenterVertically
val hue = (0..360).random(kotlin.random.Random(System.nanoTime())).toFloat() ) {
Thread.sleep(10) Image(
color = Color.hsl(hue, 0.5f, 0.6f) 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 @Composable
fun PieChart( fun MarkInBox(mark: Int) {
diagramData: List<PieChartData> 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(
Column { modifier = Modifier
AndroidView( .defaultMinSize(200.dp)
factory = { context -> .padding(25.dp),
chart = DataPieChart(context) horizontalAlignment = Alignment.CenterHorizontally
chart ) {
}, Image(
modifier = Modifier painter = if(isFine) R.drawable.ic_smile.AsPainter() else R.drawable.ic_sad_smile.AsPainter(),
.wrapContentSize() contentDescription = ""
.padding(5.dp), )
update = { chart.updatePieChartWithData(diagramData) } SpacerHeight(height = 10.dp)
Text(
text = message,
style = MainText,
color = dark
) )
} }
} }
@Composable @Composable
fun PieChartCard( fun EmptyMessage(message: String) = ContentMessage(message = message, isFine = false)
title: String,
data: List<PieChartData> @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, LayoutParams.MATCH_PARENT,
) )
setUsePercentValues(true) setUsePercentValues(true)
setEntryLabelTextSize(10f)
description.isEnabled = false description.isEnabled = false
isDrawHoleEnabled = false isDrawHoleEnabled = false
legend.isEnabled = false legend.isEnabled = false
legend.orientation = Legend.LegendOrientation.VERTICAL legend.orientation = Legend.LegendOrientation.VERTICAL
legend.horizontalAlignment = 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
)
}
}