mirror of
https://github.com/dzeiocom/charts.git
synced 2025-04-22 10:42:09 +00:00
feat: Make sample more customizable (#43)
This commit is contained in:
parent
1a812acb9e
commit
3df7541505
@ -58,7 +58,7 @@ chart.refresh()
|
||||
<img width="40%" src=".github/usage-example.jpg" />
|
||||
</p>
|
||||
|
||||
_note: Every charts used above used a helper function to have Material 3 colors [See MainFragment.kt the materialTheme function](./sample/src/main/java/com/dzeio/chartstest/ui/MainFragment.kt)_
|
||||
_note: Every charts used above used a helper function to have Material 3 colors [See the MaterialUtils.kt class](sample/src/main/java/com/dzeio/chartsapp/utils/MaterialUtils.kt)_
|
||||
|
||||
## Build
|
||||
|
||||
|
@ -5,6 +5,9 @@ buildscript {
|
||||
}
|
||||
dependencies {
|
||||
classpath("com.android.tools.build:gradle:7.4.1")
|
||||
|
||||
// Safe Navigation
|
||||
classpath("androidx.navigation:navigation-safe-args-gradle-plugin:2.5.3")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,7 @@ class ChartView @JvmOverloads constructor(context: Context?, attrs: AttributeSet
|
||||
View(context, attrs), ChartViewInterface {
|
||||
|
||||
private companion object {
|
||||
const val TAG = "Charts/ChartView"
|
||||
const val TAG = "ChartView"
|
||||
}
|
||||
|
||||
override val animator: Animation = Animation()
|
||||
@ -97,6 +97,10 @@ class ChartView @JvmOverloads constructor(context: Context?, attrs: AttributeSet
|
||||
|
||||
refresh()
|
||||
}
|
||||
setOnToggleScroll {
|
||||
// note: true == no scroll
|
||||
parent?.requestDisallowInterceptTouchEvent(!it && (yAxis.scrollEnabled || xAxis.scrollEnabled))
|
||||
}
|
||||
setOnChartClick { x, y ->
|
||||
if (getDataset().isEmpty()) {
|
||||
return@setOnChartClick
|
||||
@ -161,15 +165,11 @@ class ChartView @JvmOverloads constructor(context: Context?, attrs: AttributeSet
|
||||
|
||||
// invalidate the view
|
||||
invalidate()
|
||||
// removeCallbacks(animator)
|
||||
// post(animator)
|
||||
}
|
||||
|
||||
private var lastRun = runUpdates
|
||||
|
||||
override fun onDraw(canvas: Canvas) {
|
||||
// don't draw anything if everything is empty
|
||||
if (!runUpdates && lastRun == runUpdates && series.isEmpty() || series.maxOf { it.entries.size } == 0) {
|
||||
if (!runUpdates || series.isEmpty() || series.maxOf { it.entries.size } == 0) {
|
||||
super.onDraw(canvas)
|
||||
return
|
||||
}
|
||||
|
@ -92,18 +92,14 @@ class XAxis(
|
||||
|
||||
var maxHeight = 0f
|
||||
|
||||
val graphIncrement = space.width() / (labelCount - 1)
|
||||
val valueIncrement = getDataWidth() / (labelCount - 1)
|
||||
val valueIncrement = getDataWidth() / (labelCount - 1).coerceAtLeast(1)
|
||||
for (index in 0 until labelCount) {
|
||||
val text = onValueFormat(x + valueIncrement * index)
|
||||
textPaint.getTextBounds(text, 0, text.length, rect)
|
||||
getPositionOnRect(valueIncrement, space)
|
||||
maxHeight = maxHeight.coerceAtLeast(rect.height().toFloat() + 1)
|
||||
|
||||
var xPos = space.left + graphIncrement * index
|
||||
|
||||
if (xPos + rect.width() > space.right) {
|
||||
xPos = space.right - rect.width()
|
||||
}
|
||||
val xPos = getPositionOnRect(x + valueIncrement * index, space).toFloat()
|
||||
|
||||
canvas.drawText(
|
||||
text,
|
||||
@ -134,8 +130,8 @@ class XAxis(
|
||||
.coerceIn(1.0, drawableSpace.width().toDouble())
|
||||
|
||||
// handle grouped series
|
||||
if (view.type == ChartType.GROUPED) {
|
||||
return result / view.series.size - spacing / 2 * (view.series.size - 1)
|
||||
if (view.type == ChartType.GROUPED && view.series.size > 1) {
|
||||
return ((result - (spacing / 2 * view.series.size)) / view.series.size).coerceAtLeast(1.0)
|
||||
}
|
||||
|
||||
return result
|
||||
@ -145,5 +141,4 @@ class XAxis(
|
||||
// TODO: handle the auto dataWidth better (still not sure it is good enough)
|
||||
return dataWidth ?: (getXMax() - getXMin() + 1)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -162,7 +162,7 @@ class YAxis(
|
||||
val max = getYMax() - min
|
||||
var maxWidth = 0f
|
||||
|
||||
val valueIncrement = max / (labelCount - 1)
|
||||
val valueIncrement = max / (labelCount - 1).coerceAtLeast(1)
|
||||
for (index in 0 until labelCount) {
|
||||
val value = min + (valueIncrement * index)
|
||||
|
||||
|
@ -73,6 +73,11 @@ class Annotation(
|
||||
|
||||
val xCenter = view.xAxis.getEntryWidth(space) / 2.0 + x
|
||||
|
||||
if (xCenter < space.left || xCenter > space.right) {
|
||||
entry = null
|
||||
return
|
||||
}
|
||||
|
||||
val xText = annotationSubTitleFormat.invoke(entry!!)
|
||||
val yText = annotationTitleFormat.invoke(entry!!)
|
||||
|
||||
|
@ -1,160 +0,0 @@
|
||||
package com.dzeio.charts.series
|
||||
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Paint
|
||||
import android.graphics.Rect
|
||||
import android.graphics.RectF
|
||||
import android.util.Log
|
||||
import kotlin.math.max
|
||||
|
||||
class BarSerie : SerieAbstract() {
|
||||
|
||||
companion object {
|
||||
const val TAG = "DzeioCharts/BarSerie"
|
||||
}
|
||||
|
||||
var spacing: Float = 8f
|
||||
|
||||
/**
|
||||
* Values displayed on the grapd
|
||||
*/
|
||||
var displayedDatas = arrayListOf<Float>()
|
||||
|
||||
/**
|
||||
* Target values
|
||||
*/
|
||||
var targetDatas = arrayListOf<Float>()
|
||||
|
||||
var targetPercentList = arrayListOf<Float>()
|
||||
var percentList = arrayListOf<Float>()
|
||||
|
||||
var previousRefresh = 0
|
||||
|
||||
private var fgPaint: Paint = Paint().apply {
|
||||
isAntiAlias = true
|
||||
}
|
||||
|
||||
private val r = Rect()
|
||||
|
||||
override fun onUpdate(): Boolean {
|
||||
var needNewFrame = false
|
||||
for (i in targetPercentList.indices) {
|
||||
val value = view.animation.updateValue(
|
||||
1f,
|
||||
targetPercentList[i],
|
||||
percentList[i],
|
||||
0f,
|
||||
0.00f
|
||||
)
|
||||
|
||||
if (value != percentList[i]) {
|
||||
needNewFrame = true
|
||||
percentList[i] = value
|
||||
}
|
||||
}
|
||||
return needNewFrame
|
||||
}
|
||||
|
||||
override fun prepareData() {
|
||||
val max: Float = if (view.yAxis.max != null) view.yAxis.max!! else {
|
||||
getYMax(true)
|
||||
}
|
||||
|
||||
targetPercentList = arrayListOf()
|
||||
|
||||
// Log.d(TAG, "offset: ${view.getXOffset()}, displayed: ${view.getDisplayedEntries()}")
|
||||
for (item in getDisplayedEntries()) {
|
||||
// // // Process bottom texts
|
||||
// val text = view.xAxis.onValueFormat(item.x)
|
||||
// bottomTexts.add(text)
|
||||
//
|
||||
// // get Text boundaries
|
||||
// view.xAxis.labels.build().getTextBounds(text, 0, text.length, r)
|
||||
//
|
||||
// // get height of text
|
||||
// if (bottomTextHeight < r.height()) {
|
||||
// bottomTextHeight = r.height()
|
||||
// }
|
||||
//
|
||||
// // get text descent
|
||||
// val descent = abs(r.bottom)
|
||||
// if (bottomTextDescent < descent) {
|
||||
// bottomTextDescent = descent
|
||||
// }
|
||||
|
||||
// process values
|
||||
// Log.d(TAG, item.y.toString())
|
||||
|
||||
// add to animations the values
|
||||
targetPercentList.add(1 - item.y / max)
|
||||
}
|
||||
|
||||
// post list
|
||||
val offset = view.getXOffset()
|
||||
val movement = offset - previousRefresh
|
||||
Log.d(TAG, "$offset - $previousRefresh = $movement")
|
||||
if (movement != 0) {
|
||||
previousRefresh = offset
|
||||
}
|
||||
// if (movement != 0) {
|
||||
// Log.d(TAG, movement.toString())
|
||||
// }
|
||||
if (movement >= 1) {
|
||||
percentList = percentList.subList(1, percentList.size).toCollection(ArrayList())
|
||||
percentList.add(1f)
|
||||
} else if (movement <= -1) {
|
||||
percentList = percentList.subList(0, percentList.size - 1).toCollection(ArrayList())
|
||||
percentList.add(0, 1f)
|
||||
}
|
||||
|
||||
if (percentList.isEmpty() || percentList.size < targetPercentList.size) {
|
||||
val temp = targetPercentList.size - percentList.size
|
||||
for (i in 0 until temp) {
|
||||
percentList.add(1f)
|
||||
}
|
||||
} else if (percentList.size > targetPercentList.size) {
|
||||
val temp = percentList.size - targetPercentList.size
|
||||
for (i in 0 until temp) {
|
||||
percentList.removeAt(percentList.size - 1)
|
||||
}
|
||||
}
|
||||
|
||||
fgPaint.color = view.yAxis.color
|
||||
}
|
||||
|
||||
override fun displayData(canvas: Canvas, rect: RectF) {
|
||||
val barWidth = (rect.width() - view.padding * 2) / view.getDisplayedEntries() - spacing
|
||||
|
||||
if (percentList.isNotEmpty()) {
|
||||
// draw each rectangles
|
||||
for (i in 1..percentList.size) {
|
||||
// Log.d(TAG, percentList[i - 1].toString())
|
||||
val left = rect.left + spacing * i + barWidth * (i - 1).toFloat() + view.padding
|
||||
// Log.d(TAG, "$spacing, $i, $barWidth = $left")
|
||||
val right = rect.left + (spacing + barWidth) * i.toFloat()
|
||||
val bottom = rect.top + rect.height() - view.padding
|
||||
val top = (bottom - rect.top) * percentList[i - 1] + view.padding
|
||||
|
||||
// create rounded rect
|
||||
canvas.drawRoundRect(left, top, right, bottom, 8f, 8f, fgPaint)
|
||||
// remove the bottom corners DUH
|
||||
canvas.drawRect(left, max(top, bottom - 8f), right, bottom, fgPaint)
|
||||
val targetTop = (bottom - rect.top) * targetPercentList[i - 1]
|
||||
|
||||
val text = view.yAxis.onValueFormat(getYMax(true) - getYMax(true) * targetPercentList[i - 1], true)
|
||||
view.xAxis.labels.build().getTextBounds(text, 0, text.length, r)
|
||||
val doDisplayIn =
|
||||
r.width() + 10f < barWidth && bottom - targetTop > r.height() + 40f
|
||||
if (view.debug || !doDisplayIn || (doDisplayIn && bottom - top > r.height() + 40f)) {
|
||||
val y = if (doDisplayIn) top + r.height() + 20f else top - r.height()
|
||||
canvas.drawText(
|
||||
text,
|
||||
left + (right - left) / 2,
|
||||
y,
|
||||
view.xAxis.labels.build()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,14 +1,23 @@
|
||||
plugins {
|
||||
// Android Application?
|
||||
id("com.android.application")
|
||||
|
||||
// Support for kotlin in Android
|
||||
kotlin("android")
|
||||
|
||||
// Safe Navigation
|
||||
id("androidx.navigation.safeargs")
|
||||
|
||||
// keep at bottom
|
||||
kotlin("kapt")
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "com.dzeio.chartstest"
|
||||
namespace = "com.dzeio.chartsapp"
|
||||
compileSdk = 33
|
||||
|
||||
defaultConfig {
|
||||
applicationId = "com.dzeio.chartstest"
|
||||
applicationId = "com.dzeio.chartsapp"
|
||||
minSdk = 21
|
||||
targetSdk = 33
|
||||
versionCode = 1
|
||||
@ -34,6 +43,7 @@ android {
|
||||
|
||||
buildFeatures {
|
||||
viewBinding = true
|
||||
dataBinding = true
|
||||
}
|
||||
}
|
||||
|
||||
@ -42,8 +52,9 @@ dependencies {
|
||||
implementation(project(":library"))
|
||||
|
||||
// Material Design
|
||||
implementation("com.google.android.material:material:1.7.0")
|
||||
implementation("com.google.android.material:material:1.8.0")
|
||||
|
||||
// Navigation because I don't want to maintain basic transactions and shit
|
||||
implementation("androidx.navigation:navigation-fragment-ktx:2.5.3")
|
||||
implementation("androidx.navigation:navigation-ui-ktx:2.5.3")
|
||||
}
|
@ -3,7 +3,7 @@
|
||||
|
||||
<application
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:label="Dzeio Charts"
|
||||
android:theme="@style/Theme.Charts">
|
||||
<activity
|
||||
android:name=".ui.MainActivity"
|
||||
|
178
sample/src/main/java/com/dzeio/chartsapp/ui/ChartFragment.kt
Normal file
178
sample/src/main/java/com/dzeio/chartsapp/ui/ChartFragment.kt
Normal file
@ -0,0 +1,178 @@
|
||||
package com.dzeio.chartsapp.ui
|
||||
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.navigation.fragment.navArgs
|
||||
import com.dzeio.charts.ChartType
|
||||
import com.dzeio.charts.ChartViewInterface
|
||||
import com.dzeio.charts.Entry
|
||||
import com.dzeio.charts.series.BarSerie
|
||||
import com.dzeio.charts.series.LineSerie
|
||||
import com.dzeio.charts.series.SerieInterface
|
||||
import com.dzeio.chartsapp.databinding.FragmentChartBinding
|
||||
import com.dzeio.chartsapp.utils.MaterialUtils
|
||||
import com.dzeio.chartsapp.utils.Utils
|
||||
import kotlin.math.roundToInt
|
||||
import kotlin.random.Random
|
||||
|
||||
class ChartFragment : Fragment() {
|
||||
private var _binding: FragmentChartBinding? = null
|
||||
|
||||
private val args: ChartFragmentArgs by navArgs()
|
||||
|
||||
private var numberOfValues = 5
|
||||
|
||||
private lateinit var chart: ChartViewInterface
|
||||
private val binding: FragmentChartBinding get() = _binding!!
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
_binding = FragmentChartBinding.inflate(inflater, container, false)
|
||||
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
chart = binding.chart
|
||||
addSerie()
|
||||
|
||||
MaterialUtils.materielTheme(chart, requireView())
|
||||
|
||||
chart.refresh()
|
||||
|
||||
binding.addValue.setOnClickListener {
|
||||
chart.series.forEach {
|
||||
it.entries.add(
|
||||
Entry(
|
||||
it.entries.size.toDouble(),
|
||||
Random.nextInt(0, 100).toFloat()
|
||||
)
|
||||
)
|
||||
}
|
||||
numberOfValues++
|
||||
chart.refresh()
|
||||
}
|
||||
|
||||
binding.removeValue.setOnClickListener {
|
||||
chart.series.forEach {
|
||||
it.entries.removeLastOrNull()
|
||||
}
|
||||
numberOfValues--
|
||||
chart.refresh()
|
||||
}
|
||||
|
||||
binding.addSerie.setOnClickListener {
|
||||
addSerie()
|
||||
chart.refresh()
|
||||
}
|
||||
|
||||
binding.removeSerie.setOnClickListener {
|
||||
chart.series.removeLastOrNull()
|
||||
chart.refresh()
|
||||
}
|
||||
|
||||
binding.switchSubtype.setOnClickListener {
|
||||
when (chart.type) {
|
||||
ChartType.BASIC -> {
|
||||
chart.type = ChartType.GROUPED
|
||||
binding.switchSubtype.setText("Grouped Chart")
|
||||
}
|
||||
ChartType.GROUPED -> {
|
||||
chart.type = ChartType.STACKED
|
||||
binding.switchSubtype.setText("Stacked Chart")
|
||||
}
|
||||
else -> {
|
||||
chart.type = ChartType.BASIC
|
||||
binding.switchSubtype.setText("Basic Chart")
|
||||
}
|
||||
}
|
||||
chart.refresh()
|
||||
}
|
||||
|
||||
binding.switchAnimations.setOnCheckedChangeListener { _, isChecked ->
|
||||
chart.animator.enabled = isChecked
|
||||
}
|
||||
|
||||
binding.switchXAxis.setOnCheckedChangeListener { _, isChecked ->
|
||||
chart.xAxis.enabled = isChecked
|
||||
chart.refresh()
|
||||
}
|
||||
|
||||
binding.switchYAxis.setOnCheckedChangeListener { _, isChecked ->
|
||||
chart.yAxis.enabled = isChecked
|
||||
chart.refresh()
|
||||
}
|
||||
|
||||
binding.sliderXAxis.addOnChangeListener { _, value, _ ->
|
||||
chart.xAxis.labelCount = value.roundToInt()
|
||||
chart.refresh()
|
||||
}
|
||||
|
||||
binding.sliderYAxis.addOnChangeListener { _, value, _ ->
|
||||
chart.yAxis.labelCount = value.roundToInt()
|
||||
chart.refresh()
|
||||
}
|
||||
|
||||
binding.switchXAxisScrollable.setOnCheckedChangeListener { _, isChecked ->
|
||||
chart.xAxis.scrollEnabled = isChecked
|
||||
if (isChecked) {
|
||||
chart.xAxis.dataWidth = binding.sliderXAxisScroll.value.toDouble()
|
||||
binding.sliderXAxisScroll.visibility = View.VISIBLE
|
||||
} else {
|
||||
chart.xAxis.dataWidth = null
|
||||
chart.xAxis.x = 0.0
|
||||
binding.sliderXAxisScroll.visibility = View.GONE
|
||||
}
|
||||
chart.refresh()
|
||||
}
|
||||
|
||||
binding.sliderXAxisScroll.visibility = View.GONE
|
||||
binding.sliderXAxisScroll.addOnChangeListener { _, value, _ ->
|
||||
if (chart.xAxis.dataWidth != null) {
|
||||
chart.xAxis.dataWidth = value.toDouble()
|
||||
chart.refresh()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var lastGenerated = 0
|
||||
private fun addSerie(): SerieInterface {
|
||||
val toGet = if (args.chartType == null) {
|
||||
if (lastGenerated == 0) {
|
||||
"barchart"
|
||||
} else {
|
||||
"linechart"
|
||||
}
|
||||
} else {
|
||||
args.chartType
|
||||
}
|
||||
if (lastGenerated++ >= 1) {
|
||||
lastGenerated = 0
|
||||
}
|
||||
val serie = if (toGet === "barchart") {
|
||||
BarSerie(chart).apply {
|
||||
barPaint.color = randomColor()
|
||||
}
|
||||
} else {
|
||||
LineSerie(chart).apply {
|
||||
linePaint.color = randomColor()
|
||||
}
|
||||
}
|
||||
serie.entries = Utils.generateRandomDataset(numberOfValues)
|
||||
return serie
|
||||
}
|
||||
|
||||
private fun randomColor(): Int {
|
||||
return Color.argb(
|
||||
255,
|
||||
Random.nextInt(),
|
||||
Random.nextInt(),
|
||||
Random.nextInt()
|
||||
)
|
||||
}
|
||||
}
|
97
sample/src/main/java/com/dzeio/chartsapp/ui/MainActivity.kt
Normal file
97
sample/src/main/java/com/dzeio/chartsapp/ui/MainActivity.kt
Normal file
@ -0,0 +1,97 @@
|
||||
package com.dzeio.chartsapp.ui
|
||||
|
||||
import android.content.res.Configuration
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.view.WindowManager
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.WindowCompat
|
||||
import androidx.core.view.updatePadding
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.fragment.NavHostFragment
|
||||
import androidx.navigation.ui.AppBarConfiguration
|
||||
import androidx.navigation.ui.navigateUp
|
||||
import androidx.navigation.ui.setupActionBarWithNavController
|
||||
import com.dzeio.chartsapp.R
|
||||
import com.dzeio.chartsapp.databinding.ActivityMainBinding
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
|
||||
private lateinit var binding: ActivityMainBinding
|
||||
|
||||
private lateinit var appBarConfiguration: AppBarConfiguration
|
||||
|
||||
private lateinit var navController: NavController
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
binding = ActivityMainBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
setSupportActionBar(binding.toolbar)
|
||||
|
||||
// Comportement chelou API 28-
|
||||
// Comportement normal 31+
|
||||
|
||||
// do not do the cool status/navigation bars for API 29 & 30
|
||||
if (Build.VERSION.SDK_INT != Build.VERSION_CODES.R && Build.VERSION.SDK_INT != Build.VERSION_CODES.Q) {
|
||||
// allow to put the content behind the status bar & Navigation bar (one of them at least lul)
|
||||
// ALSO: make the status/navigation bars semi-transparent
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION)
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
|
||||
|
||||
// Make the color of the navigation bar semi-transparent
|
||||
// window.navigationBarColor = Color.TRANSPARENT
|
||||
// Make the color of the status bar transparent
|
||||
// window.statusBarColor = Color.TRANSPARENT
|
||||
// Apply the previous changes
|
||||
// window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
|
||||
|
||||
// Update toolbar height with the statusbar size included
|
||||
// ALSO: make both the status/navigation bars transparent (WHYYYYYYY)
|
||||
val toolbarHeight = binding.toolbar.layoutParams.height
|
||||
window.decorView.setOnApplyWindowInsetsListener { _, insets ->
|
||||
val statusBarSize = insets.systemWindowInsetTop
|
||||
// Add padding to the toolbar (YaY I know how something works)
|
||||
binding.toolbar.updatePadding(top = statusBarSize)
|
||||
binding.toolbar.layoutParams.height = toolbarHeight + statusBarSize
|
||||
return@setOnApplyWindowInsetsListener insets
|
||||
}
|
||||
|
||||
// normally makes sure icons are at the correct color but idk if it works
|
||||
when (this.resources.configuration.uiMode.and(Configuration.UI_MODE_NIGHT_MASK)) {
|
||||
Configuration.UI_MODE_NIGHT_YES -> {
|
||||
WindowCompat.getInsetsController(window, window.decorView).apply {
|
||||
// force to display the bars in light color
|
||||
isAppearanceLightNavigationBars = true
|
||||
isAppearanceLightStatusBars = false // WHY
|
||||
}
|
||||
}
|
||||
Configuration.UI_MODE_NIGHT_NO, Configuration.UI_MODE_NIGHT_UNDEFINED -> {
|
||||
WindowCompat.getInsetsController(window, window.decorView).apply {
|
||||
// force to display the bars in dark color
|
||||
isAppearanceLightNavigationBars = false
|
||||
isAppearanceLightStatusBars = true // WHY
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val navHostFragment =
|
||||
supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
|
||||
|
||||
navController = navHostFragment.navController
|
||||
|
||||
appBarConfiguration = AppBarConfiguration(
|
||||
setOf(
|
||||
R.id.main_fragment
|
||||
)
|
||||
)
|
||||
|
||||
setupActionBarWithNavController(navController, appBarConfiguration)
|
||||
}
|
||||
|
||||
override fun onSupportNavigateUp(): Boolean =
|
||||
navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
|
||||
}
|
93
sample/src/main/java/com/dzeio/chartsapp/ui/MainFragment.kt
Normal file
93
sample/src/main/java/com/dzeio/chartsapp/ui/MainFragment.kt
Normal file
@ -0,0 +1,93 @@
|
||||
package com.dzeio.chartsapp.ui
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.dzeio.charts.series.BarSerie
|
||||
import com.dzeio.charts.series.LineSerie
|
||||
import com.dzeio.chartsapp.databinding.FragmentMainBinding
|
||||
import com.dzeio.chartsapp.utils.MaterialUtils
|
||||
import com.dzeio.chartsapp.utils.Utils
|
||||
|
||||
class MainFragment : Fragment() {
|
||||
private var _binding: FragmentMainBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
private val months = arrayListOf(
|
||||
"Jan",
|
||||
"Feb",
|
||||
"Mar",
|
||||
"Apr",
|
||||
"May",
|
||||
"Jun",
|
||||
"Jul",
|
||||
"Aug",
|
||||
"Sep",
|
||||
"Oct",
|
||||
"Nov",
|
||||
"Dec"
|
||||
)
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
_binding = FragmentMainBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
binding.gotoBarchart.setOnClickListener {
|
||||
findNavController().navigate(
|
||||
MainFragmentDirections.actionMainFragmentToChartFragment("barchart")
|
||||
)
|
||||
}
|
||||
|
||||
binding.gotoLinechart.setOnClickListener {
|
||||
findNavController().navigate(
|
||||
MainFragmentDirections.actionMainFragmentToChartFragment("linechart")
|
||||
)
|
||||
}
|
||||
|
||||
binding.gotoBarLineChart.setOnClickListener {
|
||||
findNavController().navigate(
|
||||
MainFragmentDirections.actionMainFragmentToChartFragment(null)
|
||||
)
|
||||
}
|
||||
|
||||
binding.barchart.apply {
|
||||
BarSerie(this).apply {
|
||||
entries = Utils.generateRandomDataset(5)
|
||||
}
|
||||
MaterialUtils.materielTheme(this, requireView())
|
||||
}
|
||||
|
||||
binding.linechart.apply {
|
||||
LineSerie(this).apply {
|
||||
entries = Utils.generateRandomDataset(5)
|
||||
}
|
||||
MaterialUtils.materielTheme(this, requireView())
|
||||
}
|
||||
|
||||
binding.bothchart.apply {
|
||||
BarSerie(this).apply {
|
||||
entries = Utils.generateRandomDataset(5)
|
||||
}
|
||||
LineSerie(this).apply {
|
||||
entries = Utils.generateRandomDataset(5)
|
||||
}
|
||||
MaterialUtils.materielTheme(this, requireView())
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
package com.dzeio.chartsapp.utils
|
||||
|
||||
import android.view.View
|
||||
import com.dzeio.charts.ChartViewInterface
|
||||
import com.dzeio.charts.series.BarSerie
|
||||
import com.dzeio.charts.series.LineSerie
|
||||
import com.google.android.material.color.MaterialColors
|
||||
|
||||
object MaterialUtils {
|
||||
fun materielTheme(chart: ChartViewInterface, view: View) {
|
||||
chart.yAxis.apply {
|
||||
textLabel.color =
|
||||
MaterialColors.getColor(view, com.google.android.material.R.attr.colorOnPrimaryContainer)
|
||||
linePaint.color =
|
||||
MaterialColors.getColor(view, com.google.android.material.R.attr.colorOnPrimaryContainer)
|
||||
goalLinePaint.color =
|
||||
MaterialColors.getColor(view, com.google.android.material.R.attr.colorError)
|
||||
}
|
||||
|
||||
chart.xAxis.textPaint.color =
|
||||
MaterialColors.getColor(view, com.google.android.material.R.attr.colorOnPrimaryContainer)
|
||||
chart.annotator.apply {
|
||||
backgroundPaint.color = MaterialColors.getColor(
|
||||
view,
|
||||
com.google.android.material.R.attr.colorBackgroundFloating
|
||||
)
|
||||
titlePaint.color = MaterialColors.getColor(
|
||||
view,
|
||||
com.google.android.material.R.attr.colorOnPrimaryContainer
|
||||
)
|
||||
subTitlePaint.color = MaterialColors.getColor(
|
||||
view,
|
||||
com.google.android.material.R.attr.colorOnPrimaryContainer
|
||||
)
|
||||
}
|
||||
|
||||
for (serie in chart.series) {
|
||||
if (serie is BarSerie) {
|
||||
serie.apply {
|
||||
barPaint.color =
|
||||
MaterialColors.getColor(view, com.google.android.material.R.attr.colorPrimary)
|
||||
textPaint.color =
|
||||
MaterialColors.getColor(view, com.google.android.material.R.attr.colorOnPrimary)
|
||||
textExternalPaint.color =
|
||||
MaterialColors.getColor(view, com.google.android.material.R.attr.colorPrimary)
|
||||
}
|
||||
} else if (serie is LineSerie) {
|
||||
serie.apply {
|
||||
linePaint.color =
|
||||
MaterialColors.getColor(view, com.google.android.material.R.attr.colorPrimary)
|
||||
textPaint.color =
|
||||
MaterialColors.getColor(view, com.google.android.material.R.attr.colorOnPrimary)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
19
sample/src/main/java/com/dzeio/chartsapp/utils/Utils.kt
Normal file
19
sample/src/main/java/com/dzeio/chartsapp/utils/Utils.kt
Normal file
@ -0,0 +1,19 @@
|
||||
package com.dzeio.chartsapp.utils
|
||||
|
||||
import com.dzeio.charts.Entry
|
||||
import kotlin.random.Random.Default.nextInt
|
||||
|
||||
object Utils {
|
||||
fun generateRandomDataset(size: Int = 100, min: Int = 0, max: Int = 100, xStep: Int = 1): ArrayList<Entry> {
|
||||
val dataset: ArrayList<Entry> = ArrayList()
|
||||
for (i in 0 until size) {
|
||||
dataset.add(
|
||||
Entry(
|
||||
(i * xStep).toDouble(),
|
||||
nextInt(min, max).toFloat()
|
||||
)
|
||||
)
|
||||
}
|
||||
return dataset
|
||||
}
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
package com.dzeio.chartstest.ui
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.WindowCompat
|
||||
import com.dzeio.chartstest.databinding.ActivityMainBinding
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
|
||||
private lateinit var binding: ActivityMainBinding
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
WindowCompat.setDecorFitsSystemWindows(window, false)
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
binding = ActivityMainBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
}
|
||||
}
|
@ -1,273 +0,0 @@
|
||||
package com.dzeio.chartstest.ui
|
||||
|
||||
import android.graphics.Color
|
||||
import android.graphics.Paint
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.dzeio.charts.ChartType
|
||||
import com.dzeio.charts.ChartView
|
||||
import com.dzeio.charts.Entry
|
||||
import com.dzeio.charts.axis.Line
|
||||
import com.dzeio.charts.series.BarSerie
|
||||
import com.dzeio.charts.series.LineSerie
|
||||
import com.dzeio.chartstest.databinding.FragmentMainBinding
|
||||
import com.google.android.material.color.MaterialColors
|
||||
import kotlin.math.roundToInt
|
||||
import kotlin.random.Random
|
||||
|
||||
class MainFragment : Fragment() {
|
||||
private var _binding: FragmentMainBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
_binding = FragmentMainBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
binding.chartGrouped.apply {
|
||||
// setup the Serie
|
||||
val serie1 = BarSerie(this)
|
||||
val serie2 = BarSerie(this)
|
||||
|
||||
animator.duration = 750
|
||||
|
||||
// transform the chart into a grouped chart
|
||||
type = ChartType.GROUPED
|
||||
yAxis.setYMin(0f)
|
||||
|
||||
// utils function to use Material3 auto colors
|
||||
materielTheme(this, requireView())
|
||||
serie2.barPaint.color = Color.RED
|
||||
|
||||
// give the serie it's entries
|
||||
serie1.entries = generateRandomDataset(5)
|
||||
serie2.entries = generateRandomDataset(5)
|
||||
|
||||
// refresh the Chart
|
||||
refresh()
|
||||
}
|
||||
|
||||
binding.chartStacked.apply {
|
||||
// setup the Serie
|
||||
val serie1 = BarSerie(this)
|
||||
val serie2 = BarSerie(this)
|
||||
|
||||
animator.duration = 750
|
||||
|
||||
// transform the chart into a grouped chart
|
||||
type = ChartType.STACKED
|
||||
yAxis.setYMin(0f)
|
||||
|
||||
// utils function to use Material3 auto colors
|
||||
materielTheme(this, requireView())
|
||||
serie2.barPaint.color = Color.RED
|
||||
|
||||
// give the serie it's entries
|
||||
serie1.entries = generateRandomDataset(10)
|
||||
serie2.entries = generateRandomDataset(10)
|
||||
|
||||
// refresh the Chart
|
||||
refresh()
|
||||
}
|
||||
|
||||
binding.chartLine.apply {
|
||||
// setup the Serie
|
||||
val serie = LineSerie(this)
|
||||
|
||||
// utils function to use Material3 auto colors
|
||||
materielTheme(this, requireView())
|
||||
|
||||
// give the serie its entries
|
||||
serie.entries = generateRandomDataset(10)
|
||||
|
||||
// refresh the Chart
|
||||
refresh()
|
||||
}
|
||||
|
||||
binding.chartBar.apply {
|
||||
// setup the Serie
|
||||
val serie = BarSerie(this)
|
||||
yAxis.setYMin(0f)
|
||||
|
||||
// utils function to use Material3 auto colors
|
||||
materielTheme(this, requireView())
|
||||
|
||||
// give the serie its entries
|
||||
serie.entries = generateRandomDataset(10)
|
||||
|
||||
// refresh the Chart
|
||||
refresh()
|
||||
}
|
||||
|
||||
binding.chartCustomization.apply {
|
||||
// setup the Series
|
||||
val serie1 = BarSerie(this)
|
||||
val serie2 = LineSerie(this)
|
||||
|
||||
// utils function to use Material3 auto colors
|
||||
materielTheme(this, requireView())
|
||||
|
||||
// give the series their entries
|
||||
serie2.entries = generateRandomDataset(20, -50, 50)
|
||||
serie1.entries = generateRandomDataset(20, -50, 50).apply {
|
||||
for (idx in 0 until size) {
|
||||
val compared = serie2.entries[idx]
|
||||
val toCompare = this[idx]
|
||||
if (compared.y > toCompare.y) {
|
||||
toCompare.color = Color.RED
|
||||
} else {
|
||||
toCompare.color = Color.GREEN
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// serie1.textExternalPaint = Color.WHITE
|
||||
|
||||
// make the lineSerie red
|
||||
serie2.linePaint.color = Color.WHITE
|
||||
|
||||
// strokeWidth also control the points width
|
||||
serie2.linePaint.strokeWidth = 10f
|
||||
|
||||
yAxis.apply {
|
||||
// Enable vertical scrolling
|
||||
scrollEnabled = true
|
||||
|
||||
// change the number of labels
|
||||
labelCount = 11
|
||||
|
||||
// change how labels are displayed
|
||||
onValueFormat = { "${it.roundToInt()}g" }
|
||||
|
||||
// change labels colors
|
||||
textLabel.color = Color.WHITE
|
||||
|
||||
// change line color
|
||||
linePaint.color = Color.WHITE
|
||||
|
||||
// Add horizontal Lines
|
||||
val paint: Paint = Paint(yAxis.linePaint).apply {
|
||||
strokeWidth = 8f
|
||||
}
|
||||
addLine(10f, Line(true, paint))
|
||||
addLine(-10f, Line(true, paint))
|
||||
|
||||
// change the min/max high
|
||||
setYMin(-20f)
|
||||
setYMax(20f)
|
||||
}
|
||||
|
||||
xAxis.apply {
|
||||
// Enable horizontal scrolling
|
||||
scrollEnabled = true
|
||||
|
||||
// set the width of the datas
|
||||
dataWidth = 10.0
|
||||
|
||||
// change the number of labels displayed
|
||||
labelCount = 5
|
||||
|
||||
// change the spacing between values (it can be overriden if size to to small)
|
||||
spacing = 8.0
|
||||
|
||||
// set the offset in data (use with [dataWidth])
|
||||
x = 5.0
|
||||
}
|
||||
|
||||
// refresh the Chart
|
||||
refresh()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a random dataset
|
||||
*/
|
||||
private fun generateRandomDataset(size: Int = 100, min: Int = 0, max: Int = 100): ArrayList<Entry> {
|
||||
val dataset: ArrayList<Entry> = arrayListOf()
|
||||
|
||||
for (i in 0 until size) {
|
||||
dataset.add(
|
||||
Entry(
|
||||
i.toDouble(),
|
||||
Random.nextInt(min, max).toFloat()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
return dataset
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply Material3 theme to a [ChartView]
|
||||
*/
|
||||
private fun materielTheme(chart: ChartView, view: View) {
|
||||
chart.apply {
|
||||
yAxis.apply {
|
||||
textLabel.color = MaterialColors.getColor(
|
||||
view,
|
||||
com.google.android.material.R.attr.colorOnPrimaryContainer
|
||||
)
|
||||
linePaint.color = MaterialColors.getColor(
|
||||
view,
|
||||
com.google.android.material.R.attr.colorOnPrimaryContainer
|
||||
)
|
||||
goalLinePaint.color = MaterialColors.getColor(
|
||||
view,
|
||||
com.google.android.material.R.attr.colorError
|
||||
)
|
||||
}
|
||||
|
||||
xAxis.apply {
|
||||
textPaint.color = MaterialColors.getColor(
|
||||
view,
|
||||
com.google.android.material.R.attr.colorOnPrimaryContainer
|
||||
)
|
||||
}
|
||||
|
||||
for (serie in series) {
|
||||
if (serie is BarSerie) {
|
||||
serie.apply {
|
||||
barPaint.color = MaterialColors.getColor(
|
||||
view,
|
||||
com.google.android.material.R.attr.colorPrimary
|
||||
)
|
||||
textPaint.color = MaterialColors.getColor(
|
||||
view,
|
||||
com.google.android.material.R.attr.colorOnPrimary
|
||||
)
|
||||
textExternalPaint.color = MaterialColors.getColor(
|
||||
view,
|
||||
com.google.android.material.R.attr.colorPrimary
|
||||
)
|
||||
}
|
||||
} else if (serie is LineSerie) {
|
||||
serie.apply {
|
||||
linePaint.color = MaterialColors.getColor(
|
||||
view,
|
||||
com.google.android.material.R.attr.colorPrimary
|
||||
)
|
||||
textPaint.color = MaterialColors.getColor(
|
||||
view,
|
||||
com.google.android.material.R.attr.colorOnPrimary
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<size
|
||||
android:height="16dp"
|
||||
android:width="0dp" />
|
||||
</shape>
|
@ -1,23 +1,52 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true"
|
||||
tools:context=".ui.MainActivity">
|
||||
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:id="@+id/fragment"
|
||||
android:name="androidx.navigation.fragment.NavHostFragment"
|
||||
android:layout_marginTop="?attr/actionBarSize"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:defaultNavHost="true"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
android:id="@+id/coordinatorLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
>
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/app_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
app:titleCentered="true" />
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<androidx.core.widget.NestedScrollView
|
||||
|
||||
android:id="@+id/scrollView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:id="@+id/nav_host_fragment"
|
||||
android:name="androidx.navigation.fragment.NavHostFragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
|
||||
app:defaultNavHost="true"
|
||||
app:navGraph="@navigation/nav_graph" />
|
||||
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
216
sample/src/main/res/layout/fragment_chart.xml
Normal file
216
sample/src/main/res/layout/fragment_chart.xml
Normal file
@ -0,0 +1,216 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.dzeio.charts.ChartView
|
||||
android:id="@+id/chart"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="200dp"
|
||||
android:layout_marginBottom="16dp" />
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<Button
|
||||
android:id="@+id/remove_value"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:text="Remove Value"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginEnd="8dp" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/add_value"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:text="Add Value"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginStart="8dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<Button
|
||||
android:id="@+id/remove_serie"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:text="Remove Serie"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginEnd="8dp" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/add_serie"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:text="Add Serie"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginStart="8dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<Button
|
||||
android:id="@+id/switch_subtype"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:text="Basic Chart"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<com.google.android.material.materialswitch.MaterialSwitch
|
||||
android:id="@+id/switch_animations"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="Switch Animations"
|
||||
android:checked="true"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:layout_width="match_parent"
|
||||
android:text="X Axis manipulation"
|
||||
android:textAlignment="center"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<com.google.android.material.materialswitch.MaterialSwitch
|
||||
android:id="@+id/switch_x_axis"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="Enable X Axis"
|
||||
android:checked="true"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:layout_width="match_parent"
|
||||
android:text="X Axis Number of labels"
|
||||
android:textAlignment="center"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<com.google.android.material.slider.Slider
|
||||
android:id="@+id/slider_x_axis"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_marginTop="8dp"
|
||||
android:value="2"
|
||||
android:valueFrom="0"
|
||||
android:valueTo="20"
|
||||
android:stepSize="1"
|
||||
android:layout_weight="1"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
|
||||
<com.google.android.material.materialswitch.MaterialSwitch
|
||||
android:id="@+id/switch_x_axis_scrollable"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginTop="8dp"
|
||||
android:checked="false"
|
||||
android:text="scrollable"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:layout_width="match_parent"
|
||||
android:text="X Axis number of items in view"
|
||||
android:textAlignment="center"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<com.google.android.material.slider.Slider
|
||||
android:id="@+id/slider_x_axis_scroll"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_marginTop="8dp"
|
||||
android:value="5"
|
||||
android:valueFrom="0"
|
||||
android:valueTo="10"
|
||||
android:stepSize="1"
|
||||
android:layout_weight="1"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:layout_width="match_parent"
|
||||
android:text="Y Axis manipulation"
|
||||
android:textAlignment="center"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:layout_width="match_parent"
|
||||
android:text="Y Axis Number of labels"
|
||||
android:textAlignment="center"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<com.google.android.material.materialswitch.MaterialSwitch
|
||||
android:id="@+id/switch_y_axis"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="Switch Y Axis"
|
||||
android:checked="true"
|
||||
android:layout_weight="1"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<com.google.android.material.slider.Slider
|
||||
android:id="@+id/slider_y_axis"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="Switch X Axis"
|
||||
android:checked="true"
|
||||
android:value="5"
|
||||
android:valueFrom="0"
|
||||
android:stepSize="1"
|
||||
android:valueTo="20"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
||||
|
||||
</LinearLayout>
|
@ -4,6 +4,7 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="16dp"
|
||||
tools:context=".ui.MainFragment">
|
||||
|
||||
<ScrollView
|
||||
@ -13,35 +14,44 @@
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:showDividers="middle"
|
||||
android:divider="@drawable/shape_divider"
|
||||
android:padding="16dp">
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.dzeio.charts.ChartView
|
||||
android:id="@+id/chart_grouped"
|
||||
android:id="@+id/barchart"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="200dp" />
|
||||
android:layout_height="100dp" />
|
||||
|
||||
<Button
|
||||
android:layout_width="match_parent"
|
||||
android:id="@+id/goto_barchart"
|
||||
android:text="BarChart"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
|
||||
<com.dzeio.charts.ChartView
|
||||
android:id="@+id/chart_stacked"
|
||||
android:id="@+id/linechart"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="200dp" />
|
||||
android:layout_height="100dp" />
|
||||
|
||||
<Button
|
||||
android:layout_width="match_parent"
|
||||
android:id="@+id/goto_linechart"
|
||||
android:text="LineChart"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
|
||||
<com.dzeio.charts.ChartView
|
||||
android:id="@+id/chart_customization"
|
||||
android:id="@+id/bothchart"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="200dp" />
|
||||
android:layout_height="100dp" />
|
||||
|
||||
<com.dzeio.charts.ChartView
|
||||
android:id="@+id/chart_bar"
|
||||
<Button
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="200dp" />
|
||||
|
||||
<com.dzeio.charts.ChartView
|
||||
android:id="@+id/chart_line"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="200dp" />
|
||||
android:id="@+id/goto_bar_line_chart"
|
||||
android:text="Both barChart & lineChart"
|
||||
android:layout_height="wrap_content"/>
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
||||
|
@ -3,10 +3,27 @@
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/nav_graph"
|
||||
app:startDestination="@id/MainFragment">
|
||||
app:startDestination="@id/main_fragment">
|
||||
|
||||
<fragment
|
||||
android:id="@+id/MainFragment"
|
||||
android:name="com.dzeio.chartstest.ui.MainFragment"
|
||||
tools:layout="@layout/fragment_main"/>
|
||||
android:id="@+id/main_fragment"
|
||||
android:name="com.dzeio.chartsapp.ui.MainFragment"
|
||||
android:label="Dzeio Charts Examples"
|
||||
tools:layout="@layout/fragment_main">
|
||||
<action
|
||||
android:id="@+id/action_MainFragment_to_ChartFragment"
|
||||
app:destination="@id/chart_fragment" />
|
||||
</fragment>
|
||||
|
||||
<fragment
|
||||
android:id="@+id/chart_fragment"
|
||||
android:name="com.dzeio.chartsapp.ui.ChartFragment"
|
||||
android:label="Test the chart"
|
||||
tools:layout="@layout/fragment_chart">
|
||||
|
||||
<argument
|
||||
android:name="chart_type"
|
||||
app:nullable="true"
|
||||
app:argType="string" />
|
||||
</fragment>
|
||||
</navigation>
|
@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="ic_launcher_background">#FFFFFF</color>
|
||||
</resources>
|
@ -1,3 +0,0 @@
|
||||
<resources>
|
||||
<string name="app_name" translatable="false">Dzeio Charts</string>
|
||||
</resources>
|
@ -1,4 +1,6 @@
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<style name="Theme.Charts" parent="Theme.Material3.DynamicColors.DayNight" />
|
||||
<resources>
|
||||
<style name="Theme.Charts" parent="Theme.Material3.DynamicColors.DayNight">
|
||||
<item name="windowActionBar">false</item>
|
||||
<item name="windowNoTitle">true</item>
|
||||
</style>
|
||||
</resources>
|
Loading…
x
Reference in New Issue
Block a user