patrykandpatrick / vico

A light and extensible chart library for Android.
https://patrykandpatrick.com/vico/wiki
Apache License 2.0
2.07k stars 125 forks source link

At the end the label of bottom axis is cut off #731

Closed penghaitao closed 3 months ago

penghaitao commented 3 months ago

How to reproduce

20240526235034 I use X axis to show the hours of the day. zoomEnabled = false zoomState = rememberVicoZoomState(zoomEnabled = false, initialZoom = remember { Zoom.min(Zoom.static(), Zoom.Content) },),

Observed behavior

You can see the last label is not shown. Because I only show five labels, if the last one is hidden, it will be very easy to notice.

Expected behavior

I have already set addExtremeLabelPadding = true, but it only let the first label be shown. I have seen a few other Apps' chart, and many of them also don't show the last label, I don't know which library they are using, but maybe it's not easy to fix this? Or maybe you could give me some other advice to work around this issue? Thanks.

Vico version(s)

2.0.0-alpha.20

Android version(s)

33

Additional information

No response

Gowsky commented 3 months ago

Do you want to add a label for 23:00? What AxisItemPlacer.Horizontal implementation are you using?

penghaitao commented 3 months ago

Do you want to add a label for 23:00? What AxisItemPlacer.Horizontal implementation are you using?

Thanks for your reply. Yes, I want to add a label for 23:00 which is the last label. I am using itemPlacer =remember { AxisItemPlacer.Horizontal.default(spacing = 6, addExtremeLabelPadding = true) } I have tried to change the spacing from 1 to 10, and also tried to shorten the label text to one character, but the last label still can't be shown.

patrickmichalik commented 3 months ago

Hello, @penghaitao! Isn’t spacing set to 6? Without API overrides, it shouldn’t be possible to obtain the result in the screenshot with spacing set to 4. If it is, in fact, 4, could you please share your code?

penghaitao commented 3 months ago

Hello, @penghaitao! Isn’t spacing set to 6? Without API overrides, it shouldn’t be possible to obtain the result in the screenshot with spacing set to 4. If it is, in fact, 4, could you please share your code?

Thanks for your reply. Yes, you are right. the screenshot was captured when the spacing = 6. I made a mistake. I have already editted the comment. So is there any advice to show the last label? Thanks.

patrickmichalik commented 3 months ago

Got it. If so, this behavior is expected—23 isn’t a multiple of 6 (unlike 0, 6, 12, and 18). To have 23:00 labeled, you can create a suitable AxisItemPlacer.Horizontal implementation. Here’s a basic example, which assumes an x range of 0 through 23:

object : AxisItemPlacer.Horizontal by AxisItemPlacer.Horizontal.default() {
    val labelValues = listOf(0f, 6f, 12f, 18f, 23f)

    override fun getFirstLabelValue(context: CartesianMeasureContext, maxLabelWidth: Float) = labelValues.first()

    override fun getLastLabelValue(context: CartesianMeasureContext, maxLabelWidth: Float) = labelValues.last()

    override fun getLabelValues(
        context: CartesianDrawContext,
        visibleXRange: ClosedFloatingPointRange<Float>,
        fullXRange: ClosedFloatingPointRange<Float>,
        maxLabelWidth: Float,
    ) = labelValues

    override fun getWidthMeasurementLabelValues(
        context: CartesianMeasureContext,
        horizontalDimensions: HorizontalDimensions,
        fullXRange: ClosedFloatingPointRange<Float>,
    ) = labelValues

    override fun getHeightMeasurementLabelValues(
        context: CartesianMeasureContext,
        horizontalDimensions: HorizontalDimensions,
        fullXRange: ClosedFloatingPointRange<Float>,
        maxLabelWidth: Float,
    ) = labelValues
}

We plan on adding a built-in AxisItemPlacer.Horizontal implementation with support for nonuniform spacing.

As a side note, since you mentioned that you tried 1 through 10 for spacing, I wanted to add that with spacing set to 1, if there were enough room, the label in question would show up. 23 is, of course, a multiple of 1. When HorizontalLayout.FullWidth is applied, and addExtremeLabelPadding is set to true, the AxisItemPlacer.Horizontal implementation returned by AxisItemPlacer.Horizontal.default uses the lowest multiple of spacing for which there are no overlaps. Note that rememberAxisLabelComponent applies some padding by default—this influences the label width.

Since the behavior in question isn’t a bug, I’ll be closing this issue. Let me know if you have any questions.