diff --git a/README.md b/README.md
index 78ec390..525bfb4 100644
--- a/README.md
+++ b/README.md
@@ -1,13 +1,13 @@
##### `Node Line Chart`
-[![](https://jitpack.io/v/oky2abbas/reactor.svg)](https://jitpack.io/#dfmAbbas/reactor)
-[![License](http://img.shields.io/badge/license-MIT-green.svg?style=flat)](https://github.com/oky2abbas/reactor)
-[![API](https://img.shields.io/badge/API-14%2B-blue.svg?style=flat)](https://github.com/oky2abbas/reactor)
+[![](https://jitpack.io/v/naqdi/reactor.svg)](https://jitpack.io/#dfmAbbas/reactor)
+[![License](http://img.shields.io/badge/license-MIT-green.svg?style=flat)](https://github.com/naqdi/reactor)
+[![API](https://img.shields.io/badge/API-14%2B-blue.svg?style=flat)](https://github.com/naqdi/reactor)
**Chain Chart View** is a
-[![Donate](https://img.shields.io/badge/Donate-green)](https://idpay.ir/oky2abbas)
+[![Donate](https://img.shields.io/badge/Donate-green)](https://idpay.ir/naqdi)
**Bitcoin (BTC) Donate: `bc1qhgvnx2nfzr0qep5fnsevyyn59k32wpe7q0c7nh`**
diff --git a/build.gradle b/build.gradle
index 61abf78..c150856 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,6 +1,6 @@
buildscript {
ext {
- minV = 14
+ minV = 17
targetV = 30
vCode = 1
vName = '0.9.0'
@@ -9,12 +9,13 @@ buildscript {
gradleV = '4.1.0'
kotlinV = '1.4.10'
materialV = '1.2.1'
+ appcompatV = '1.2.0'
}
repositories {
+ maven { url 'https://maven.google.com' }
google()
jcenter()
- mavenCentral()
}
dependencies {
classpath "com.android.tools.build:gradle:$gradleV"
@@ -24,6 +25,7 @@ buildscript {
allprojects {
repositories {
+ maven { url 'https://maven.google.com' }
google()
jcenter()
}
diff --git a/library/build.gradle b/library/build.gradle
index 4cf94a3..a412538 100644
--- a/library/build.gradle
+++ b/library/build.gradle
@@ -32,4 +32,5 @@ android {
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinV"
+ implementation "androidx.appcompat:appcompat:$appcompatV"
}
\ No newline at end of file
diff --git a/library/src/main/AndroidManifest.xml b/library/src/main/AndroidManifest.xml
index 2057551..49d7951 100644
--- a/library/src/main/AndroidManifest.xml
+++ b/library/src/main/AndroidManifest.xml
@@ -1,5 +1,5 @@
+ package="com.naqdi.chart">
\ No newline at end of file
diff --git a/library/src/main/java/com/oky2abbas/library/view/ChainChartView.kt b/library/src/main/java/com/naqdi/chart/ChainChartView.kt
similarity index 52%
rename from library/src/main/java/com/oky2abbas/library/view/ChainChartView.kt
rename to library/src/main/java/com/naqdi/chart/ChainChartView.kt
index dba23b3..02564b1 100644
--- a/library/src/main/java/com/oky2abbas/library/view/ChainChartView.kt
+++ b/library/src/main/java/com/naqdi/chart/ChainChartView.kt
@@ -1,47 +1,34 @@
-package com.oky2abbas.library.view
+package com.naqdi.chart
import android.annotation.SuppressLint
import android.content.Context
-import android.graphics.Canvas
-import android.graphics.Color
-import android.graphics.DashPathEffect
-import android.graphics.Paint
+import android.graphics.*
+import android.graphics.Paint.ANTI_ALIAS_FLAG
import android.text.TextPaint
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
-import com.oky2abbas.library.ext.closestValue
-import com.oky2abbas.library.ext.dpToPx
-import com.oky2abbas.library.ext.getMaxGraph
-import com.oky2abbas.library.ext.getSize
-import com.oky2abbas.library.model.Graph
-import com.oky2abbas.library.utils.FakeGenerator
+import androidx.core.content.res.ResourcesCompat
+import com.naqdi.chart.model.Line
+import com.naqdi.chart.utils.*
-/*
- @author: abbas naqdi (naqdi)
- - All the following code was written by @naqdi without any copying
- - Use of this source code is not permitted without permission
- - This source was sent to https://zelkaa.com
- */
class ChainChartView @JvmOverloads constructor(
context: Context, attrs: AttributeSet?, defStyleAttr: Int = 0
) : View(
context, attrs, defStyleAttr
) {
-
- private var graphList = listOf()
- private var nameList = listOf()
+ private var lineList = listOf()
+ private var titleList = listOf()
private var rangeList = listOf()
private val splitList = arrayListOf()
+
private val circleRadius = 9f
private var selectedX = 0f
private val minLeftMargin = 10f
private var maxLeftMargin = minLeftMargin * 2
- private val topMargin = 30f
- private val bottomMargin = 30f
- private val textSize = 11f
+ private val topBottomMargin = 30f
private var maxGraphTitleSize = 50f
private var maxNode = 0f
@@ -49,67 +36,142 @@ class ChainChartView @JvmOverloads constructor(
private var widthVal = 0f
private var heightVal = 0f
- private val circlePaint = Paint().apply {
- style = Paint.Style.FILL
+
+ private val nodePaint = Paint(ANTI_ALIAS_FLAG).apply {
isAntiAlias = true
+ style = Paint.Style.FILL_AND_STROKE
+ strokeCap = Paint.Cap.ROUND
}
- private val linePaint = Paint().apply {
- style = Paint.Style.FILL
+ private val linePaint = Paint(ANTI_ALIAS_FLAG).apply {
isAntiAlias = true
+ style = Paint.Style.FILL
strokeCap = Paint.Cap.ROUND
- strokeWidth = 3f
}
- private val badgePaint = Paint().apply {
- style = Paint.Style.FILL
+ private val badgePaint = Paint(ANTI_ALIAS_FLAG).apply {
isAntiAlias = true
+ style = Paint.Style.FILL_AND_STROKE
strokeCap = Paint.Cap.ROUND
- strokeWidth = 5f
+ strokeWidth = context.dpToPx(1f)
}
- private val liteLinePaint = Paint().apply {
- style = Paint.Style.FILL
+ private val liteLinePaint = Paint(ANTI_ALIAS_FLAG).apply {
isAntiAlias = true
+ style = Paint.Style.FILL
strokeCap = Paint.Cap.ROUND
- strokeWidth = 0.09f
+ color = 0x10000000
}
- private val strokeLinePaint = Paint().apply {
- style = Paint.Style.STROKE
+ private val strokeLinePaint = Paint(ANTI_ALIAS_FLAG).apply {
isAntiAlias = true
- strokeWidth = 4f
+ style = Paint.Style.FILL
pathEffect = DashPathEffect(floatArrayOf(10f, 12f), 0f)
- strokeCap = Paint.Cap.BUTT
- color = 0x20000000
+ strokeCap = Paint.Cap.ROUND
+ color = 0x40000000
}
- private val textPaint = TextPaint().apply {
+ private val textPaint = TextPaint(ANTI_ALIAS_FLAG).apply {
isAntiAlias = true
- textSize = getContext().dpToPx(textSize)
- color = Color.BLACK
+ style = Paint.Style.FILL
+ strokeCap = Paint.Cap.ROUND
}
- private val textCenterPaint = TextPaint().apply {
+ private val textCenterPaint = TextPaint(ANTI_ALIAS_FLAG).apply {
isAntiAlias = true
- textSize = getContext().dpToPx(textSize)
- color = Color.BLACK
+ style = Paint.Style.FILL
+ strokeCap = Paint.Cap.ROUND
textAlign = Paint.Align.CENTER
}
- /*
- The client can use this method to set data in graphs
- Note: The source instance of using this method is available
- in the `FakeGenerator` object.
- */
+ init {
+ val typeArray = context.theme.obtainStyledAttributes(
+ attrs, R.styleable.cc_line,
+ 0, 0
+ )
+
+ try {
+ typeArray.getDimension(
+ R.styleable.cc_line_cc_text_size,
+ context.dpToPx(11f)
+ ).let {
+ textCenterPaint.textSize = it
+ textPaint.textSize = it
+ }
+
+ typeArray.getDimension(
+ R.styleable.cc_line_cc_line_size,
+ context.dpToPx(1f)
+ ).let {
+ linePaint.strokeWidth = it
+ }
+
+ typeArray.getDimension(
+ R.styleable.cc_line_cc_node_size,
+ context.dpToPx(1f)
+ ).let {
+ nodePaint.strokeWidth = it
+ }
+
+ typeArray.getColor(
+ R.styleable.cc_line_cc_text_color,
+ Color.BLACK
+ ).let {
+ textCenterPaint.color = it
+ textPaint.color = it
+ }
+
+ typeArray.getResourceId(
+ R.styleable.cc_line_cc_font_family,
+ 0
+ ).let {
+ if (it == 0) return@let
+ val font = ResourcesCompat.getFont(context, it)
+ textCenterPaint.typeface = font
+ textPaint.typeface = font
+ }
+
+ } finally {
+ typeArray.recycle()
+ }
+ }
+
+ fun setFontFamily(font: Typeface) {
+ textCenterPaint.typeface = font
+ textPaint.typeface = font
+ }
+
+ fun setTextSize(size: Float) {
+ textCenterPaint.textSize = context.dpToPx(size)
+ textPaint.textSize = context.dpToPx(size)
+ }
+
+ fun setLineSize(size: Float) {
+ linePaint.strokeWidth = context.dpToPx(size)
+ }
+
+ fun setNodeSize(size: Float) {
+ nodePaint.strokeWidth = context.dpToPx(size)
+ }
+
+ fun setTextColor(color: Int) {
+ textCenterPaint.color = color
+ textPaint.color = color
+ }
+
+/*
+ The client can use this method to set data in graphs
+ Note: The source instance of using this method is available
+ in the `FakeGenerator` object.
+ */
fun setData(
- graphList: List,
- nameList: List,
+ lineList: List,
+ intervalList: List,
rangeList: List
) {
- this.graphList = graphList
- this.nameList = nameList
+ this.lineList = lineList
+ this.titleList = intervalList
this.rangeList = rangeList
invalidate()
@@ -125,8 +187,8 @@ class ChainChartView @JvmOverloads constructor(
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
- //
- if (graphList.isEmpty()) {
+ //work only in editable mode
+ if (isInEditMode && lineList.isEmpty()) {
setData(
FakeGenerator.generate(),
FakeGenerator.nameList,
@@ -140,7 +202,7 @@ class ChainChartView @JvmOverloads constructor(
This code finds the largest graph based on the number of nodes,
then divides it based on this graph.
*/
- graphList.getMaxGraph()?.let {
+ lineList.getMaxGraph()?.let {
for (index in it.nodeList.indices) {
splitList.add(it.getGraphX(index))
}
@@ -151,7 +213,7 @@ class ChainChartView @JvmOverloads constructor(
then converts this range to float size
and is used for padding
*/
- rangeList.map { it.length }.maxOrNull()?.let {
+ rangeList.map { it.length }.max()?.let {
maxLeftMargin = minLeftMargin + (it + 110).toFloat()
}
@@ -159,20 +221,20 @@ class ChainChartView @JvmOverloads constructor(
This code finds the largest title in the graph
and converts this title to a float size
*/
- graphList.map { it.title.getSize() }.maxOrNull()?.let {
+ lineList.map { it.title.getSize() }.max()?.let {
maxGraphTitleSize = it
}
//This code finds the largest node among all graphs
- graphList.flatMap { it.nodeList }.max()?.let {
+ lineList.flatMap { it.nodeList }.max()?.let {
maxNode = it
}
- graphList.forEachIndexed { index, graph ->
+ lineList.forEachIndexed { index, graph ->
//Draw title badge
canvas?.drawCircle(
- maxLeftMargin + (index * maxGraphTitleSize), topMargin,
+ maxLeftMargin + (index * maxGraphTitleSize), topBottomMargin,
10f, badgePaint.apply {
color = graph.color
}
@@ -182,7 +244,7 @@ class ChainChartView @JvmOverloads constructor(
canvas?.drawText(
graph.title,
minLeftMargin + maxLeftMargin + (maxGraphTitleSize * index),
- topMargin * 2, textPaint
+ topBottomMargin * 2, textPaint
)
rangeList.reversed().forEachIndexed { index, value ->
@@ -210,29 +272,29 @@ class ChainChartView @JvmOverloads constructor(
}
@SuppressLint("ClickableViewAccessibility")
- private fun generateGraph(canvas: Canvas?, graph: Graph) {
- for (index in (graph.nodeList.indices)) {
+ private fun generateGraph(canvas: Canvas?, line: Line) {
+ for (index in (line.nodeList.indices)) {
- val currentX = graph.getGraphX(index)
- val currentY = graph.getGraphY(index)
+ val currentX = line.getGraphX(index)
+ val currentY = line.getGraphY(index)
- val name = nameList[index]
+ val name = titleList[index]
//Draw node text
canvas?.drawText(
- name, currentX, heightVal - topMargin,
+ name, currentX, heightVal - topBottomMargin,
textCenterPaint
)
- if (index < graph.nodeList.size - 1) {
- val nextX = graph.getGraphX(index + 1)
- val nextY = graph.getGraphY(index + 1)
+ if (index < line.nodeList.size - 1) {
+ val nextX = line.getGraphX(index + 1)
+ val nextY = line.getGraphY(index + 1)
//Draw node line
canvas?.drawLine(
currentX, currentY, nextX, nextY,
linePaint.apply {
- color = graph.color
+ color = line.color
}
)
}
@@ -241,14 +303,14 @@ class ChainChartView @JvmOverloads constructor(
//Draw selected circle
canvas?.drawCircle(currentX, currentY, circleRadius,
- circlePaint.apply {
- color = graph.color
+ nodePaint.apply {
+ color = line.color
})
//Draw selected vertical line
canvas?.drawLine(
- currentX, topMargin * 3, currentX,
- heightVal - topMargin * 3,
+ currentX, topBottomMargin * 3, currentX,
+ heightVal - topBottomMargin * 3,
strokeLinePaint
)
}
@@ -267,28 +329,28 @@ class ChainChartView @JvmOverloads constructor(
}
//Calculate the width for each node
- private fun Graph.getGraphX(index: Int): Float {
+ private fun Line.getGraphX(index: Int): Float {
val w = (widthVal / nodeList.size)
return (index * w) + (maxLeftMargin)
}
//Calculate the height for each node
- private fun Graph.getGraphY(index: Int): Float {
+ private fun Line.getGraphY(index: Int): Float {
val value = nodeList[index]
val h = (heightVal - nodeList[index])
- return h - (topMargin * 4)
+ return h - (topBottomMargin * 4)
}
- /*
- Adjust nodes based on height
- If a node is larger than height, all nodes are rendered in height
- */
+/*
+ Adjust nodes based on height
+ If a node is larger than height, all nodes are rendered in height
+ */
- private fun Graph.round(): Graph {
+ private fun Line.round(): Line {
if (maxNode < heightVal)
return this
- val nav = (maxNode - (heightVal - topMargin * 7))
+ val nav = (maxNode - (heightVal - topBottomMargin * 7))
val nav2 = (maxNode / nav)
nodeList = nodeList.map { it - (it / nav2) }
@@ -297,7 +359,7 @@ class ChainChartView @JvmOverloads constructor(
//This method finds the distance between the range elements
private fun getRangeYVal(index: Int): Float {
- val h = (heightVal / rangeList.size) - (topMargin)
- return (h * index) + (topMargin * 3.5f)
+ val h = (heightVal / rangeList.size) - (topBottomMargin)
+ return (h * index) + (topBottomMargin * 3.5f)
}
}
\ No newline at end of file
diff --git a/library/src/main/java/com/naqdi/chart/model/Line.kt b/library/src/main/java/com/naqdi/chart/model/Line.kt
new file mode 100644
index 0000000..1defd01
--- /dev/null
+++ b/library/src/main/java/com/naqdi/chart/model/Line.kt
@@ -0,0 +1,10 @@
+package com.naqdi.chart.model
+
+import androidx.annotation.ColorInt
+
+
+data class Line(
+ val title: String,
+ @ColorInt val color: Int,
+ var nodeList: List
+)
\ No newline at end of file
diff --git a/library/src/main/java/com/oky2abbas/library/ext/ConversionsExt.kt b/library/src/main/java/com/naqdi/chart/utils/ConversionsExt.kt
similarity index 57%
rename from library/src/main/java/com/oky2abbas/library/ext/ConversionsExt.kt
rename to library/src/main/java/com/naqdi/chart/utils/ConversionsExt.kt
index 284bcd4..ceeb920 100644
--- a/library/src/main/java/com/oky2abbas/library/ext/ConversionsExt.kt
+++ b/library/src/main/java/com/naqdi/chart/utils/ConversionsExt.kt
@@ -1,8 +1,9 @@
-package com.oky2abbas.library.ext
+package com.naqdi.chart.utils
import android.content.Context
+import android.content.res.Resources
import android.util.TypedValue
-import com.oky2abbas.library.model.Graph
+import com.naqdi.chart.model.Line
internal fun Context.dpToPx(dp: Float) = TypedValue.applyDimension(
@@ -14,9 +15,9 @@ internal fun String.getSize(): Float {
}
internal fun List.closestValue(value: Float): Float? {
- return minBy { kotlin.math.abs(value - it) }
+ return minByOrNull { kotlin.math.abs(value - it) }
}
-internal fun List.getMaxGraph(): Graph? {
- return maxBy { it.nodeList.size }
+internal fun List.getMaxGraph(): Line? {
+ return maxByOrNull { it.nodeList.size }
}
\ No newline at end of file
diff --git a/library/src/main/java/com/oky2abbas/library/utils/FakeGenerator.kt b/library/src/main/java/com/naqdi/chart/utils/FakeGenerator.kt
similarity index 73%
rename from library/src/main/java/com/oky2abbas/library/utils/FakeGenerator.kt
rename to library/src/main/java/com/naqdi/chart/utils/FakeGenerator.kt
index 1a25b67..b392c4a 100644
--- a/library/src/main/java/com/oky2abbas/library/utils/FakeGenerator.kt
+++ b/library/src/main/java/com/naqdi/chart/utils/FakeGenerator.kt
@@ -1,14 +1,14 @@
-package com.oky2abbas.library.utils
+package com.naqdi.chart.utils
import android.graphics.Color
-import com.oky2abbas.library.model.Graph
+import com.naqdi.chart.model.Line
object FakeGenerator {
val nameList = listOf("Jul", "Aug", "Sep", "Oct", "Nov", "Dec")
- val rangeList = listOf("0", "100", "200", "500")
+ val rangeList = listOf("0-1K", "100K", "200K", "500K")
- fun generate(): List {
- val graphList = arrayListOf()
+ fun generate(): List {
+ val graphList = arrayListOf()
for (i in (1..(1..3).random())) {
val nodeList = arrayListOf()
@@ -18,7 +18,7 @@ object FakeGenerator {
}
graphList.add(
- Graph(
+ Line(
"Node ${(1..9).random()}", getColorValue(i), nodeList
)
)
diff --git a/library/src/main/java/com/oky2abbas/library/model/Graph.kt b/library/src/main/java/com/oky2abbas/library/model/Graph.kt
deleted file mode 100644
index fea002d..0000000
--- a/library/src/main/java/com/oky2abbas/library/model/Graph.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.oky2abbas.library.model
-
-
-data class Graph(
- val title: String,
- val color: Int,
- var nodeList: List
-)
diff --git a/library/src/main/res/values/attrs.xml b/library/src/main/res/values/attrs.xml
new file mode 100644
index 0000000..de45e96
--- /dev/null
+++ b/library/src/main/res/values/attrs.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sample/src/main/java/com/naqdi/sample/MainActivity.kt b/sample/src/main/java/com/naqdi/sample/MainActivity.kt
index d5172eb..db26c5f 100644
--- a/sample/src/main/java/com/naqdi/sample/MainActivity.kt
+++ b/sample/src/main/java/com/naqdi/sample/MainActivity.kt
@@ -2,7 +2,7 @@ package com.naqdi.sample
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
-import com.oky2abbas.library.utils.FakeGenerator
+import com.naqdi.chart.utils.FakeGenerator
import kotlinx.android.synthetic.main.main_activity.*
class MainActivity : AppCompatActivity() {
@@ -11,10 +11,22 @@ class MainActivity : AppCompatActivity() {
setContentView(R.layout.main_activity)
btnGenerate.setOnClickListener {
- grfView1.setData(
- FakeGenerator.generate(),
- FakeGenerator.nameList, FakeGenerator.rangeList
- )
+ chainChartView.apply {
+
+ //example
+
+// setLineSize(3f)
+// setTextSize(13f)
+// setTextColor(Color.GRAY)
+// setNodeSize(8F)
+// setFontFamily(Typeface.DEFAULT_BOLD)
+
+
+ setData(
+ FakeGenerator.generate(),
+ FakeGenerator.nameList, FakeGenerator.rangeList
+ )
+ }
}
}
}
\ No newline at end of file
diff --git a/sample/src/main/res/layout/main_activity.xml b/sample/src/main/res/layout/main_activity.xml
index 2dd60e5..4268cc0 100644
--- a/sample/src/main/res/layout/main_activity.xml
+++ b/sample/src/main/res/layout/main_activity.xml
@@ -1,27 +1,29 @@
-
-
+ android:layout_height="match_parent"
+ android:gravity="center"
+ android:orientation="vertical">
+
+
-
+
\ No newline at end of file
diff --git a/sample/src/main/res/values/strings.xml b/sample/src/main/res/values/strings.xml
index 3dff4d5..d5a8eb6 100644
--- a/sample/src/main/res/values/strings.xml
+++ b/sample/src/main/res/values/strings.xml
@@ -1,4 +1,4 @@
- Chart
- Generate Fake Graph
+ Chart
+ Generate Fake Random Chart
\ No newline at end of file