I made a stat calculator and I need to store 10 user inputted values to be stored in an array where I can get the average and lowest number. How do I go about getting the values on the array to get the maximum and minimum values?
var values = ArrayList<Int>()
var count = 0
var arrCount = 0
addButt.setOnClickListener {
values.add(statNum.text.toString().toInt())
count++
arrCount++
var i = 0
statNum.setText("")
statArray.text = ""
for (i in 0..arrCount - 1) {
statArray.text = statArray.text as String + values[i] + ","
}
}
avgBut.setOnClickListener{
val statArray = doubleArrayOf(4.0, 7.0, 11.0, 12.0, 9.0)
var sum = 0.0
for (num in statArray) {
sum += num
}
val average = sum / statArray.size
finalAnswer.text = average.toString()
}
minmaxBut.setOnClickListener{
fun findMin(list: List<Int?>): Int? {
return list.sortedWith(compareBy { it }).first()
}
fun findMax(list: List<Int?>): Int? {
return list.sortedWith(compareBy { it }).last()
}
fun main() {
val list = listOf(10, 4, 2, 7, 6, 9)
val min = findMin(list)
finalAnswer.text = "Min Vale = $min"
val max = findMax(list)
println(max) // 10
}
It's very easy to get min, max and average number in the arraylist. I did not understand your code clearly but i will share how you can do these. After you may use that on your array:
val list = arrayListOf<Int>(1,2,3,4,5,6,7,8,9,10)
Log.e("min", list.min().toString())
Log.e("max", list.max().toString())
Log.e("average", list.average().toString())
This will give you below output in logcat:
E/min: 1
E/max: 10
E/average: 5.5
I am currently attempting to do something very similar (or maybe the same) as the following question:
Getting variable frequency ranges with androids visualizer class
However, the selected answer has a few bugs, and I'm not a DSP/Audio expert at all and I'm learning as I go.
My goal is to break an FFT that I'm getting from Android Visualizer class into frequency bands. Specifically, these bands:
0Hz - 400Hz
400Hz - 900Hz
900Hz - 1500Hz
1500Hz - 2300Hz
2300Hz - 3400Hz
3400Hz - 5000Hz
5000Hz - 7300Hz
7300Hz - 12000Hz
I have the following code, at the top of my class:
private val targetEndpoints = listOf(0f, 400f, 900f, 1500f, 2300f, 3400f, 5000f, 7300f, 12000f)
private const val CAPTURE_SIZE = 1024
and then, in the method where I'm trying to get the frequency bands for the current track in MediaPlayer:
val mp = mediaPlayer!!
val audioSessionId = mp.getAudioSessionId()
val visualizer: Visualizer = Visualizer(audioSessionId)
val captureSizeRange = Visualizer.getCaptureSizeRange().let { it[0]..it[1] }
val captureSize = CAPTURE_SIZE.coerceIn(captureSizeRange)
val captureRate: Int = Visualizer.getMaxCaptureRate()
val isWaveFormRequested: Boolean = false
val isFFTRequested: Boolean = true
visualizer.setCaptureSize(captureSize)
val frequencyOrdinalRanges: List<IntProgression> =
targetEndpoints.zipWithNext { a, b ->
val startOrdinal = 1 + (captureSize * a / samplingRate).toInt()
val endOrdinal = (captureSize * b / samplingRate).toInt()
startOrdinal downTo endOrdinal
}
Now this is the point where things are getting a little murky for me because, like I said, I am no Audio expert.
frequencyOrdinalRanges is a List with IntProgressions that go 1 -> 0
For the audio file that I'm using:
captureSize = 1024
samplingRate = 44100000
With those numbers and my frequency bands, pretty much guarantees that the startOrdinal will always be 1, and endOrdinal will always be 0.
So my frequencyOrdinalRanges looks like this:
[1 downTo 0 step 1, 1 downTo 0 step 1, 1 downTo 0 step 1, 1 downTo 0 step 1, 1 downTo 0 step 1, 1 downTo 0 step 1, 1 downTo 0 step 1]
Then I've got an Listener with a capture rate of 20000 milihertz:
visualizer.setDataCaptureListener(listener, captureRate, isWaveFormRequested, isFFTRequested)
The values for the above call are as follows:
captureRate = 2000 // in milihertz
isWaveFormRequested = false
isFFTRequested = true
The onFftDataCapture of the listener object looks as follows:
override fun onFftDataCapture(visualizer: Visualizer, bytes: ByteArray, samplingRate: Int) {
var output = DoubleArray(frequencyOrdinalRanges.size)
for ((i, ordinalRange) in frequencyOrdinalRanges.withIndex()) {
var logMagnitudeSum = 0.0
for (k in ordinalRange) {
val fftIndex = k * 2
val currentByte = bytes[fftIndex].toDouble()
val nextByte = bytes[fftIndex + 1].toDouble()
val hypot = Math.hypot(currentByte, nextByte)
val logHypot = Math.log10(hypot)
logMagnitudeSum += logHypot
val result = (logMagnitudeSum / (ordinalRange.last - ordinalRange.first + 1)).toDouble()
output[i] = result
}
// do something else with output
}
Now the problem I'm facing with onFftDataCapture is that this line:
val hypot = Math.hypot(currentByte, nextByte)
it often evaluates to 0, thus making the following line evaluate to -Infinity and ultimately giving me an array full of Infinity values which I can't do anything with.
This leads me to believe that I am doing something very wrong, but I am not sure what or how to fix it.
This answer looks more or less what I am trying to do, but then again, I am no expert in audio analysis, so all the finer details totally escape me.
The way to extract 10-band equalization information from mp3 format
Can someone tell me what am I doing wrong? or what am I missing?
The problem with my code was quite silly... I was using samplingRate in milihertz... the formula expects the sampling rate to be in Hertz.
Dividing samplingRate by 1000 fixed the problems.
This changes to:
val samplingRateInHz = samplingRate / 1000
val frequencyOrdinalRanges: List<IntRange> =
targetEndpoints.zipWithNext { a, b ->
val startOrdinal = 1 + (captureSize * a / samplingRateInHz).toInt()
val endOrdinal = (captureSize * b / samplingRateInHz).toInt()
startOrdinal..endOrdinal
}
I have a codebase where all my data calculations and data formatting occur within a single function. Are there any performance benefits to separating these out into separate functions or does separating them only improve readability?
I know that I should separate them but I don't really know all the reasons why.
Here is the function I am referring to:
private fun processData(data: ByteArray) {
progressBar.visibility = GONE
Log.d(TAG, "displayDiagnosticData: ")
val bmsVersionView = findViewById<TextView>(R.id.textview_bms_version)
val boardVersionView = findViewById<TextView>(R.id.textview_board_version)
val cellOneView = findViewById<TextView>(R.id.textview_cell_1)
val cellTwoView = findViewById<TextView>(R.id.textview_cell_2)
val cellThreeView = findViewById<TextView>(R.id.textview_cell_3)
val cellFourView = findViewById<TextView>(R.id.textview_cell_4)
val cellFiveView = findViewById<TextView>(R.id.textview_cell_5)
val cellSixView = findViewById<TextView>(R.id.textview_cell_6)
val cellSevenView = findViewById<TextView>(R.id.textview_cell_7)
val cellEightView = findViewById<TextView>(R.id.textview_cell_8)
val cellNineView = findViewById<TextView>(R.id.textview_cell_9)
val cellTenView = findViewById<TextView>(R.id.textview_cell_10)
val cellElevenView = findViewById<TextView>(R.id.textview_cell_11)
val cellTwelveView = findViewById<TextView>(R.id.textview_cell_12)
val cellThirteenView = findViewById<TextView>(R.id.textview_cell_13)
val cellFourteenView = findViewById<TextView>(R.id.textview_cell_14)
val packTotalView = findViewById<TextView>(R.id.textview_diagnostic_voltage)
val packSocView = findViewById<TextView>(R.id.textview_diagnostic_soc)
val chargeTempView = findViewById<TextView>(R.id.textview_charge_temp)
val dischargeTempView = findViewById<TextView>(R.id.textview_discharge_temp)
val chargeCurrentView = findViewById<TextView>(R.id.textview_diagnostic_charge_current)
// val dischargeCurrentView = findViewById<TextView>(R.id.textview_diagnostic_discharge_current)
val dischargeCircuitStateView = findViewById<TextView>(R.id.textview_discharge_circuit)
val chargeCircuitStateView = findViewById<TextView>(R.id.textview_charge_circuit)
val balanceCircuitStateView = findViewById<TextView>(R.id.textview_balance_circuit)
val emptyCircuitStateView = findViewById<TextView>(R.id.textview_empty_circuit)
val bmsVersion = data[0] + (data[1] * 256)
val cellOne = data[2].toDouble() / 100 + 3.52
val cellTwo = data[3].toDouble() / 100 + 3.52
val cellThree = data[4].toDouble() / 100 + 3.52
val cellFour = data[5].toDouble() / 100 + 3.52
val cellFive = data[6].toDouble() / 100 + 3.52
val cellSix = data[7].toDouble() / 100 + 3.52
val cellSeven = data[8].toDouble() / 100 + 3.52
val cellEight = data[9].toDouble() / 100 + 3.52
val cellNine = data[10].toDouble() / 100 + 3.52
val cellTen = data[11].toDouble() / 100 + 3.52
val cellEleven = data[12].toDouble() / 100 + 3.52
val cellTwelve = data[13].toDouble() / 100 + 3.52
val cellThirteen = data[14].toDouble() / 100 + 3.52
val cellFourteen = data[15].toDouble() / 100 + 3.52
val totalVoltage = 47.8 + (data[16].toDouble() / 10)
val chargeTempCelsius = data[19]
val dischargeTempCelsius = data[20]
val chargeTempFahr = (chargeTempCelsius * 9.0 / 5.0) + 32.0
val dischargeTempFahr = (dischargeTempCelsius * 9.0 / 5.0) + 32.0
val chargeCurrent = data[21]
// val dischargeCurrent = (data[23].toDouble() * 100 + data[22]).toInt()
val chargeCircuitState = data[25].toInt()
val dischargeCircuitState = data[26].toInt()
val balanceCircuitState = data[27].toInt()
val emptyCircuitState = data[28].toInt()
val chargeCircuit: String = if (chargeCircuitState == 1) {
"On"
}else {
"Off"
}
val dischargeCircuit: String = if (dischargeCircuitState == 1) {
"On"
}else {
"Off"
}
val balanceCircuit: String = if (balanceCircuitState == 1) {
"On"
}else {
"Off"
}
val emptyCircuit: String = if (emptyCircuitState == 1) {
"On"
}else {
"Off"
}
val bmsVersionString = SpannableString("BMS Version: $bmsVersion")
bmsVersionString.setSpan(StyleSpan(Typeface.BOLD), 0, 11, 0)
val boardVersionString = SpannableString("Board Version: 2.1")
boardVersionString.setSpan(StyleSpan(Typeface.BOLD), 0, 13, 0)
val cellOneString = SpannableString("Cell 1: %.2fV".format(cellOne))
cellOneString.setSpan(StyleSpan(Typeface.BOLD), 0, 6, 0)
val cellTwoString = SpannableString("Cell 2: %.2fV".format(cellTwo))
cellTwoString.setSpan(StyleSpan(Typeface.BOLD), 0, 6, 0)
val cellThreeString = SpannableString("Cell 3: %.2fV".format(cellThree))
cellThreeString.setSpan(StyleSpan(Typeface.BOLD), 0, 6, 0)
val cellFourString = SpannableString("Cell 4: %.2fV".format(cellFour))
cellFourString.setSpan(StyleSpan(Typeface.BOLD), 0, 6, 0)
val cellFiveString = SpannableString("Cell 5: %.2fV".format(cellFive))
cellFiveString.setSpan(StyleSpan(Typeface.BOLD), 0, 6, 0)
val cellSixString = SpannableString("Cell 6: %.2fV".format(cellSix))
cellSixString.setSpan(StyleSpan(Typeface.BOLD), 0, 6, 0)
val cellSevenString = SpannableString("Cell 7: %.2fV".format(cellSeven))
cellSevenString.setSpan(StyleSpan(Typeface.BOLD), 0, 6, 0)
val cellEightString = SpannableString("Cell 8: %.2fV".format(cellEight))
cellEightString.setSpan(StyleSpan(Typeface.BOLD), 0, 6, 0)
val cellNineString = SpannableString("Cell 9: %.2fV".format(cellNine))
cellNineString.setSpan(StyleSpan(Typeface.BOLD), 0, 6, 0)
val cellTenString = SpannableString("Cell 10: %.2fV".format(cellTen))
cellTenString.setSpan(StyleSpan(Typeface.BOLD), 0, 7, 0)
val cellElevenString = SpannableString("Cell 11: %.2fV".format(cellEleven))
cellElevenString.setSpan(StyleSpan(Typeface.BOLD), 0, 7, 0)
val cellTwelveString = SpannableString("Cell 12: %.2fV".format(cellTwelve))
cellTwelveString.setSpan(StyleSpan(Typeface.BOLD), 0, 7, 0)
val cellThirteenString = SpannableString("Cell 13: %.2fV".format(cellThirteen))
cellThirteenString.setSpan(StyleSpan(Typeface.BOLD), 0, 7, 0)
val cellFourteenString = SpannableString("Cell 14: %.2fV".format(cellFourteen))
cellFourteenString.setSpan(StyleSpan(Typeface.BOLD), 0, 7, 0)
val packTotalString = SpannableString("Pack Total: %.1fV".format(totalVoltage))
packTotalString.setSpan(StyleSpan(Typeface.BOLD), 0, 10, 0)
val socString = SpannableString("SOC: ${data[17].toInt()}%")
socString.setSpan(StyleSpan(Typeface.BOLD), 0, 3, 0)
val chargeTempString = SpannableString("Charge Temp: ${chargeTempFahr.toInt()}" + "°F")
chargeTempString.setSpan(StyleSpan(Typeface.BOLD), 0, 11, 0)
val dischargeTempString = SpannableString("Discharge Temp: ${dischargeTempFahr.toInt()}" + "°F")
dischargeTempString.setSpan(StyleSpan(Typeface.BOLD), 0, 15, 0)
val chargeCurrentString = SpannableString("Charge Current: $chargeCurrent" + "A")
chargeCurrentString.setSpan(StyleSpan(Typeface.BOLD), 0, 14, 0)
// val dischargeCurrentString = "Discharge Current: $dischargeCurrent" + "A"
val chargeCircuitStateString = SpannableString("Charge Circuit: $chargeCircuit")
chargeCircuitStateString.setSpan(StyleSpan(Typeface.BOLD), 0, 14, 0)
val dischargeCircuitStateString = SpannableString("Discharge Circuit: $dischargeCircuit")
dischargeCircuitStateString.setSpan(StyleSpan(Typeface.BOLD), 0, 17, 0)
val balanceCircuitStateString = SpannableString("Balance Circuit: $balanceCircuit")
balanceCircuitStateString.setSpan(StyleSpan(Typeface.BOLD), 0, 15, 0)
val emptyCircuitStateString = SpannableString("Empty Circuit: $emptyCircuit")
emptyCircuitStateString.setSpan(StyleSpan(Typeface.BOLD), 0, 13, 0)
bmsVersionView.text = bmsVersionString
boardVersionView.text = boardVersionString
cellOneView.text = cellOneString
cellTwoView.text = cellTwoString
cellThreeView.text = cellThreeString
cellFourView.text = cellFourString
cellFiveView.text = cellFiveString
cellSixView.text = cellSixString
cellSevenView.text = cellSevenString
cellEightView.text = cellEightString
cellNineView.text = cellNineString
cellTenView.text = cellTenString
cellElevenView.text = cellElevenString
cellTwelveView.text = cellTwelveString
cellThirteenView.text = cellThirteenString
cellFourteenView.text = cellFourteenString
packTotalView.text = packTotalString
packSocView.text = socString
chargeTempView.text = chargeTempString
dischargeTempView.text = dischargeTempString
chargeCurrentView.text = chargeCurrentString
// dischargeCurrentView.text = dischargeCurrentString
chargeCircuitStateView.text = chargeCircuitStateString
dischargeCircuitStateView.text = dischargeCircuitStateString
balanceCircuitStateView.text = balanceCircuitStateString
emptyCircuitStateView.text = emptyCircuitStateString
}
Performance? No. Maintainability? Yes. Separation of concerns is one of the core tenets of modern software architecture. Combining the two things makes a difficult to read, difficult to debug mess. Separating them allows you to concentrate on one thing at a time, and makes it easier for people maintaining the code (which may even be you 6 months from now when fixing a bug and you've forgotten how it works) to understand the logic and flow of the program.
That function you posted would not be accepted in any professional codebase. It's too long, it does too many things. It needs to be broken up.
Your bigger problem there is that you're repeating yourself, a lot. Not only does that make the whole thing longer, and arguably harder to read, it also makes it hard to maintain like Gabe says, and makes it far more likely a bug will sneak in there. Imagine you needed to add another row of cells - there's a lot of boilerplate involved, a lot of repetitive work, and that's where humans tend to mess up
Like as an example of the kind of thing you can do - see how your cell data is basically taken from a range of values in data, with the same calculation applied to each? You could do this instead:
val cells = (2..15).map { index -> data[index].toDouble() / 100 + 3.52 }
or, to keep things more explicit and separate:
// Except give this a good name since it's doing something specific
// Because this is some kind of conversion formula, putting it in its own function
// makes it easy to maintain and document, and it's clear exactly what it is
fun getCellValue(dataValue: Int) = dataValue.toDouble() / 100 + 3.52
val cells = (2..15).map { index -> getCellValue(data[index]) }
Now you have one or two lines replacing 14 lines of initialisation code. It's also easier to make changes - if the format of data changes, you can easily change the range of indices to use, or the formula applied to each value. It's one place, instead of on each line, where you have to update each one and make sure you haven't made a typo or skipped one.
And when you have structured data like that, it can make your other code easier to work with too - because instead of needing to work with separate variables, you can work with indices and loop over things instead of writing each step out:
// no need for a separate line for each with hardcoded values if you can work it out
// (Because it's a separate function, you can use it for the other display lines too,
// it's not cell-specific)
fun SpannableString.applyBoldPrefix() = apply {
val colonIndex = indexOf(':')
if (colonIndex >= 0) setSpan(StyleSpan(Typeface.BOLD), 0, colonIndex, 0)
}
// you could also just pass in the index and look up cells[index] here -
// this is a more functional approach, but whatever's good
fun getCellDisplayString(cellIndex: Int, cellData: Double) =
SpannableString("Cell ${cellIndex + 1}: %.2fV".format(cellData))
.applyBoldPrefix()
// lots of ways to define/grab a set of views programmatically - putting them all
// in a container you can look up is one way. You can also generate resource identifier
// strings, like "R.id.textview_cell_$i" and look that up
val cellTextViews = findViewById<ViewGroup>(R.id.containerHoldingCells)
.children.filterIsInstance<TextView>
// now you can just iterate over stuff to complete the repetitive task
cellTextViews.forEachIndexed { i, view ->
view.text = getCellDisplayString(i, cells[i])
}
That's about half your code right there. I wouldn't necessarily structure everything this way (I feel like given you're working with a data format here, a more formal structure definition would be helpful, and you can generalise more too) and it's a bit rough-and-ready, but hopefully it gives you a general sense of how you can cut things down, but also make it easier to maintain them and try out changes
I condensed my code a lot more and created functions to process separate chunks of data. I also was able to get rid of a lot of my repetitious code. For anyone who is interested, here is the updated code:
private fun String.withStyling() = SpannableString(this).apply {
setSpan(StyleSpan(Typeface.BOLD), 0, indexOfFirst { it == ':' }, 0)
}
private fun processDiagnosticData(data: ByteArray) {
binding.progressBarCyclic.visibility = GONE
Log.d(TAG, "displayDiagnosticData: ")
processCells(data)
processTemps(data[19], data[20])
processCircuits(data)
processOtherData(data)
}
// Process cells 1-14 and display.
private fun processCells(data: ByteArray) {
val cellViews = listOf(
binding.textviewCell1,
binding.textviewCell2,
binding.textviewCell3,
binding.textviewCell4,
binding.textviewCell5,
binding.textviewCell6,
binding.textviewCell7,
binding.textviewCell8,
binding.textviewCell9,
binding.textviewCell10,
binding.textviewCell11,
binding.textviewCell12,
binding.textviewCell13,
binding.textviewCell14
)
for ((i, cellView) in cellViews.withIndex()) {
val value = data[2 + i].toDouble() / 100 + 3.52
val cellNumberString = (i + 1).toString()
val formattedString = "Cell $cellNumberString: %.2fV".format(value).withStyling()
cellView.text = formattedString
}
}
// Process charge/discharge temps and display.
private fun processTemps(chargeTempCel: Byte, dischargeTempCel: Byte) {
val chargeTempFahr = chargeTempCel * 9.0 / 5.0 + 32.0
val dischargeTempFahr = dischargeTempCel * 9.0 / 5.0 + 32.0
val chargeTempString = "Charge Temp: $chargeTempFahr°F".withStyling()
val dischargeTempString = "Discharge Temp: $dischargeTempFahr°F".withStyling()
binding.textviewChargeTemp.text = chargeTempString
binding.textviewDischargeTemp.text = dischargeTempString
}
// Process circuit states and display.
private fun processCircuits(data: ByteArray) {
val circuitViews = listOf(
binding.textviewChargeCircuit,
binding.textviewDischargeCircuit,
binding.textviewBalanceCircuit,
binding.textviewEmptyCircuit
)
val circuitNames = listOf(
"Charge Circuit: ",
"Discharge Circuit: ",
"Balance Circuit: ",
"Empty Circuit: "
)
for ((i, circuit) in circuitViews.withIndex()) {
val value = if (data[25 + i].toInt() == 1) {
"On"
} else {
"Off"
}
val formattedString = (circuitNames[i] + value).withStyling()
circuit.text = formattedString
}
}
// Process the rest of the data and display.
private fun processOtherData(data: ByteArray) {
val totalVoltage = 47.8 + (data[16].toDouble() / 10)
val packSoc = data[17].toInt()
val chargeCurrent = data[21]
// val dischargeCurrent = (data[23].toDouble() * 100 + data[22]).toInt()
val bmsVersionString = "BMS Version: ${data[0] + (data[1] * 256)}".withStyling()
val boardVersionString = "Board Version: 2.1".withStyling()
val totalVoltageString = "Pack Total: %.1fV".format(totalVoltage).withStyling()
val packSocString = "SOC: ${packSoc}%".withStyling()
val chargeCurrentString = "Charge Current: ${chargeCurrent}A".withStyling()
// val dischargeCurrent = "Discharge Current: $dischargeCurrentA".withStyling()
binding.textviewBmsVersion.text = bmsVersionString
binding.textviewBoardVersion.text = boardVersionString
binding.textviewDiagnosticVoltage.text = totalVoltageString
binding.textviewDiagnosticSoc.text = packSocString
binding.textviewDiagnosticChargeCurrent.text = chargeCurrentString
// binding.textviewDiagnosticDischargeCurrent.text = dischargeCurrentString
}
I am trying to show the data using LineChart, and ran into issues displaying x axis labels. I use data.start and data.end to set the x-axis bounds in my chart. So let's say API returns data for two days only (Thursday and Friday), start will be Monday and end will be Saturday.
Note:X values are ALL unix timestamps.
here's my code:
class MyChart(chart: LineChart?, val data: MyData) {
private val startValue = data.start.toEpochSecond(ZoneOffset.UTC)
init {
chart?.run {
setScaleEnabled(false)
legend.isEnabled = false
description.isEnabled = false
axisRight.run {
setDrawGridLines(true)
setDrawLabels(false)
axisMinimum = 0.1f // hide 0.0 values
}
axisLeft.run {
setDrawGridLines(true)
axisMinimum = 0.1f // hide 0.0 values
}
setupXAxis(xAxis)
Log.e("MPTEST, startValue: ", startValue.toString())
val entries = ArrayList<Entry>()
data.list?.forEachIndexed { _, data ->
val timeInSeconds = data.time.toEpochSecond(ZoneOffset.UTC)
val xIndex = (timeInSeconds - startValue).toFloat()
Log.e("MPTEST, xIndex: ", xIndex.toString())
entries.add(Entry(xIndex, data.value))
}
val data = LineData(LineDataSet(entries, ""))
setData(data)
invalidate()
}}
private fun setupXAxis(xAxis: XAxis?) {
xAxis?.run {
position = XAxis.XAxisPosition.BOTTOM
val startInSeconds = data.start.toEpochSecond(ZoneOffset.UTC)
axisMinimum = (startInSeconds - startValue).toFloat()
Log.e("MPTEST, axisMinimum: ", axisMinimum.toString())
val endInSeconds = data.end.toEpochSecond(ZoneOffset.UTC)
axisMaximum = (endInSeconds - startValue).toFloat()
Log.e("MPTEST, axisMaximum: ", axisMaximum.toString())
setCenterAxisLabels(true)
setDrawGridLines(false)
// I need to fix something here I think
setLabelCount(7, true)
valueFormatter = IndexAxisValueFormatter(data.labels)
}
} }
Here's the logcat output:
E/MPTEST, axisMinimum:: 0.0
E/MPTEST, axisMaximum:: 604799.0
E/MPTEST, startValue:: 1546732800
E/MPTEST, xIndex:: 366180.0
E/MPTEST, xIndex:: 467893.0
That's what I get - https://i.ibb.co/YD2DnhJ/Screen-Shot-2019-01-16-at-7-20-23-AM.png
(as you can see only first x axis label is displayed)
and this is what I am trying to achieve - https://i.ibb.co/M8b9pyP/Screen-Shot-2019-01-16-at-7-24-15-AM.png