diff --git a/app/src/androidTest/kotlin/info/appdev/chartexample/StartTest.kt b/app/src/androidTest/kotlin/info/appdev/chartexample/StartTest.kt index 5bbdbaf80..b667f4fbb 100644 --- a/app/src/androidTest/kotlin/info/appdev/chartexample/StartTest.kt +++ b/app/src/androidTest/kotlin/info/appdev/chartexample/StartTest.kt @@ -42,6 +42,7 @@ import org.junit.Test import org.junit.rules.TestName import org.junit.runner.RunWith import timber.log.Timber +import kotlin.jvm.java @RunWith(AndroidJUnit4::class) @@ -278,6 +279,7 @@ class StartTest { contentItem.clazz == HorizontalBarFullComposeActivity::class.java || contentItem.clazz == MultiLineComposeActivity::class.java || contentItem.clazz == GradientActivity::class.java || + contentItem.clazz == TimeBarActivity::class.java || contentItem.clazz == TimeLineActivity::class.java ) { // These charts have less clickable area, so skip further clicks diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 104d62c8d..96654d69d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -60,6 +60,7 @@ + diff --git a/app/src/main/kotlin/info/appdev/chartexample/TimeBarActivity.kt b/app/src/main/kotlin/info/appdev/chartexample/TimeBarActivity.kt new file mode 100644 index 000000000..e9525b1cf --- /dev/null +++ b/app/src/main/kotlin/info/appdev/chartexample/TimeBarActivity.kt @@ -0,0 +1,251 @@ +package info.appdev.chartexample + +import android.Manifest +import android.R.attr.entries +import android.content.Intent +import android.content.pm.PackageManager +import android.graphics.Color +import android.os.Bundle +import android.view.Menu +import android.view.MenuItem +import android.widget.SeekBar +import android.widget.SeekBar.OnSeekBarChangeListener +import androidx.core.content.ContextCompat +import androidx.core.content.res.ResourcesCompat +import androidx.core.net.toUri +import info.appdev.chartexample.DataTools.Companion.getValues +import info.appdev.chartexample.TimeLineActivity.Companion.TIME_OFFSET +import info.appdev.chartexample.databinding.ActivityHorizontalbarchartBinding +import info.appdev.chartexample.formatter.TimeRangeValueFormatter +import info.appdev.chartexample.formatter.UnixTimeAxisValueFormatter +import info.appdev.chartexample.formatter.UnixTimeRelative2NowAxisValueFormatter +import info.appdev.chartexample.formatter.UnixTimeValueFormatter +import info.appdev.chartexample.notimportant.DemoBase +import info.appdev.charting.components.Description +import info.appdev.charting.components.Legend +import info.appdev.charting.components.XAxis.XAxisPosition +import info.appdev.charting.data.BarData +import info.appdev.charting.data.BarDataSet +import info.appdev.charting.data.BarEntryDouble +import info.appdev.charting.data.BarEntryFloat +import info.appdev.charting.interfaces.datasets.IBarDataSet +import timber.log.Timber + +class TimeBarActivity : DemoBase(), OnSeekBarChangeListener { + + private lateinit var binding: ActivityHorizontalbarchartBinding + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = ActivityHorizontalbarchartBinding.inflate(layoutInflater) + setContentView(binding.root) + + binding.seekBarX.setOnSeekBarChangeListener(this) + binding.seekBarY.setOnSeekBarChangeListener(this) + + binding.chart1.isLogging = true + binding.chart1.isDrawBarShadow = false + binding.chart1.isDrawValueAboveBar = true + binding.chart1.description.isEnabled = true + binding.chart1.description = Description().apply { + text = "Time Bar Line" + } + + // if more than 60 entries are displayed in the chart, no values will be drawn + binding.chart1.setMaxVisibleValueCount(60) + + // scaling can now only be done on x- and y-axis separately + binding.chart1.isPinchZoom = false + + // draw shadows for each bar that show the maximum value + // chart.setDrawBarShadow(true); + binding.chart1.setDrawGridBackground(false) + + binding.chart1.xAxis.apply { + position = XAxisPosition.BOTTOM + typeface = tfLight + isDrawAxisLine = true + isDrawGridLines = true + granularity = 10f +// valueFormatter = UnixTimeAxisValueFormatter("HH:mm:ss") + } + +// binding.chart1.axisLeft.apply { +// typeface = tfLight +// isDrawAxisLine = true +// isDrawGridLines = true +// axisMinimum = 0f // this replaces setStartAtZero(true) +// } + + binding.chart1.axisRight.apply { + typeface = tfLight + isDrawAxisLine = true + isDrawGridLines = false + axisMinimum = 0f // this replaces setStartAtZero(true) + valueFormatter = UnixTimeRelative2NowAxisValueFormatter("HH:mm:ss") + } + + binding.chart1.setFitBars(true) + binding.chart1.animateY(2500) + + // setting data + binding.seekBarX.progress = 4 + binding.seekBarY.progress = 12 + + binding.chart1.legend.apply { + verticalAlignment = Legend.LegendVerticalAlignment.BOTTOM + horizontalAlignment = Legend.LegendHorizontalAlignment.LEFT + orientation = Legend.LegendOrientation.HORIZONTAL + setDrawInside(false) + formSize = 8f + xEntrySpace = 4f + } + } + + private fun setData(count: Int) { + val barWidth = 9f + val spaceForBar = 10.0 + val values = ArrayList() + val sampleValues = getValues(100).map { (it!! * 100).toInt() } + + var previousTimeOffset: Double = 0.0 //TIME_OFFSET.toDouble() + for (i in 0.. 0 + ) { + set1 = binding.chart1.barData!!.getDataSetByIndex(0) as BarDataSet + @Suppress("UNCHECKED_CAST") + set1.entries = values as MutableList + binding.chart1.barData?.notifyDataChanged() + binding.chart1.notifyDataSetChanged() + } else { + @Suppress("UNCHECKED_CAST") + set1 = BarDataSet(values as MutableList, "Bar DataSet") + set1.setColors( + Color.GREEN, + Color.BLUE, + Color.YELLOW + ) + + set1.isDrawIcons = false + + val dataSets = ArrayList() + dataSets.add(set1) + + val data = BarData(dataSets) + data.setValueTextSize(10f) + data.setValueTypeface(tfLight) + data.setValueFormatter(TimeRangeValueFormatter("HH:mm:ss")) + data.barWidth = barWidth + binding.chart1.data = data + } + } + + override fun onCreateOptionsMenu(menu: Menu?): Boolean { + menuInflater.inflate(R.menu.bar, menu) + return true + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + when (item.itemId) { + R.id.viewGithub -> { + val i = Intent(Intent.ACTION_VIEW) + i.data = + "https://github.com/AppDevNext/AndroidChart/blob/master/app/src/main/java/info/appdev/chartexample/HorizontalBarChartActivity.kt".toUri() + startActivity(i) + } + + R.id.actionToggleValues -> { + binding.chart1.barData?.dataSets?.forEach { + it.isDrawValues = !it.isDrawValues + } + binding.chart1.invalidate() + } + + R.id.actionToggleIcons -> { + binding.chart1.barData?.dataSets?.forEach { set -> + set.isDrawIcons = !set.isDrawIcons + } + binding.chart1.invalidate() + } + + R.id.actionToggleHighlight -> { + binding.chart1.barData?.let { data -> + data.isHighlight = !data.isHighlight + binding.chart1.invalidate() + } + } + + R.id.actionTogglePinch -> { + binding.chart1.isPinchZoom = !binding.chart1.isPinchZoom + binding.chart1.invalidate() + } + + R.id.actionToggleAutoScaleMinMax -> { + binding.chart1.isAutoScaleMinMax = !binding.chart1.isAutoScaleMinMax + binding.chart1.notifyDataSetChanged() + } + + R.id.actionToggleBarBorders -> { + binding.chart1.barData?.dataSets?.map { it as BarDataSet }?.forEach { set -> + set.barBorderWidth = if (set.barBorderWidth == 1f) 0f else 1f + } + binding.chart1.invalidate() + } + + R.id.animateX -> { + binding.chart1.animateX(2000) + } + + R.id.animateY -> { + binding.chart1.animateY(2000) + } + + R.id.animateXY -> { + binding.chart1.animateXY(2000, 2000) + } + + R.id.actionSave -> { + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + saveToGallery() + } else { + requestStoragePermission(binding.chart1) + } + } + } + return true + } + + override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) { + binding.tvXMax.text = binding.seekBarX.progress.toString() + binding.tvYMax.text = binding.seekBarY.progress.toString() + + setData(binding.seekBarX.progress) + binding.chart1.setFitBars(true) + binding.chart1.invalidate() + } + + override fun saveToGallery() { + saveToGallery(binding.chart1, "HorizontalBarChartActivity") + } + + override fun onStartTrackingTouch(seekBar: SeekBar?) = Unit + + override fun onStopTrackingTouch(seekBar: SeekBar?) = Unit + +} diff --git a/app/src/main/kotlin/info/appdev/chartexample/notimportant/MainActivity.kt b/app/src/main/kotlin/info/appdev/chartexample/notimportant/MainActivity.kt index 9c50a3bf2..38f26d6b7 100644 --- a/app/src/main/kotlin/info/appdev/chartexample/notimportant/MainActivity.kt +++ b/app/src/main/kotlin/info/appdev/chartexample/notimportant/MainActivity.kt @@ -75,6 +75,7 @@ import info.appdev.chartexample.ScrollViewActivity import info.appdev.chartexample.SpecificPositionsLineChartActivity import info.appdev.chartexample.StackedBarActivity import info.appdev.chartexample.StackedBarActivityNegative +import info.appdev.chartexample.TimeBarActivity import info.appdev.chartexample.TimeLineActivity import info.appdev.chartexample.compose.HorizontalBarComposeActivity import info.appdev.chartexample.compose.HorizontalBarFullComposeActivity @@ -219,6 +220,7 @@ class MainActivity : ComponentActivity() { add(ContentItem("Demonstrate and fix issues")) add(ContentItem("Gradient", "Show a gradient edge case", GradientActivity::class.java)) add(ContentItem("Timeline", "Show a time line with Unix timestamp", TimeLineActivity::class.java)) + add(ContentItem("TimeBar", "Show a time line with Unix timestamp", TimeBarActivity::class.java)) } } } diff --git a/screenshotsToCompare9/StartTest_smokeTestStart-46-TimeBarActivity-TimeBar-1SampleClick.png b/screenshotsToCompare9/StartTest_smokeTestStart-46-TimeBarActivity-TimeBar-1SampleClick.png new file mode 100644 index 000000000..4960717a3 Binary files /dev/null and b/screenshotsToCompare9/StartTest_smokeTestStart-46-TimeBarActivity-TimeBar-1SampleClick.png differ diff --git a/screenshotsToCompare9/StartTest_smokeTestStart-46-TimeBarActivity-TimeBar-2menu-click-10ToggleBarBorders.png b/screenshotsToCompare9/StartTest_smokeTestStart-46-TimeBarActivity-TimeBar-2menu-click-10ToggleBarBorders.png new file mode 100644 index 000000000..675558691 Binary files /dev/null and b/screenshotsToCompare9/StartTest_smokeTestStart-46-TimeBarActivity-TimeBar-2menu-click-10ToggleBarBorders.png differ diff --git a/screenshotsToCompare9/StartTest_smokeTestStart-46-TimeBarActivity-TimeBar-2menu-click-1ToggleValues.png b/screenshotsToCompare9/StartTest_smokeTestStart-46-TimeBarActivity-TimeBar-2menu-click-1ToggleValues.png new file mode 100644 index 000000000..675558691 Binary files /dev/null and b/screenshotsToCompare9/StartTest_smokeTestStart-46-TimeBarActivity-TimeBar-2menu-click-1ToggleValues.png differ diff --git a/screenshotsToCompare9/StartTest_smokeTestStart-46-TimeBarActivity-TimeBar-2menu-click-24rotateXAxislabels.png b/screenshotsToCompare9/StartTest_smokeTestStart-46-TimeBarActivity-TimeBar-2menu-click-24rotateXAxislabels.png new file mode 100644 index 000000000..77b6f2cc1 Binary files /dev/null and b/screenshotsToCompare9/StartTest_smokeTestStart-46-TimeBarActivity-TimeBar-2menu-click-24rotateXAxislabels.png differ diff --git a/screenshotsToCompare9/StartTest_smokeTestStart-46-TimeBarActivity-TimeBar-2menu-click-4ToggleIcons.png b/screenshotsToCompare9/StartTest_smokeTestStart-46-TimeBarActivity-TimeBar-2menu-click-4ToggleIcons.png new file mode 100644 index 000000000..feb6754a9 Binary files /dev/null and b/screenshotsToCompare9/StartTest_smokeTestStart-46-TimeBarActivity-TimeBar-2menu-click-4ToggleIcons.png differ diff --git a/screenshotsToCompare9/StartTest_smokeTestStart-46-TimeBarActivity-TimeBar-2menu-click-5ToggleHighlight.png b/screenshotsToCompare9/StartTest_smokeTestStart-46-TimeBarActivity-TimeBar-2menu-click-5ToggleHighlight.png new file mode 100644 index 000000000..feb6754a9 Binary files /dev/null and b/screenshotsToCompare9/StartTest_smokeTestStart-46-TimeBarActivity-TimeBar-2menu-click-5ToggleHighlight.png differ diff --git a/screenshotsToCompare9/StartTest_smokeTestStart-46-TimeBarActivity-TimeBar-2menu-click-6TogglePinchZoom.png b/screenshotsToCompare9/StartTest_smokeTestStart-46-TimeBarActivity-TimeBar-2menu-click-6TogglePinchZoom.png new file mode 100644 index 000000000..77b6f2cc1 Binary files /dev/null and b/screenshotsToCompare9/StartTest_smokeTestStart-46-TimeBarActivity-TimeBar-2menu-click-6TogglePinchZoom.png differ diff --git a/screenshotsToCompare9/StartTest_smokeTestStart-46-TimeBarActivity-TimeBar-2menu-click-7ToggleAutoScale.png b/screenshotsToCompare9/StartTest_smokeTestStart-46-TimeBarActivity-TimeBar-2menu-click-7ToggleAutoScale.png new file mode 100644 index 000000000..77b6f2cc1 Binary files /dev/null and b/screenshotsToCompare9/StartTest_smokeTestStart-46-TimeBarActivity-TimeBar-2menu-click-7ToggleAutoScale.png differ