위 사진에 보이는 차트를 안드로이드 주요 차트 라이브러리인 MPAndroidChart를 이용해 그려볼 것이다. 내가 영어를 그닥 잘하지 않아서 그런건지 모르겠지만, 저런 차트를 그리고 싶은데 문서나 강의 같은걸 찾지 못했다. 그래서 블로그에도 올려서 방법을 공유 해 보려고 한다!
MPAndroidChart 준비하기
MPAndroidChart
라이브러리를 사용하기 위해서 gradle에 다음과 같이 추가한다.
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
dependencies {
...
implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0'
최신 버전으로 받고 싶다면 github로 직접 가서 Getting Started 가이드를 보면 된다.
https://github.com/PhilJay/MPAndroidChart
차트 데이터
차트를 그리기 위해서는 자료가 필요하다. 빠른 진행을 위해, Data 자료형과 Data를 가져올 수 있는 유틸 클래스를 먼저 만들자!
Stock.kt
주식 데이터를 담고있다. 시간(unix timestamp)과 주가를 가짐.
data class Stock(
var createdAt: Long = 0,
var price: Long = 0
)
DataUtil.kt
DataUtil.getStockData()
로 데이터 목록을 바로 가져올 수 있도록 만들었다.
object DataUtil {
fun getStockData(): List<Stock> {
return listOf(
Stock(1_500_000_000, 2000),
Stock(1_500_000_100, 2100),
Stock(1_500_000_200, 1700),
Stock(1_500_000_300, 1740),
Stock(1_500_000_400, 1980),
Stock(1_500_000_500, 2000),
Stock(1_500_000_600, 2100),
Stock(1_500_000_700, 2400),
Stock(1_500_000_800, 3000),
Stock(1_500_000_900, 1700),
Stock(1_500_001_000, 1500),
Stock(1_500_001_100, 1294),
Stock(1_500_001_200, 3944),
Stock(1_500_001_300, 4500),
Stock(1_500_001_400, 6969),
Stock(1_500_001_500, 8930),
Stock(1_500_001_600, 9900),
Stock(1_500_001_700, 7000),
Stock(1_500_001_800, 8300),
Stock(1_500_001_900, 4300),
Stock(1_500_002_000, 2003),
Stock(1_500_002_100, 5960),
Stock(1_500_002_200, 3403),
Stock(1_500_002_300, 3040),
Stock(1_500_002_400, 5060),
Stock(1_500_002_500, 2931),
Stock(1_500_002_600, 3030),
Stock(1_500_002_700, 6431),
Stock(1_500_002_800, 3948),
Stock(1_500_002_900, 2100),
Stock(1_500_003_000, 2030),
Stock(1_500_003_100, 2031),
Stock(1_500_003_200, 2039),
Stock(1_500_003_300, 4504),
Stock(1_500_003_400, 4912),
Stock(1_500_003_500, 7963),
Stock(1_500_003_600, 3929),
Stock(1_500_003_700, 7945),
Stock(1_500_003_800, 9920),
Stock(1_500_003_900, 1293),
Stock(1_500_004_000, 2192),
Stock(1_500_004_100, 2944),
Stock(1_500_004_200, 1912),
Stock(1_500_004_300, 2392),
Stock(1_500_004_400, 1029),
Stock(1_500_004_500, 4950),
Stock(1_500_004_600, 2392),
Stock(1_500_004_700, 3494),
Stock(1_500_004_800, 3590),
Stock(1_500_004_900, 3429),
Stock(1_500_005_000, 2066),
Stock(1_500_005_100, 6938),
Stock(1_500_005_200, 7939),
Stock(1_500_005_300, 8400),
Stock(1_500_005_400, 8700),
Stock(1_500_005_500, 8900),
Stock(1_500_005_600, 9100),
Stock(1_500_005_700, 1010),
Stock(1_500_005_800, 1200),
Stock(1_500_005_900, 1500),
Stock(1_500_006_000, 1430),
Stock(1_500_006_100, 1220),
Stock(1_500_006_200, 1900),
Stock(1_500_006_300, 2210),
Stock(1_500_006_400, 2391),
Stock(1_500_006_500, 2399),
Stock(1_500_006_600, 2394),
Stock(1_500_006_700, 3494),
Stock(1_500_006_800, 2050),
Stock(1_500_006_900, 2150),
Stock(1_500_007_000, 3493),
Stock(1_500_007_100, 2942),
Stock(1_500_007_200, 2191),
Stock(1_500_007_300, 3050),
Stock(1_500_007_400, 1012),
Stock(1_500_007_500, 2129),
Stock(1_500_007_600, 2434),
Stock(1_500_007_700, 2933),
Stock(1_500_007_800, 3020),
Stock(1_500_007_900, 3430),
Stock(1_500_008_000, 2930),
Stock(1_500_008_100, 2041),
Stock(1_500_008_200, 3439),
Stock(1_500_008_300, 2032),
Stock(1_500_008_400, 3043),
Stock(1_500_008_500, 1990),
Stock(1_500_008_600, 2032),
Stock(1_500_008_700, 1700),
Stock(1_500_008_800, 2092),
Stock(1_500_008_900, 2399)
)
}
}
레이아웃 준비하기
activity_line_chart.xml
MPAndroidChart의 LineChart
를 사용하기 위해서 다음과 같이 xml을 구성 해 주었다.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center">
<com.github.mikephil.charting.charts.LineChart
android:id="@+id/chart"
android:layout_width="match_parent"
android:layout_height="400dp"/>
</LinearLayout>
LineChart 그리기
처음에 MPAndroidChart에서 제공하는 라인차트를 그리게 되면 너무 기능상 충실한 나머지 디자인이 눈뜨고 못봐줄 정도라 가리고 싶은 부분이 많은데, 원하는 부분을 가리고 커스터마이징 할 수 있다. 우선은 모든- 거추장스러운 부분을 가리고 라인 차트를 하나 그려보자!
LineChartActivity.kt
kotlin의 viewBinding을 이용할 것이다. (사용하기 위해서는 app 수준 gradle에 아래 코드 추가해주면됨)
android {
viewBinding {
enabled = true
}
}
다음 코드를 이용하면 사진과 같은 깔끔한 차트 하나를 그릴 수 있다. 데이터의 평균 값으로 LimitLine
을 그리고, Color.RED
로 그냥 빨갛게만 칠했다. 코드를 만져보면서 눈치챈 사람들도 있겠지만, LineDataSet
에서는 setColor()
외에도 setColors()
라는 메소드가 있어서 색상값을 배열로 전달 할 수 있다.
class LineChartActivity : AppCompatActivity() {
private lateinit var binding: ActivityLineChartBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityLineChartBinding.inflate(layoutInflater)
setContentView(binding.root)
// 평균 값 구하기
var average = 0F
for (stock in DataUtil.getStockData()) {
average += stock.price.toFloat()
}
average /= DataUtil.getStockData().size
// 그래프에 들어갈 데이터 준비
val entries = ArrayList<Entry>()
for (stock in DataUtil.getStockData()) {
entries.add(Entry(stock.createdAt.toFloat(), stock.price.toFloat()))
}
val dataSet = LineDataSet(entries, "").apply {
setDrawCircles(false)
color = Color.RED
highLightColor = Color.TRANSPARENT
valueTextSize = 0F
lineWidth = 1.5F
}
val lineData = LineData(dataSet)
binding.chart.run {
data = lineData
description.isEnabled = false // 하단 Description Label 제거함
invalidate() // refresh
}
val averageLine = LimitLine(average).apply {
lineWidth = 1F
enableDashedLine(4F, 10F, 10F)
lineColor = Color.DKGRAY
}
// 범례
binding.chart.legend.apply {
isEnabled = false // 사용하지 않음
}
// Y 축
binding.chart.axisLeft.apply {
// 라벨, 축라인, 그리드 사용하지 않음
setDrawLabels(false)
setDrawAxisLine(false)
setDrawGridLines(false)
// 한계선 추가
removeAllLimitLines()
addLimitLine(averageLine)
}
binding.chart.axisRight.apply {
// 우측 Y축은 사용하지 않음
isEnabled = false
}
// X 축
binding.chart.xAxis.apply {
// x축 값은 투명으로
textColor = Color.TRANSPARENT
// 축라인, 그리드 사용하지 않음
setDrawAxisLine(false)
setDrawGridLines(false)
}
}
}
그렇다면! 평균값을 기준으로 평균값 >= 가격
이라면 Color.RED
, 평균값 < 가격
이라면 Color.BLUE
로 해서 표를 그려보면 어떨까?! 그래서 colors
라는 ArrayList<Int>
를 추가하고 적용시켜보았다.
val entries = ArrayList<Entry>()
val colors = ArrayList<Int>()
for (stock in DataUtil.getStockData()) {
entries.add(Entry(stock.createdAt.toFloat(), stock.price.toFloat()))
colors.add(if (stock.price >= average) {
Color.RED
} else {
Color.BLUE
})
}
val dataSet = LineDataSet(entries, "").apply {
setDrawCircles(false)
this.colors = colors
highLightColor = Color.TRANSPARENT
valueTextSize = 0F
lineWidth = 1.5F
}
결과는 다소 당황스러웠는데, 값과 값 사이의 색깔을 칠해주는거라서 정확하게 평균값을 기준으로 두 색깔을 가르지 못했다. 이를 해결하기 위해서는 가짜 값들을 넣어주어야 한다. 이전 색깔을 검사하고 색깔이 달라질때 투명이면서 평균값을 가지는 데이터 하나를 추가하고, 다음 색깔을 가지면서 평균값을 가지는 데이터 하나를 추가하면 우리가 원하는 차트를 얻을 수 있다.
val entries = ArrayList<Entry>()
val colors = Stack<Int>()
for (stock in DataUtil.getStockData()) {
if (stock.price >= average) {
if (colors.isNotEmpty() && colors.peek() == Color.BLUE) {
entries.add(Entry(stock.createdAt.toFloat(), average))
colors.add(Color.TRANSPARENT)
entries.add(Entry(stock.createdAt.toFloat(), average))
colors.add(Color.RED)
}
entries.add(Entry(stock.createdAt.toFloat(), stock.price.toFloat()))
colors.add(Color.RED)
} else {
if (colors.isNotEmpty() && colors.peek() == Color.RED) {
entries.add(Entry(stock.createdAt.toFloat(), average))
colors.add(Color.TRANSPARENT)
entries.add(Entry(stock.createdAt.toFloat(), average))
colors.add(Color.BLUE)
}
entries.add(Entry(stock.createdAt.toFloat(), stock.price.toFloat()))
colors.add(Color.BLUE)
}
}
'프로그래밍 > Android' 카테고리의 다른 글
[Kotlin/Java] 생년월일 기준으로 현재 만 나이 계산하기 (0) | 2021.01.11 |
---|---|
[안드로이드] 주식 봉차트 그리기 (Drawing candle stick chart with MPAndroidChart Library Example) (0) | 2021.01.10 |
[Java/Kotlin] 안드로이드 DP to PX 변환하기 (0) | 2021.01.08 |
[안드로이드] RecyclerView의 자동 스크롤 막기 (0) | 2021.01.08 |
[안드로이드] Keytool을 이용해 KeyHash, SHA-1 얻기 (0) | 2021.01.07 |