Skip to content

Commit 9232c5c

Browse files
committed
resolve issue with horizontal axis labels
1 parent 3ce0d36 commit 9232c5c

File tree

4 files changed

+35
-45
lines changed

4 files changed

+35
-45
lines changed

app/src/main/java/com/waldo121/pongstats/MainActivity.kt

Lines changed: 9 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,13 @@ import androidx.compose.foundation.text.KeyboardOptions
2626
import androidx.compose.foundation.verticalScroll
2727
import androidx.compose.material.icons.Icons
2828
import androidx.compose.material.icons.filled.Add
29-
import androidx.compose.material.icons.filled.ArrowDropDown
3029
import androidx.compose.material.icons.filled.Home
3130
import androidx.compose.material.icons.filled.Person
3231
import androidx.compose.material3.Button
3332
import androidx.compose.material3.ButtonDefaults
3433
import androidx.compose.material3.CenterAlignedTopAppBar
3534
import androidx.compose.material3.DropdownMenuItem
3635
import androidx.compose.material3.ExperimentalMaterial3Api
37-
import androidx.compose.material3.ExposedDropdownMenuBox
38-
import androidx.compose.material3.ExposedDropdownMenuDefaults
39-
import androidx.compose.material3.HorizontalDivider
4036
import androidx.compose.material3.Icon
4137
import androidx.compose.material3.MaterialTheme
4238
import androidx.compose.material3.NavigationBar
@@ -49,7 +45,6 @@ import androidx.compose.material3.SnackbarDuration
4945
import androidx.compose.material3.SnackbarHost
5046
import androidx.compose.material3.SnackbarHostState
5147
import androidx.compose.material3.Text
52-
import androidx.compose.material3.TextField
5348
import androidx.compose.material3.TopAppBarDefaults
5449
import androidx.compose.runtime.Composable
5550
import androidx.compose.runtime.LaunchedEffect
@@ -71,9 +66,7 @@ import androidx.compose.ui.unit.dp
7166
import androidx.lifecycle.compose.collectAsStateWithLifecycle
7267
import androidx.lifecycle.viewmodel.MutableCreationExtras
7368
import androidx.lifecycle.viewmodel.compose.viewModel
74-
import androidx.lifecycle.lifecycleScope
7569
import com.patrykandpatrick.vico.compose.cartesian.CartesianChartHost
76-
import com.patrykandpatrick.vico.compose.cartesian.axis.rememberAxisTickComponent
7770
import com.patrykandpatrick.vico.compose.cartesian.axis.rememberBottom
7871
import com.patrykandpatrick.vico.compose.cartesian.axis.rememberStart
7972
import com.patrykandpatrick.vico.compose.cartesian.layer.rememberLineCartesianLayer
@@ -90,18 +83,14 @@ import com.waldo121.pongstats.domain.DailyWinRateUseCase
9083
import com.waldo121.pongstats.ui.theme.PingPongBlack
9184
import com.waldo121.pongstats.ui.theme.PingPongDarkGrey
9285
import com.waldo121.pongstats.ui.theme.PingPongDarkRed
93-
import com.waldo121.pongstats.ui.theme.PingPongLightWood
9486
import com.waldo121.pongstats.ui.theme.PingPongRed
9587
import com.waldo121.pongstats.ui.theme.PingPongWood
9688
import com.waldo121.pongstats.ui.theme.PongStatsTheme
9789
import com.waldo121.pongstats.viewModel.MatchRecordViewModel
9890
import com.waldo121.pongstats.viewModel.StatisticsViewModel
9991
import kotlinx.coroutines.Dispatchers
10092
import kotlinx.coroutines.launch
101-
import kotlinx.coroutines.withContext
102-
import java.time.LocalDate
10393
import java.time.ZoneId
104-
import java.time.format.DateTimeFormatter
10594
import kotlin.math.round
10695
import com.patrykandpatrick.vico.core.cartesian.layer.LineCartesianLayer
10796
import java.time.Instant
@@ -124,12 +113,14 @@ import androidx.compose.foundation.clickable
124113
import androidx.compose.foundation.layout.fillMaxSize
125114
import androidx.compose.foundation.text.KeyboardActions
126115
import androidx.compose.material3.DropdownMenu
127-
import androidx.compose.material3.DropdownMenuItem
128116
import androidx.compose.ui.unit.DpOffset
129117
import androidx.compose.foundation.lazy.LazyColumn
130118
import androidx.compose.foundation.lazy.items
131119
import androidx.compose.foundation.layout.heightIn
132-
import android.widget.Toast
120+
import com.patrykandpatrick.vico.compose.cartesian.VicoScrollState
121+
import com.patrykandpatrick.vico.compose.cartesian.rememberVicoScrollState
122+
import com.patrykandpatrick.vico.core.cartesian.Scroll
123+
import com.waldo121.pongstats.ui.components.xLabelFormatter
133124

134125

135126
class MainActivity : ComponentActivity() {
@@ -345,10 +336,6 @@ fun HomeScreen(
345336
// Collect all unique x-values in order
346337
val allXValues = (singleSeriesX + doubleSeriesX).distinct().sorted()
347338

348-
// Dynamically calculate labelEvery so that at most maxLabels are shown
349-
val maxLabels = 7
350-
val labelEvery = if (allXValues.size <= maxLabels) 1 else (allXValues.size + maxLabels - 1) / maxLabels
351-
352339
// Determine which series are present and in what order
353340
val presentSeries = mutableListOf<String>()
354341
if (singleSeriesY.isNotEmpty()) presentSeries.add("singles")
@@ -441,12 +428,11 @@ fun HomeScreen(
441428
if (singleData.isNotEmpty() || doubleData.isNotEmpty()) {
442429
WinRateChart(
443430
modelProducer = combinedModelProducer,
444-
modifier = Modifier.padding(vertical = 8.dp),
431+
modifier = Modifier.padding(vertical = 8.dp).fillMaxWidth(),
445432
title = stringResource(R.string.daily_win_rate),
446433
showLegend = true,
447434
presentSeries = presentSeries,
448435
allXValues = allXValues,
449-
labelEvery = labelEvery
450436
)
451437
} else {
452438
EmptyChartPlaceholder(
@@ -488,11 +474,10 @@ private fun WinRateChart(
488474
showLegend: Boolean = false,
489475
presentSeries: List<String>,
490476
allXValues: List<Float>,
491-
labelEvery: Int = 5
492477
) {
493478
val singlesColor = PingPongRed
494479
val doublesColor = PingPongDarkRed
495-
480+
val scrollState = rememberVicoScrollState(scrollEnabled = false)
496481
val lines = presentSeries.map { series ->
497482
when (series) {
498483
"singles" -> LineCartesianLayer.Line(
@@ -535,19 +520,11 @@ private fun WinRateChart(
535520
}
536521
),
537522
bottomAxis = HorizontalAxis.rememberBottom(
538-
itemPlacer = HorizontalAxis.ItemPlacer.aligned(),
539-
valueFormatter = { _, value, _ ->
540-
val index = allXValues.indexOf(value.toFloat())
541-
if (index >= 0 && index % labelEvery == 0) {
542-
val date = LocalDate.ofEpochDay(value.toLong())
543-
date.format(DateTimeFormatter.ofPattern("MMM, YYYY"))
544-
} else {
545-
""
546-
}
547-
},
548-
labelRotationDegrees = 30f
523+
valueFormatter = xLabelFormatter(allXValues),
524+
labelRotationDegrees = 40f,
549525
),
550526
),
527+
scrollState = scrollState,
551528
modelProducer = modelProducer,
552529
modifier = Modifier
553530
.fillMaxWidth()
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.waldo121.pongstats.ui.components
2+
3+
import com.patrykandpatrick.vico.core.cartesian.data.CartesianValueFormatter
4+
import java.time.LocalDate
5+
import java.time.format.DateTimeFormatter
6+
7+
fun xLabelFormatter(
8+
allXValues: List<Float>,
9+
): CartesianValueFormatter {
10+
// Format the tick as a date only if it exactly matches a data point
11+
return CartesianValueFormatter { _,value ,_ ->
12+
val nearest = allXValues.minByOrNull { kotlin.math.abs(it - value) }
13+
if (nearest != null) {
14+
val date = LocalDate.ofEpochDay(nearest.toLong())
15+
val result = date.format(DateTimeFormatter.ofPattern("MM-yyyy"))
16+
result
17+
} else ""
18+
}
19+
}

app/src/main/java/com/waldo121/pongstats/ui/screens/PlayerProfileScreen.kt

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,13 @@ import com.patrykandpatrick.vico.compose.cartesian.axis.rememberBottom
3737
import com.patrykandpatrick.vico.compose.cartesian.axis.rememberStart
3838
import com.patrykandpatrick.vico.compose.cartesian.layer.rememberLineCartesianLayer
3939
import com.patrykandpatrick.vico.compose.cartesian.rememberCartesianChart
40+
import com.patrykandpatrick.vico.compose.cartesian.rememberVicoScrollState
4041
import com.patrykandpatrick.vico.core.cartesian.axis.HorizontalAxis
4142
import com.patrykandpatrick.vico.core.cartesian.axis.VerticalAxis
4243
import com.patrykandpatrick.vico.core.cartesian.data.CartesianChartModelProducer
4344
import com.patrykandpatrick.vico.core.cartesian.data.lineSeries
4445
import com.waldo121.pongstats.R
46+
import com.waldo121.pongstats.ui.components.xLabelFormatter
4547
import com.waldo121.pongstats.ui.theme.PingPongDarkRed
4648
import com.waldo121.pongstats.ui.theme.PingPongRed
4749
import kotlinx.coroutines.Dispatchers
@@ -66,8 +68,7 @@ fun PlayerProfileScreen(
6668
val seriesX = chartData.map { Instant.ofEpochMilli(it.date.time).atZone(ZoneId.systemDefault()).toLocalDate().toEpochDay().toFloat() }
6769
val seriesY = chartData.map { it.winRate.toFloat() }
6870
val allXValues = seriesX.distinct().sorted()
69-
val maxLabels = 7
70-
val labelEvery = if (allXValues.size <= maxLabels) 1 else (allXValues.size + maxLabels - 1) / maxLabels
71+
val scrollState = rememberVicoScrollState(scrollEnabled = false)
7172

7273
LaunchedEffect(key) {
7374
coroutineScope.launch(Dispatchers.Default) {
@@ -168,19 +169,11 @@ fun PlayerProfileScreen(
168169
}
169170
),
170171
bottomAxis = HorizontalAxis.rememberBottom(
171-
itemPlacer = HorizontalAxis.ItemPlacer.aligned(),
172-
valueFormatter = { _, value, _ ->
173-
val index = allXValues.indexOf(value.toFloat())
174-
if (index >= 0 && index % labelEvery == 0) {
175-
val date = LocalDate.ofEpochDay(value.toLong())
176-
date.format(DateTimeFormatter.ofPattern("MMM, yyyy"))
177-
} else {
178-
""
179-
}
180-
},
181-
labelRotationDegrees = 30f
172+
valueFormatter = xLabelFormatter(allXValues),
173+
labelRotationDegrees = 40f
182174
),
183175
),
176+
scrollState = scrollState,
184177
modelProducer = modelProducer,
185178
modifier = Modifier
186179
.fillMaxWidth()

app/src/main/res/values/strings.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,5 @@
3535
<string name="player_stats">Statistiques contre ce joueur</string>
3636
<string name="back_to_player_list">Retour à la liste</string>
3737
<string name="no_matches_against_player">Aucun match contre ce joueur</string>
38+
<string name="date_axis">Date</string>
3839
</resources>

0 commit comments

Comments
 (0)