Comments (6)
Hello! DefaultMarkerLabelFormatter
color-codes Marker
labels. You can set colorCode
to false
to turn this off.
To customize the number format such that there are no trailing zeros, please use a custom MarkerLabelFormatter
implementation. (We’ll be looking into updating DefaultMarkerLabelFormatter
to accept a pattern string and improving the default behavior.) You can also use MarkerLabelFormatter
to add extra text to your Marker
—any string can be returned. Regarding font customization, TextComponent
has a typeface
field. A Marker
can have any position—while a MarkerComponent
appears at the top of its chart, you can create a custom Marker
implementation with different positioning logic. (We’ll be looking into making MarkerComponent
configurable position-wise.) Finally, Marker
visibility changes can be detected via MarkerVisibilityChangeListener
, and the ability to highlight individual columns in column charts is a planned addition.
Since the behavior described isn’t a bug and can be changed, I’ll be closing this issue, but feel free to comment if you have any questions.
from vico.
Thanks for the response, will give those suggestions a shot
from vico.
@patrickmichalik If you could, Could you help point me in the right direction for the marker height in the marker class?
I made my own, which I now have color authority, font, and string formatting completed. Just a bit unsure how to override the hight so that it's on top of the columns like the labels are.
from vico.
Sure, @ozanKalan1. Could you share your Marker
code? I’ll then be able to give you precise instructions.
from vico.
Here you go @patrickmichalik
import android.text.Spannable
import android.text.style.ForegroundColorSpan
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import androidx.core.content.res.ResourcesCompat
import com.autonomy.autonomyconsumer.R
import com.autonomy.autonomyconsumer.data.extensions.formatToMileage
import com.autonomy.autonomyconsumer.ui.theme.AutonomyBlack
import com.autonomy.autonomyconsumer.ui.theme.White
import com.patrykandpatrick.vico.compose.dimensions.dimensionsOf
import com.patrykandpatrick.vico.core.chart.dimensions.HorizontalDimensions
import com.patrykandpatrick.vico.core.chart.insets.Insets
import com.patrykandpatrick.vico.core.chart.values.ChartValues
import com.patrykandpatrick.vico.core.component.marker.MarkerComponent
import com.patrykandpatrick.vico.core.component.shape.DashedShape
import com.patrykandpatrick.vico.core.component.shape.ShapeComponent
import com.patrykandpatrick.vico.core.component.shape.Shapes
import com.patrykandpatrick.vico.core.component.shape.cornered.Corner
import com.patrykandpatrick.vico.core.component.shape.cornered.MarkerCorneredShape
import com.patrykandpatrick.vico.core.component.text.TextComponent
import com.patrykandpatrick.vico.core.context.MeasureContext
import com.patrykandpatrick.vico.core.extension.appendCompat
import com.patrykandpatrick.vico.core.extension.sumOf
import com.patrykandpatrick.vico.core.extension.transformToSpannable
import com.patrykandpatrick.vico.core.marker.Marker
import com.patrykandpatrick.vico.core.marker.MarkerLabelFormatter
import com.patrykandpatrick.vico.core.model.CartesianLayerModel
import com.patrykandpatrick.vico.core.model.ColumnCartesianLayerModel
import com.patrykandpatrick.vico.core.model.LineCartesianLayerModel
public class AutonomyMarkerLabelFormatter(private val colorCode: Color? = White) :
MarkerLabelFormatter {
override fun getLabel(
markedEntries: List<Marker.EntryModel>,
chartValues: ChartValues,
): CharSequence =
markedEntries.transformToSpannable(
prefix = if (markedEntries.size > 1) PATTERN.format(markedEntries.sumOf { it.entry.y }) + " (" else "",
postfix = if (markedEntries.size > 1) ")" else "",
separator = "; ",
) { model ->
if (colorCode != null) {
appendCompat(
"${model.entry.y.toInt().formatToMileage()} Mi.",
ForegroundColorSpan(colorCode.hashCode()),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE,
)
} else {
append("${model.entry.y.toInt().formatToMileage()} Mi.")
}
}
private val CartesianLayerModel.Entry.y
get() =
when (this) {
is ColumnCartesianLayerModel.Entry -> y
is LineCartesianLayerModel.Entry -> y
else -> throw IllegalArgumentException("Unexpected `CartesianLayerModel.Entry` implementation.")
}
private companion object {
const val PATTERN = "%.02f"
}
}
@composable
internal fun rememberMarker(): Marker {
val labelBackgroundColor = AutonomyBlack
val labelBackground =
remember(labelBackgroundColor) {
ShapeComponent(labelBackgroundShape).setShadow(
radius = LABEL_BACKGROUND_SHADOW_RADIUS,
dy = LABEL_BACKGROUND_SHADOW_DY,
applyElevationOverlay = true,
)
}
val context = LocalContext.current
val label =
TextComponent.Builder().apply {
background = labelBackground
lineCount = LABEL_LINE_COUNT
padding = labelPadding
typeface = ResourcesCompat.getFont(context, R.font.dmsansbold)//Typeface.createFromFile(ResourcesCompat.getFont(context, R.font.dmsansbold).toString())
textSizeSp = 13f
color = Color.White.toArgb()
}.build()
val indicator = null
val guideline = null
return remember(label, indicator, guideline) {
object : MarkerComponent(label, indicator, guideline) {
init {
labelFormatter = AutonomyMarkerLabelFormatter()
}
override fun getInsets(
context: MeasureContext,
outInsets: Insets,
horizontalDimensions: HorizontalDimensions,
) = with(context) {
outInsets.bottom = label.getHeight(context) + labelBackgroundShape.tickSizeDp.pixels +
LABEL_BACKGROUND_SHADOW_RADIUS.pixels * SHADOW_RADIUS_MULTIPLIER -
LABEL_BACKGROUND_SHADOW_DY.pixels
}
}
}
}
private const val LABEL_BACKGROUND_SHADOW_RADIUS = 4f
private const val LABEL_BACKGROUND_SHADOW_DY = 2f
private const val LABEL_LINE_COUNT = 1
private const val GUIDELINE_ALPHA = .2f
private const val INDICATOR_SIZE_DP = 36f
private const val INDICATOR_OUTER_COMPONENT_ALPHA = 32
private const val INDICATOR_CENTER_COMPONENT_SHADOW_RADIUS = 12f
private const val GUIDELINE_DASH_LENGTH_DP = 8f
private const val GUIDELINE_GAP_LENGTH_DP = 4f
private const val SHADOW_RADIUS_MULTIPLIER = 1.3f
private val labelBackgroundShape = MarkerCorneredShape(Corner.FullyRounded)
private val labelHorizontalPaddingValue = 8.dp
private val labelVerticalPaddingValue = 4.dp
private val labelPadding = dimensionsOf(labelHorizontalPaddingValue, labelVerticalPaddingValue)
private val indicatorInnerAndCenterComponentPaddingValue = 5.dp
private val indicatorCenterAndOuterComponentPaddingValue = 10.dp
private val guidelineThickness = 2.dp
private val guidelineShape = DashedShape(Shapes.pillShape, GUIDELINE_DASH_LENGTH_DP, GUIDELINE_GAP_LENGTH_DP)
from vico.
Thanks, @ozanKalan1! A custom Marker
implementation, not a MarkerComponent
instance, will be needed. I’d suggest copying over the MarkerComponent
definition and making the necessary tweaks. Pull request #540 adds the feature in question, so you can use it as a reference. Once #540 has been merged and an update has been released, you’ll no longer need a custom Marker
implementation to achieve the desired result—you’ll just have to pass an extra argument to the MarkerComponent
constructor.
By the way, in Compose, TextComponent
instances are best created via rememberTextComponent
. In rememberMarker
, for label
, you appear to be using TextComponent.Builder
, which is generally intended for the view system. With rememberTextComponent
, your TextComponent
won’t be unnecessarily recreated.
from vico.
Related Issues (20)
- Marker missing style defined by custom MarkerLabelFormatter HOT 9
- Cannot access CartesianChartHost in my project HOT 2
- Reading a state that was created after the snapshot was taken or in a snapshot that has not yet been applied HOT 6
- Cannot make a LabelFormatter on stacked column chart HOT 11
- Markers only works for the first line series HOT 2
- Crash on changing dataset which contains negative values HOT 3
- Throwing OOM Exception when using Chart in LazyColumn HOT 7
- Marker duplicated HOT 2
- No axisValueOverrider in rememberCandlestickCartesianLayer HOT 4
- Feature Missing - Slide to Position HOT 4
- Text alignment on y-axis label only shown correctly for ALIGN_NORMAL HOT 6
- [View] CartesianChartView always handles touches, even if `isClickable` or `isEnabled` is false HOT 6
- Cannot Round NaN to Float HOT 4
- Crash inside AnimatedVisibility() HOT 4
- ColumnChart with MergeMode.Grouped does not receive callback for all the series added through CartesianMarkerVisibilityListener HOT 2
- TopBottomShader.splitY doesn't do anything HOT 1
- Incorrect floating point rounding in xSpacingMultiplier calculation leads to wrong IllegalStateException HOT 6
- At the end the label of bottom axis is cut off HOT 5
- Couple crashes with `java.util.ConcurrentModificationException` and `java.util.NoSuchElementException: Key null is missing in the map` HOT 3
- Bottom label truncated sometimes HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from vico.