multiple linedataset label didn't show MPAndroidChart - android

I'm trying to show the label of my LineDataSet, but it didn't show on my android chart. It should be 4 labels at the bottom, with 4 different colors and names. I simply the code so I can post it here
Here is my code :
val chartLineDataSet = LineDataSet(arrayData, "Phasa A")
chartLineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER
chartLineDataSet.color = Color.RED
chartLineDataSet.circleRadius = 5f
chartLineDataSet.lineWidth = 2f
chartLineDataSet.setCircleColor(Color.RED)
chartLineDataSet.valueTextColor = Color.RED
chartLineDataSet.valueTextSize = 10F
chartLineDataSet.setDrawValues(false)
chartLineDataSet.setDrawCircleHole(false)
chartLineDataSet.valueFormatter = MyValueFormatter()
val lineDatas: MutableList<ILineDataSet> = ArrayList()
lineDatas.add(chartLineDataSet)
binding.lineChart.let {
it.description.isEnabled = false
it.xAxis.position = XAxis.XAxisPosition.BOTTOM
it.data = LineData(lineDatas)
it.animateXY(100, 500)
it.xAxis.setDrawGridLines(true)
it.axisLeft.textColor = Color.BLACK
it.axisRight.textColor = Color.BLACK
it.xAxis.textColor = Color.BLACK
it.legend.textColor = Color.BLACK
it.axisRight.isEnabled = false
it.axisLeft.isEnabled = true
it.isClickable = false
it.setVisibleXRangeMaximum(7F)
}
and the result for the code above
Did I miss something ?

Nevermind, I forgot to set enabled / true the binding.chart.legend. Finally, the labels are already shown.

Related

How can I see mpandroid barchart x-axis label completely?

I draw barchart in my Android project, but I can't see x-axis label completely about g, j....etc.
These letters are not shown completely. The letters cut off.
I chaged many things like margin, padding.... but I can not change x-axis label.
My code is below.
binding.contributorsChart.apply {
setDrawBarShadow(false)
setTouchEnabled(false)
setPinchZoom(false)
setDrawGridBackground(false)
description.isEnabled = false
legend.isEnabled = false
axisRight.isEnabled = false
axisLeft.apply {
axisMinimum = 0f
granularity = 10f
setDrawLabels(true)
setDrawGridLines(true)
setDrawAxisLine(true)
axisLineColor = ContextCompat.getColor(context, R.color.black)
gridColor = ContextCompat.getColor(context, R.color.black)
textColor = ContextCompat.getColor(context, R.color.black)
textSize = 13f
}
xAxis.apply {
yOffset = 5f
isEnabled = true
position = XAxis.XAxisPosition.BOTTOM
granularity = 1f
setDrawAxisLine(true)
setDrawGridLines(false)
textColor = ContextCompat.getColor(context, R.color.black)
textSize = 12f
valueFormatter = MyXAxisFormatter(contributors)
}
animateY(500) // 밑에서부터 올라오는 애니매이션 적용
}
data.apply {
setValueTextSize(12f)
barWidth = 0.3f
}
binding.contributorsChart.data = data
binding.contributorsChart.invalidate()
binding.contributorsChart.visibility = View.VISIBLE
I changed margin, padding, ... etc.

Trying to Recreate Wordscapes circle input thingy in Jetpack-Compose

I'm trying to recreate Wordscapes' circle input thingy.
That guy.
I have about 95% of it recreated. The only thing I'm missing is the removal side of it. When you drag back to the previous circle and it's removed.
I've tried a few things already and I keep running into similar issues. The line wigs out because it's removing and adding constantly. I've tried keeping a check, the last dot variable, nothing I seem to do has the intended effect to match that moving back to the circle to remove that from the list.
I have my code here
#OptIn(ExperimentalComposeUiApi::class)
#Composable
fun <T : Any> PatternInput2(
options: List<T>,
modifier: Modifier = Modifier,
optionToString: (T) -> String = { it.toString() },
dotsColor: Color,
dotsSize: Float = 50f,
letterColor: Color = dotsColor,
sensitivity: Float = dotsSize,
linesColor: Color = dotsColor,
linesStroke: Float,
circleStroke: Stroke = Stroke(width = linesStroke),
animationDuration: Int = 200,
animationDelay: Long = 100,
onStart: (Dot<T>) -> Unit = {},
onDotConnected: (Dot<T>) -> Unit = {},
onResult: (List<Dot<T>>) -> Unit = {}
) {
val scope = rememberCoroutineScope()
val dotsList = remember(options) { mutableListOf<Dot<T>>() }
var previewLine by remember {
mutableStateOf(Line(Offset(0f, 0f), Offset(0f, 0f)))
}
val connectedLines = remember { mutableListOf<Line>() }
val connectedDots = remember { mutableListOf<Dot<T>>() }
Canvas(
modifier.pointerInteropFilter {
when (it.action) {
MotionEvent.ACTION_DOWN -> {
for (dots in dotsList) {
if (
it.x in Range(dots.offset.x - sensitivity, dots.offset.x + sensitivity) &&
it.y in Range(dots.offset.y - sensitivity, dots.offset.y + sensitivity)
) {
connectedDots.add(dots)
onStart(dots)
scope.launch {
dots.size.animateTo(
(dotsSize * 1.8).toFloat(),
tween(animationDuration)
)
delay(animationDelay)
dots.size.animateTo(dotsSize, tween(animationDuration))
}
previewLine = previewLine.copy(start = Offset(dots.offset.x, dots.offset.y))
}
}
}
MotionEvent.ACTION_MOVE -> {
previewLine = previewLine.copy(end = Offset(it.x, it.y))
dotsList.find { dots ->
it.x in Range(
dots.offset.x - sensitivity,
dots.offset.x + sensitivity
) && it.y in Range(
dots.offset.y - sensitivity,
dots.offset.y + sensitivity
)
}
?.let { dots ->
if (dots !in connectedDots) {
if (previewLine.start != Offset(0f, 0f)) {
connectedLines.add(
Line(
start = previewLine.start,
end = dots.offset
)
)
}
connectedDots.add(dots)
onDotConnected(dots)
scope.launch {
dots.size.animateTo(
(dotsSize * 1.8).toFloat(),
tween(animationDuration)
)
delay(animationDelay)
dots.size.animateTo(dotsSize, tween(animationDuration))
}
previewLine = previewLine.copy(start = dots.offset)
}
}
}
MotionEvent.ACTION_UP -> {
previewLine = previewLine.copy(start = Offset(0f, 0f), end = Offset(0f, 0f))
onResult(connectedDots)
connectedLines.clear()
connectedDots.clear()
}
}
true
}
) {
drawCircle(
color = dotsColor,
radius = size.width / 2 - circleStroke.width,
style = circleStroke,
center = center
)
val radius = (size.width / 2) - (dotsSize * 2) - circleStroke.width
if (dotsList.size < options.size) {
options.forEachIndexed { index, t ->
val angleInDegrees = ((index.toFloat() / options.size.toFloat()) * 360.0) + 50.0
val x = -(radius * sin(Math.toRadians(angleInDegrees))).toFloat() + (size.width / 2)
val y = (radius * cos(Math.toRadians(angleInDegrees))).toFloat() + (size.height / 2)
dotsList.add(
Dot(
id = t,
offset = Offset(x = x, y = y),
size = Animatable(dotsSize)
)
)
}
}
if (previewLine.start != Offset(0f, 0f) && previewLine.end != Offset(0f, 0f)) {
drawLine(
color = linesColor,
start = previewLine.start,
end = previewLine.end,
strokeWidth = linesStroke,
cap = StrokeCap.Round
)
}
for (dots in dotsList) {
drawCircle(
color = dotsColor,
radius = dotsSize * 2,
style = Stroke(width = 2.dp.value),
center = dots.offset
)
drawIntoCanvas {
it.nativeCanvas.drawText(
optionToString(dots.id),
dots.offset.x,
dots.offset.y + (dots.size.value / 3),
Paint().apply {
color = letterColor.toArgb()
textSize = dots.size.value
textAlign = Paint.Align.CENTER
}
)
}
}
for (line in connectedLines) {
drawLine(
color = linesColor,
start = line.start,
end = line.end,
strokeWidth = linesStroke,
cap = StrokeCap.Round
)
}
}
}
data class Dot<T : Any>(
val id: T,
val offset: Offset,
val size: Animatable<Float, AnimationVector1D>
)
data class Line(
val start: Offset,
val end: Offset
)
#Preview
#Composable
fun PatternInput2Preview() {
var wordGuess by remember { mutableStateOf("") }
Column {
Text(wordGuess)
PatternInput2(
options = listOf("h", "e", "l", "l", "o", "!", "!"),
modifier = Modifier
.width(500.dp)
.height(1000.dp)
.background(Color.Black),
optionToString = { it },
dotsColor = Color.White,
dotsSize = 100f,
letterColor = Color.White,
sensitivity = 50.sp.value,
linesColor = Color.White,
linesStroke = 30f,
circleStroke = Stroke(width = 30f),
animationDuration = 200,
animationDelay = 100,
onStart = {
wordGuess = ""
wordGuess = it.id
},
onDotConnected = { wordGuess = "$wordGuess${it.id}" },
onResult = { /*Does a final thing*/ }
)
}
}
I have tried to put in:
onDotRemoved = { wordGuess = wordGuess.removeSuffix(it.id.toString()) },
The logic to the outside code is working as intended, but it's the component itself that's having the issue.
I've tried to do this in the ACTION_MOVE after the current code there, but this isn't working as it should:
val dots = connectedDots.lastOrNull()
if (removableDot != null && connectedDots.size >= 2) {
if (
it.x in Range(
removableDot!!.offset.x - sensitivity,
removableDot!!.offset.x + sensitivity
) &&
it.y in Range(
removableDot!!.offset.y - sensitivity,
removableDot!!.offset.y + sensitivity
)// && canRemove
) {
canRemove = false
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
connectedLines.removeIf { it.end == removableDot!!.offset }
}
connectedDots.removeLastOrNull()
onDotRemoved(removableDot!!)
removableDot = null
connectedDots.lastOrNull()?.let { previewLine = previewLine.copy(start = it.offset) }
} else if (
it.x !in Range(
removableDot!!.offset.x - sensitivity,
removableDot!!.offset.x + sensitivity
) &&
it.y !in Range(
removableDot!!.offset.y - sensitivity,
removableDot!!.offset.y + sensitivity
)
) {
canRemove = true
}
}
I actually found the solution to this!
I was doing a few things funky here. For starters:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
connectedLines.removeIf { it.end == removableDot!!.offset }
}
Was the cause of the funky line issues I was having. Replacing it with:
connectedLines.removeLastOrNull()
Was the perfect fix for it! I didn't even think of just removing the last one. I slightly over engineered this part.
The second issue I had ran into was the onDotRemoved not working correctly. Since I'm doing the removal side of this like onDotRemoved = { wordGuess = wordGuess.removeSuffix(it.id.toString()) }, so, I was curious as to why it wasn't working:
connectedDots.removeLastOrNull()
onDotRemoved(removableDot!!)
It didn't make sense to me why this wasn't working...BUT! removableDot SHOULD be the last item in connectedDots so instead of using removableDot, I ended up doing:
connectedDots.removeLastOrNull()?.let(onDotRemoved)
and it worked perfectly!

How to convert android color to compose color

I want to convert Android color to Compose color. But I don't know how.
I used these code but these codes have Error and my App crashes.
val currColor = task.startDate.time.toColor()
var test = lerp(Color.Red,Color.Blue,265f)
And
var test = Color(ArgbEvaluator().evaluate(20f,Color.Red,Color.Blue) as Int)
I checked that link too.
How to convert android.graphics.Color to androidx.compose.ui.graphics.Color
So how can I convert android.graphics.color to androidx.compose.ui.graphics.color ?
val graphicsColor = android.graphics.Color.RED
val composeColor = androidx.compose.ui.graphics.Color(graphicsColor)
You can convert it with
val int = android.graphics.Color.RED
val color = Color(int)
but you neither need conversion nor ArgbEvaluator().evaluate() to changer color based on fraction.
Compose has lerp function that takes two Compose Colors and fraction to change color based on fraction which is between 0f and 1f
lerp(Color.Red,Color.Blue,265f)
should be between 0f and 1f
/**
* Linear interpolate between two [Colors][Color], [start] and [stop] with [fraction] fraction
* between the two. The [ColorSpace] of the result is always the [ColorSpace][Color.colorSpace]
* of [stop]. [fraction] should be between 0 and 1, inclusive. Interpolation is done
* in the [ColorSpaces.Oklab] color space.
*/
#Stable
fun lerp(start: Color, stop: Color, /*#FloatRange(from = 0.0, to = 1.0)*/ fraction: Float): Color {
val colorSpace = ColorSpaces.Oklab
val startColor = start.convert(colorSpace)
val endColor = stop.convert(colorSpace)
val startAlpha = startColor.alpha
val startL = startColor.red
val startA = startColor.green
val startB = startColor.blue
val endAlpha = endColor.alpha
val endL = endColor.red
val endA = endColor.green
val endB = endColor.blue
val interpolated = Color(
alpha = lerp(startAlpha, endAlpha, fraction),
red = lerp(startL, endL, fraction),
green = lerp(startA, endA, fraction),
blue = lerp(startB, endB, fraction),
colorSpace = colorSpace
)
return interpolated.convert(stop.colorSpace)
}

Jetpack Compose: How to create a rating bar?

I'm trying to implement a rating bar. I refer to https://gist.github.com/vitorprado/0ae4ad60c296aefafba4a157bb165e60 but I don't understand anything from this code. It works but when I use this code the stars don't have rounded corners. I want to implement something like the following :
I made very basic sample for this, it would give the basic idea for creating rating bar with sample border and filled png files.
#Composable
private fun RatingBar(
modifier: Modifier = Modifier,
rating: Float,
spaceBetween: Dp = 0.dp
) {
val image = ImageBitmap.imageResource(id = R.drawable.star)
val imageFull = ImageBitmap.imageResource(id = R.drawable.star_full)
val totalCount = 5
val height = LocalDensity.current.run { image.height.toDp() }
val width = LocalDensity.current.run { image.width.toDp() }
val space = LocalDensity.current.run { spaceBetween.toPx() }
val totalWidth = width * totalCount + spaceBetween * (totalCount - 1)
Box(
modifier
.width(totalWidth)
.height(height)
.drawBehind {
drawRating(rating, image, imageFull, space)
})
}
private fun DrawScope.drawRating(
rating: Float,
image: ImageBitmap,
imageFull: ImageBitmap,
space: Float
) {
val totalCount = 5
val imageWidth = image.width.toFloat()
val imageHeight = size.height
val reminder = rating - rating.toInt()
val ratingInt = (rating - reminder).toInt()
for (i in 0 until totalCount) {
val start = imageWidth * i + space * i
drawImage(
image = image,
topLeft = Offset(start, 0f)
)
}
drawWithLayer {
for (i in 0 until totalCount) {
val start = imageWidth * i + space * i
// Destination
drawImage(
image = imageFull,
topLeft = Offset(start, 0f)
)
}
val end = imageWidth * totalCount + space * (totalCount - 1)
val start = rating * imageWidth + ratingInt * space
val size = end - start
// Source
drawRect(
Color.Transparent,
topLeft = Offset(start, 0f),
size = Size(size, height = imageHeight),
blendMode = BlendMode.SrcIn
)
}
}
private fun DrawScope.drawWithLayer(block: DrawScope.() -> Unit) {
with(drawContext.canvas.nativeCanvas) {
val checkPoint = saveLayer(null, null)
block()
restoreToCount(checkPoint)
}
}
Usage
Column {
RatingBar(rating = 3.7f, spaceBetween = 3.dp)
RatingBar(rating = 2.5f, spaceBetween = 2.dp)
RatingBar(rating = 4.5f, spaceBetween = 2.dp)
RatingBar(rating = 1.3f, spaceBetween = 4.dp)
}
Result
Also created a library that uses gestures, other png files and vectors as rating items is available here.
RatingBar(
rating = rating,
space = 2.dp,
imageBackground = imageBackground,
imageForeground = imageForeground,
animationEnabled = false,
gestureEnabled = true,
itemSize = 60.dp
) {
rating = it
}
You can pass the custom drawable as icon. check this code.
Replace your RatingStar() function as it is using canvas to draw star, instead pass the custom drawable.
#Composable
private fun starShow(){
val icon = if (isSelected)
//your selected drawable
else
//your unselected drawable
Icon(
painter = painterResource(id = icon),
contentDescription = null,
tint = MyColor.starColor)
}

How to outline text in Jetpack Compose

I have a Jetpack Compose Text() element that I'd like to outline in black like so .
Anyone know how to do this?
I've tried using the border() modifier, but that just adds a border around the rectangular area containing the text. I've also tried overlaying two text elements, but that doesn't quite work either.
The 1.4.0-alpha01 introduced a DrawStyle parameter to TextStyle function that enables drawing outlined text.
You can use something like:
Text(
text = "Sample",
style = TextStyle.Default.copy(
fontSize = 64.sp,
drawStyle = Stroke(
miter = 10f,
width = 5f,
join = StrokeJoin.Round
)
)
)
Before 1.4.0-alpha01 you can use a Canvas and the drawIntoCanvas function.
Something like:
Canvas(
modifier = Modifier.fillMaxSize(),
onDraw = {
drawIntoCanvas {
it.nativeCanvas.drawText(
"Sample",
0f,
120.dp.toPx(),
textPaintStroke
)
it.nativeCanvas.drawText(
"Sample",
0f,
120.dp.toPx(),
textPaint
)
}
}
)
with these Paint:
val textPaintStroke = Paint().asFrameworkPaint().apply {
isAntiAlias = true
style = android.graphics.Paint.Style.STROKE
textSize = 64f
color = android.graphics.Color.BLACK
strokeWidth = 12f
strokeMiter= 10f
strokeJoin = android.graphics.Paint.Join.ROUND
}
val textPaint = Paint().asFrameworkPaint().apply {
isAntiAlias = true
style = android.graphics.Paint.Style.FILL
textSize = 64f
color = android.graphics.Color.WHITE
}

Categories

Resources