diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..7643783 --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,123 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..79ee123 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index e546720..82f4a17 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,6 +1,6 @@ - + diff --git a/app/build.gradle b/app/build.gradle index 3fa7036..d514e8a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -72,4 +72,7 @@ dependencies { implementation 'com.squareup.retrofit2:retrofit:2.6.4' implementation 'com.squareup.retrofit2:converter-gson:2.3.0' coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5' + + //Библиотечка для рисования круговых диаграмок + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e741be1..cbc87c6 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -3,6 +3,8 @@ xmlns:tools="http://schemas.android.com/tools" package="ru.megboyzz.dnevnik"> + + { } return list } + +@Composable +fun Modifier.mainClickable( + radius: Dp, + onClick: () -> Unit +) = this.clickable( + interactionSource = remember { MutableInteractionSource() }, + indication = rememberRipple( + radius = radius, + color = dark + ), + onClick = onClick +) diff --git a/app/src/main/java/ru/megboyzz/dnevnik/navigation/MarksSubScreenNavHost.kt b/app/src/main/java/ru/megboyzz/dnevnik/navigation/MarksSubScreenNavHost.kt index 3e308f1..11bd886 100644 --- a/app/src/main/java/ru/megboyzz/dnevnik/navigation/MarksSubScreenNavHost.kt +++ b/app/src/main/java/ru/megboyzz/dnevnik/navigation/MarksSubScreenNavHost.kt @@ -3,7 +3,6 @@ package ru.megboyzz.dnevnik.navigation import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.foundation.layout.Column import androidx.compose.material.Text -import androidx.compose.material.rememberScaffoldState import androidx.compose.runtime.Composable import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -13,6 +12,8 @@ import com.google.accompanist.navigation.animation.rememberAnimatedNavController import ru.megboyzz.dnevnik.AsString import ru.megboyzz.dnevnik.R import ru.megboyzz.dnevnik.screens.* +import ru.megboyzz.dnevnik.screens.ui.SubScreenData +import ru.megboyzz.dnevnik.screens.ui.SubScreenNavBar sealed class MarksNavRoute(override val route: String): BaseNavRote(route){ diff --git a/app/src/main/java/ru/megboyzz/dnevnik/screens/HomeWorkScreen.kt b/app/src/main/java/ru/megboyzz/dnevnik/screens/HomeWorkScreen.kt index fa4c7ec..5188f60 100644 --- a/app/src/main/java/ru/megboyzz/dnevnik/screens/HomeWorkScreen.kt +++ b/app/src/main/java/ru/megboyzz/dnevnik/screens/HomeWorkScreen.kt @@ -6,6 +6,7 @@ import androidx.navigation.NavController import ru.megboyzz.dnevnik.AsPainter import ru.megboyzz.dnevnik.AsString import ru.megboyzz.dnevnik.R +import ru.megboyzz.dnevnik.screens.ui.MainScaffold @Composable fun HomeWorkScreen( diff --git a/app/src/main/java/ru/megboyzz/dnevnik/screens/LoginScreen.kt b/app/src/main/java/ru/megboyzz/dnevnik/screens/LoginScreen.kt index a1f3888..57dc51d 100644 --- a/app/src/main/java/ru/megboyzz/dnevnik/screens/LoginScreen.kt +++ b/app/src/main/java/ru/megboyzz/dnevnik/screens/LoginScreen.kt @@ -1,25 +1,11 @@ package ru.megboyzz.dnevnik.screens -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.* -import androidx.compose.material.* import androidx.compose.runtime.Composable import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalConfiguration -import androidx.compose.ui.text.input.KeyboardType -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp import androidx.navigation.NavController -import ru.megboyzz.dnevnik.AsString -import ru.megboyzz.dnevnik.R -import ru.megboyzz.dnevnik.SpacerHeight -import ru.megboyzz.dnevnik.SpacerWidth import ru.megboyzz.dnevnik.navigation.AppNavRoute -import ru.megboyzz.dnevnik.ui.theme.* +import ru.megboyzz.dnevnik.screens.ui.LoginScreenContent @Composable fun LoginScreen(navController: NavController) { diff --git a/app/src/main/java/ru/megboyzz/dnevnik/screens/MarksScreen.kt b/app/src/main/java/ru/megboyzz/dnevnik/screens/MarksScreen.kt index f2cd6a6..d29adb7 100644 --- a/app/src/main/java/ru/megboyzz/dnevnik/screens/MarksScreen.kt +++ b/app/src/main/java/ru/megboyzz/dnevnik/screens/MarksScreen.kt @@ -7,6 +7,7 @@ import ru.megboyzz.dnevnik.AsPainter import ru.megboyzz.dnevnik.AsString import ru.megboyzz.dnevnik.R import ru.megboyzz.dnevnik.navigation.MarksSubScreenNavHost +import ru.megboyzz.dnevnik.screens.ui.MainScaffold @Composable fun MarksScreen( diff --git a/app/src/main/java/ru/megboyzz/dnevnik/screens/ScheduleScreen.kt b/app/src/main/java/ru/megboyzz/dnevnik/screens/ScheduleScreen.kt index 888a6a5..1c63fd7 100644 --- a/app/src/main/java/ru/megboyzz/dnevnik/screens/ScheduleScreen.kt +++ b/app/src/main/java/ru/megboyzz/dnevnik/screens/ScheduleScreen.kt @@ -6,7 +6,7 @@ import androidx.navigation.NavController import ru.megboyzz.dnevnik.AsPainter import ru.megboyzz.dnevnik.AsString import ru.megboyzz.dnevnik.R -import ru.megboyzz.dnevnik.navigation.AppNavRoute +import ru.megboyzz.dnevnik.screens.ui.MainScaffold @Composable fun ScheduleScreen( diff --git a/app/src/main/java/ru/megboyzz/dnevnik/screens/Components.kt b/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/Components.kt similarity index 86% rename from app/src/main/java/ru/megboyzz/dnevnik/screens/Components.kt rename to app/src/main/java/ru/megboyzz/dnevnik/screens/ui/Components.kt index a69852f..bb21305 100644 --- a/app/src/main/java/ru/megboyzz/dnevnik/screens/Components.kt +++ b/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/Components.kt @@ -1,12 +1,14 @@ -package ru.megboyzz.dnevnik.screens +package ru.megboyzz.dnevnik.screens.ui import android.annotation.SuppressLint -import android.graphics.ColorSpace.Rgb.TransferParameters -import android.graphics.Point -import android.graphics.RectF +import android.graphics.Typeface +import android.util.Log +import android.view.ViewGroup +import android.widget.LinearLayout 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.selection.toggleable import androidx.compose.foundation.shape.RoundedCornerShape @@ -17,6 +19,7 @@ import androidx.compose.material.icons.filled.Check import androidx.compose.material.icons.filled.Menu import androidx.compose.material.icons.filled.Visibility import androidx.compose.material.icons.filled.VisibilityOff +import androidx.compose.material.ripple.rememberRipple import androidx.compose.runtime.* import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Alignment @@ -29,8 +32,6 @@ 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.drawscope.DrawStyle -import androidx.compose.ui.graphics.drawscope.Stroke import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalConfiguration @@ -42,7 +43,14 @@ import androidx.compose.ui.text.input.VisualTransformation import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.* +import androidx.compose.ui.viewinterop.AndroidView import androidx.navigation.NavController +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.data.PieData +import com.github.mikephil.charting.data.PieDataSet +import com.github.mikephil.charting.data.PieEntry +import com.github.mikephil.charting.formatter.PercentFormatter import kotlinx.coroutines.launch import ru.megboyzz.dnevnik.* import ru.megboyzz.dnevnik.R @@ -450,11 +458,24 @@ fun DrawerMainButton( textColor: Color = white, onClick: () -> Unit = {} ) { + val interactionSource = MutableInteractionSource() + + val coroutineScope = rememberCoroutineScope() + + val scale = remember { + androidx.compose.animation.core.Animatable(1f) + } + + val animationDuration = 100 + val scaleDown = 0.9f + Column( modifier = Modifier .fillMaxWidth() .height(30.dp) - .clickable(onClick = onClick), + //TODO Сделать нормальную анимаую клика(не квадратную) + .mainClickable(10.dp, onClick::invoke), + //.clickable(onClick = onClick), verticalArrangement = Arrangement.Center ) { Row( @@ -806,6 +827,19 @@ enum class Month{ } +@Preview +@Composable +fun CardCalendarPrev() { + Column() { + CardCalendar(month = Month.March, year = 2023){ + + } + Button(onClick = { /*TODO*/ }) { + Text("hello") + } + } +} + @Composable fun CardCalendar( month: Month, @@ -863,6 +897,8 @@ fun CardCalendar( val offset = 8 - getMonthDaysBy(year, month, DayOfWeek.MONDAY)[0] + val clicked = mutableListOf>() + Row( horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier @@ -870,8 +906,7 @@ fun CardCalendar( .padding(0.dp, 10.dp, 0.dp, 5.dp) ) { for(day in DayOfWeek.values()){ - if(day != DayOfWeek.SUNDAY) - Column { + if(day != DayOfWeek.SUNDAY) Column { val list = getMonthDaysBy(year, month, day) var len = 0 if(day.ordinal + 1 <= offset && offset !in 6..7){ @@ -881,11 +916,15 @@ fun CardCalendar( for(i in list.indices){ val data = list[i] val isClicked = remember { mutableStateOf(false) } + clicked.add(isClicked) NumberOnCalendar( isClicked = isClicked, number = data.toString() ) { expanded.value != expanded.value + for(click in clicked) + if(click != isClicked) + click.value = false onClick.invoke(data) } len++ @@ -932,23 +971,28 @@ fun NumberOnCalendar( Box( modifier = Modifier .size(30.dp) + .clickable( + interactionSource = remember { MutableInteractionSource() }, + indication = rememberRipple(radius = 15.dp, color = dark), + onClick = { + if (number != "") { + isClicked.value = !isClicked.value + onClick.invoke() + } + } + ) .then(isClickedModifier), - contentAlignment = Alignment.Center + contentAlignment = Alignment.Center, ){ Text( text = number, style = H2, color = dark, - modifier = Modifier.clickable{ - if(number != "") { - isClicked.value = !isClicked.value - onClick.invoke() - } - } ) } } + @Composable fun MonthToggle( startMonth: Month, @@ -1094,47 +1138,133 @@ fun UnderlinedTextPrev() { * CircleDiagramData(parameterName = "Химия", count=1) = 8% * CircleDiagramData(parameterName = "Математика", count=3) = 23% */ -data class CircleDiagramData( - val parameterName: String, - val count: Int -) - -@Composable -fun CircleDiagram( - diagramData: List -) { - - val sum = diagramData.sumOf { it.count } - - Canvas(modifier = Modifier.size(100.dp)) { - val canvasWidth = size.width - val canvasHeight = size.height - drawCircle(color = white) - var angle = -45f - var isBlue = true - for(data in diagramData){ - val cur = -(360 * data.count.toFloat() / sum.toFloat()) - drawArc( - color = if(isBlue) Color.Blue else Color.Red, - startAngle = -angle, - sweepAngle = cur, - useCenter = true, - //style = Stroke(width = 1f, cap = StrokeCap.Round). - ) - isBlue = !isBlue - angle -= cur - } +@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) } } + @Preview @Composable fun CirclePrev() { val list = listOf( - CircleDiagramData(parameterName = "История", count=5), - CircleDiagramData(parameterName = "Русский язык", count=4), - CircleDiagramData(parameterName = "Химия", count=1), - CircleDiagramData(parameterName = "Математика", count=3) + PieChartData(legend = "История", value=5), + PieChartData(legend = "Русский язык", value=4), + PieChartData(legend = "Химия", value=1), + PieChartData(legend = "Математика", value=3) ) - CircleDiagram(list) + PieChart(list) } + +@Composable +fun PieChart( + diagramData: List +) { + + // Sum of all the values + val sumOfValues = diagramData.sumOf { it.value } + + // Calculate each proportion value + val proportions = diagramData.map { + it.value.toFloat() / sumOfValues + } + + // Convert each proportions to angle + val sweepAngles = proportions.map { + 360 * it + } + Row(verticalAlignment = Alignment.CenterVertically) { + Canvas( + modifier = Modifier.size(200.dp) + ) { + + var startAngle = -90f + + for (i in sweepAngles.indices) { + drawArc( + color = diagramData[i].color, + startAngle = startAngle, + sweepAngle = sweepAngles[i], + useCenter = true + ) + startAngle += sweepAngles[i] + //draw + } + + } + + Spacer(modifier = Modifier.width(32.dp)) + Column() { + for (data in diagramData) { + DisplayLegend(color = data.color, legend = data.legend) + } + } + } + +} + +@Composable +fun DisplayLegend(color: Color, legend: String) { + + Row( + horizontalArrangement = Arrangement.Center, + verticalAlignment = Alignment.CenterVertically + ) { + Divider( + modifier = Modifier.width(16.dp), + thickness = 4.dp, + color = color + ) + + Spacer(modifier = Modifier.width(4.dp)) + + Text( + text = legend, + color = Color.Black + ) + } +} + + +@Preview +@Composable +fun GoodPieChartPrev() { + Log.i("HUE", "HUE START") + val list = listOf( + PieChartData(legend = "История", value=5), + PieChartData(legend = "Русский язык", value=4), + PieChartData(legend = "Химия", value=1), + PieChartData(legend = "Математика", value=3), + //PieChartData(legend = "Физика", value=10) + ) + Log.i("HUE", "HUE END") + GoodPieChart(diagramData = list) +} + +@Composable +fun GoodPieChart( + diagramData: List +) { + lateinit var chart: DataPieChart + Column { + AndroidView(factory = { context -> + chart = DataPieChart(context) + chart + }, + modifier = Modifier + .wrapContentSize() + .padding(5.dp), + update = { chart.updatePieChartWithData(diagramData) } + ) + + + } +} \ No newline at end of file diff --git a/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/DataPieChart.kt b/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/DataPieChart.kt new file mode 100644 index 0000000..29ff8ba --- /dev/null +++ b/app/src/main/java/ru/megboyzz/dnevnik/screens/ui/DataPieChart.kt @@ -0,0 +1,59 @@ +package ru.megboyzz.dnevnik.screens.ui + +import android.content.Context +import android.graphics.Typeface +import android.view.ViewGroup +import android.widget.LinearLayout +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.toArgb +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.data.PieData +import com.github.mikephil.charting.data.PieDataSet +import com.github.mikephil.charting.data.PieEntry +import com.github.mikephil.charting.formatter.PercentFormatter +import ru.megboyzz.dnevnik.ui.theme.MainText + +class DataPieChart(context: Context) : PieChart(context) { + + init { + layoutParams = LinearLayout.LayoutParams( + LayoutParams.MATCH_PARENT, + LayoutParams.MATCH_PARENT, + ) + setUsePercentValues(true) + description.isEnabled = false + isDrawHoleEnabled = false + + legend.isEnabled = false + legend.orientation = Legend.LegendOrientation.VERTICAL + legend.horizontalAlignment = + Legend.LegendHorizontalAlignment.CENTER + legend.textSize = 10f + + setEntryLabelColor(Color.Black.toArgb()) + } + + fun updatePieChartWithData(data: List) { + val entries = data.map { PieEntry(it.value.toFloat(), it.legend) } + + val ds = PieDataSet(entries, "") + + ds.colors = data.map { it.color.toArgb() } + + ds.yValuePosition = PieDataSet.ValuePosition.INSIDE_SLICE + ds.xValuePosition = PieDataSet.ValuePosition.INSIDE_SLICE + + ds.sliceSpace = 2f + + ds.valueTextColor = Color.Black.toArgb() + ds.valueFormatter = PercentFormatter(this) + ds.valueTextSize = 10f + ds.valueTypeface = Typeface.DEFAULT + + this.data = PieData(ds) + + invalidate() + } + +} \ No newline at end of file diff --git a/app/src/test/java/ru/megboyzz/dnevnik/UtilsTest.kt b/app/src/test/java/ru/megboyzz/dnevnik/UtilsTest.kt index e68ef0e..1e13ec9 100644 --- a/app/src/test/java/ru/megboyzz/dnevnik/UtilsTest.kt +++ b/app/src/test/java/ru/megboyzz/dnevnik/UtilsTest.kt @@ -3,7 +3,7 @@ package ru.megboyzz.dnevnik import org.junit.Test import org.junit.Assert.* -import ru.megboyzz.dnevnik.screens.Month +import ru.megboyzz.dnevnik.screens.ui.Month import java.time.DayOfWeek class UtilsTest { diff --git a/build.gradle b/build.gradle index 1f209fc..1f6d3b7 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,6 @@ plugins { id 'com.android.library' version '7.2.1' apply false id 'org.jetbrains.kotlin.android' version '1.6.10' apply false } - task clean(type: Delete) { delete rootProject.buildDir } \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index afcf840..f4b0b19 100644 --- a/settings.gradle +++ b/settings.gradle @@ -10,6 +10,7 @@ dependencyResolutionManagement { repositories { google() mavenCentral() + maven { url 'https://jitpack.io' } } } rootProject.name = "MyDnevnik"