diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 648410d1e..a7f24367f 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/GanttUtils.kt b/app/src/main/kotlin/info/appdev/chartexample/GanttUtils.kt new file mode 100644 index 000000000..2a83eea08 --- /dev/null +++ b/app/src/main/kotlin/info/appdev/chartexample/GanttUtils.kt @@ -0,0 +1,50 @@ +package info.appdev.chartexample + +import info.appdev.charting.data.BarEntry + +/** + * Utility class for creating time interval entries for Gantt-style charts. + * Provides helper methods to create BarEntry objects with time interval data. + */ +object GanttUtils { + /** + * Create a time interval entry for a single task. + * + * @param taskIndex Y-axis position (task row) + * @param startTime Start time value + * @param duration Duration value + * @return BarEntry configured for time interval rendering + */ + fun createTimeIntervalEntry(taskIndex: Float, startTime: Float, duration: Float): BarEntry { + return BarEntry(taskIndex, floatArrayOf(startTime, duration)) + } + + /** + * Create a time interval entry with multiple segments. + * Useful for showing multiple time ranges for a single task. + * + * @param taskIndex Y-axis position (task row) + * @param timeIntervals Array of [start1, duration1, start2, duration2, ...] + * @return BarEntry configured for time interval rendering + */ + fun createMultiSegmentEntry(taskIndex: Float, timeIntervals: FloatArray): BarEntry { + require(timeIntervals.size >= 2) { "timeIntervals must have at least 2 elements" } + return BarEntry(taskIndex, timeIntervals) + } + + /** + * Create a time interval entry with custom data. + * + * @param taskIndex Y-axis position (task row) + * @param startTime Start time value + * @param duration Duration value + * @param data Custom data object + * @return BarEntry configured for time interval rendering with data + */ + fun createTimeIntervalEntry( + taskIndex: Float, startTime: Float, + duration: Float, data: Any? + ): BarEntry { + return BarEntry(taskIndex, floatArrayOf(startTime, duration), data) + } +} \ No newline at end of file diff --git a/app/src/main/kotlin/info/appdev/chartexample/TimeIntervalBarChartActivity.kt b/app/src/main/kotlin/info/appdev/chartexample/TimeIntervalBarChartActivity.kt new file mode 100644 index 000000000..dcd3950ae --- /dev/null +++ b/app/src/main/kotlin/info/appdev/chartexample/TimeIntervalBarChartActivity.kt @@ -0,0 +1,80 @@ +package info.appdev.chartexample + +import android.graphics.Color +import android.os.Bundle +import android.widget.SeekBar +import android.widget.SeekBar.OnSeekBarChangeListener +import info.appdev.chartexample.databinding.ActivityHorizontalbarchartBinding +import info.appdev.chartexample.notimportant.DemoBase +import info.appdev.charting.components.YAxis +import info.appdev.charting.data.BarData +import info.appdev.charting.data.BarDataSet +import info.appdev.charting.data.BarEntry +import info.appdev.charting.data.Entry +import info.appdev.charting.highlight.Highlight +import info.appdev.charting.listener.OnChartValueSelectedListener +import info.appdev.chartexample.GanttUtils + +/** + * using HorizontalBarChart for Gantt-style time interval visualization. + * Shows how to display tasks as horizontal bars with start time and duration. + */ +class TimeIntervalBarChartActivity : DemoBase(), OnSeekBarChangeListener, OnChartValueSelectedListener { + + private lateinit var binding: ActivityHorizontalbarchartBinding + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = ActivityHorizontalbarchartBinding.inflate(layoutInflater) + setContentView(binding.root) + + // Create sample tasks with time intervals + val entries: MutableList = ArrayList() + + entries.add(GanttUtils.createMultiSegmentEntry(-1f, floatArrayOf(-50f, -20f, 20f, 50f))) + // starts at 0, duration 100 + entries.add(GanttUtils.createTimeIntervalEntry(0f, 0f, 100f)) + // starts at 50, duration 150 + entries.add(GanttUtils.createTimeIntervalEntry(1f, 50f, 150f)) + // starts at 150, duration 100 + entries.add(GanttUtils.createTimeIntervalEntry(2f, 150f, 100f)) + + // Create dataset with time interval data + val dataSet = BarDataSet(entries, "Tasks") + dataSet.setColors( + Color.GREEN, + Color.BLUE, + Color.YELLOW + ) + dataSet.barBorderWidth = 1f + dataSet.barBorderColor = Color.BLACK + + // Create and set data + val barData = BarData(dataSet) + barData.barWidth = 0.8f + binding.chart1.data = barData + + // Configure chart + binding.chart1.setFitBars(true) + binding.chart1.isDrawValueAboveBar = true + binding.chart1.xAxis.setDrawLabels(true) + + val yl = binding.chart1.axisLeft + yl.setPosition(YAxis.YAxisLabelPosition.OUTSIDE_CHART) + + // Refresh + binding.chart1.invalidate() + } + + override fun saveToGallery() = Unit + + override fun onProgressChanged(p0: SeekBar?, p1: Int, p2: Boolean) = Unit + + override fun onStartTrackingTouch(p0: SeekBar?) = Unit + + override fun onStopTrackingTouch(p0: SeekBar?) = Unit + + override fun onValueSelected(entry: Entry, highlight: Highlight) = Unit + + override fun onNothingSelected() = 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 35572d42a..53e70fbc0 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.TimeIntervalBarChartActivity 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("Timeinterval", "Grantt chart", TimeIntervalBarChartActivity::class.java)) } } } diff --git a/screenshotsToCompare9/StartTest_smokeTestStart-46-TimeIntervalBarChartActivity-Timeinterval-1SampleClick.png b/screenshotsToCompare9/StartTest_smokeTestStart-46-TimeIntervalBarChartActivity-Timeinterval-1SampleClick.png new file mode 100644 index 000000000..e556fb1bd Binary files /dev/null and b/screenshotsToCompare9/StartTest_smokeTestStart-46-TimeIntervalBarChartActivity-Timeinterval-1SampleClick.png differ diff --git a/screenshotsToCompare9/StartTest_smokeTestStart-46-TimeIntervalBarChartActivity-Timeinterval-click.png b/screenshotsToCompare9/StartTest_smokeTestStart-46-TimeIntervalBarChartActivity-Timeinterval-click.png new file mode 100644 index 000000000..e556fb1bd Binary files /dev/null and b/screenshotsToCompare9/StartTest_smokeTestStart-46-TimeIntervalBarChartActivity-Timeinterval-click.png differ diff --git a/screenshotsToCompare9/StartTest_smokeTestStart-46-TimeIntervalBarChartActivity-Timeinterval-click2020.png b/screenshotsToCompare9/StartTest_smokeTestStart-46-TimeIntervalBarChartActivity-Timeinterval-click2020.png new file mode 100644 index 000000000..e556fb1bd Binary files /dev/null and b/screenshotsToCompare9/StartTest_smokeTestStart-46-TimeIntervalBarChartActivity-Timeinterval-click2020.png differ diff --git a/screenshotsToCompare9/StartTest_smokeTestStart-46-TimeIntervalBarChartActivity-Timeinterval-click7070.png b/screenshotsToCompare9/StartTest_smokeTestStart-46-TimeIntervalBarChartActivity-Timeinterval-click7070.png new file mode 100644 index 000000000..e556fb1bd Binary files /dev/null and b/screenshotsToCompare9/StartTest_smokeTestStart-46-TimeIntervalBarChartActivity-Timeinterval-click7070.png differ