์ด๋ฒ์ ๊ณต๋ถํ ๋ด์ฉ์ android studio์์ ์ฐจํธ(๊ทธ๋ํ)๋ฅผ ๊ทธ๋ฆฌ๋ ๋ฐฉ๋ฒ์ ๋ํด ๊ณต๋ถํด ๋ณด์๋ค.
์ด๋ฒ ํฌ์คํ ์ ์ฐจํธ ๋ง๋ค๊ธฐ์ ๋ํด ๊ณต๋ถํ๋ ๋ด์ฉ์ ์ ๋ฆฌํด๋ณด๋ ค ํ๋ค.
์ฌ์ค ์๋ ์๋ ์ฐจํธ๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝํ์ด ์์์ง๋ง, ์ด๋ฒ์ ๋ค์ ์ฌ์ฉํด์ผ ํ๋ ๊ฒฝ์ฐ๊ฐ ์๊ฒผ๊ธฐ์ ์ด๋ฒ ๊ธฐํ์ ์ ๋ฆฌํด ๋ณด๋ ค ํ๋ค.(์๋ ์ ๊ณต๋ถํ๋ ๋ด์ฉ์ ๊ฑฐ์ ๋ค ๊น๋จน์ด์ ์ฒ์๋ถํฐ ๋ค์ ๊ณต๋ถํ์๋ค >:( )
์ฐจํธ๋ฅผ ๋ง๋๋ ๋ฐฉ๋ฒ์ ๋ค์ํ์ง๋ง ๊ธฐ๋ณธ์ ์ผ๋ก๋ ๋ค๋ฅธ ๋ถ๋ค์ด ๋ง๋ค์ด์ค ์ฐจํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๊ฐ์ฅ ํธํ ๊ฒ์ด๋ค.
๊ทธ๋ฅ android chart library๋ผ๊ณ ๊ฒ์ํด๋ ๋ค๋ฅธ ๋ถ๋ค์ด ์ด๋ฏธ ๋ง๋ค๊ณ ์ฌ์ฉ ์ค์ธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ๋ค์ ์กด์ฌํ๋ค.
์๋๋ฉด ์์ ์ด ์ง์ custom ํด์ ๋ง๋ค๊ณ ์ถ์ผ๋ฉด android์์ ์ ๊ณตํ๋ canvas๋ฅผ ์ด์ฉํด ๋ง๋ค์ด์ผ ํ๋๋ฐ, canvas๋ ํ์๊ฐ ์ ๋ชจ๋ฅด๋ ๋ด์ฉ์ด๊ธฐ์ ๋ค๋ฅธ ๊ธ์ ์ฐธ๊ณ ํด์ ๋ง๋ค๋ฉด ๋ ๋ฏํ๋ค.
์ด๋ฒ์ ์ฐจํธ๋ฅผ ๋ง๋ค๋ฉด์ ํ์๊ฐ ์ฌ์ฉํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ์ฐจํธ๋ฅผ ๊ทธ๋ ค๋ณธ ์ฌ๋๋ค์ ๋๋ถ๋ถ ์๊ณ ์์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ธ mpAndroidChart๋ผ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํด์ ์ฐจํธ๋ฅผ ๋ง๋ค์ด ๋ณด์๋ค.
https://github.com/PhilJay/MPAndroidChart
์ด ์ฐจํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ๋ค์ํ ์ฐจํธ ํ์์ ์ง์ํ๊ธฐ ๋๋ฌธ์ ์์ฃผ ์ ์ฉํ๊ฒ ์ฌ์ฉํ ์ ์๋ค.
์ด๋ฒ์ ์ฌ์ฉํ ์ฐจํธ๋ ์ ๋ชฉ์์๋ ์ธ๊ธํ๋ฏ์ด line chart๋ฅผ ์ฌ์ฉํด ๋ณด๊ฒ ๋ค.
์ฐจํธ๋ง๋ค ์๊ตฌํ๋ ํญ๋ชฉ์ด ๋ชจ๋ ๋ค๋ฅด๊ธฐ์ ์ด์ ์ฃผ์ํด์ ์ฌ์ฉํ์.
์ด์ ๋ณธ๊ฒฉ์ ์ผ๋ก line chart(์ ๊ทธ๋ํ)๋ฅผ ๋ง๋ค์ด ๋ณด์.
1. ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ถ๊ฐ
mpAndroidChart๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ถ๊ฐํด์ผ ํ๋ค.
setting.gradle.kts(kotlin dsl)
repositories {
maven { setUrl("https://jitpack.io") }
}
setting.gradle(groovy dsl)
repositories {
maven { url 'https://jitpack.io' }
}
app ๋จ์ build.gradle(2023. 09. 27 ๊ธฐ์ค)
// mp android chart
implementation("com.github.PhilJay:MPAndroidChart:v3.1.0")
2. xml์ chart ์์ฑํ๊ธฐ
๋ผ์ด๋ธ๋ฌ๋ฆฌ dependency๋ฅผ ์ถ๊ฐํ๋ค๋ฉด, ์ด์ ๋ xml์ ์ฐจํธ๋ฅผ ๋ง๋ค์ด ๋ณด๊ฒ ๋ค.
<com.github.mikephil.charting.charts.LineChart
android:id="@+id/your_chart_name"
android:layout_width="match_parent"
android:layout_height="match_parent" />
์์ ์ฝ๋๋ฅผ ์ถ๊ฐํด ์ฃผ๋ฉด lineChart๋ฅผ ์ฌ์ฉํ ์ ์์ ๊ฒ์ด๋ค.
๊ทธ๋ฐ๋ฐ ์ด๋จ ๋์๋ ์ฐจํธ๋ก ๋ณด์ฌ์ค์ผ ํ ๋ฐ์ดํฐ๊ฐ ๋ง์ ๋์๋ width๊ฐ match_parent๋ก ๊ตฌ์ฑ๋ chart๋ก๋ ๊ฐ๊ฐ์ ๋ฐ์ดํฐ๋ค์ ํ์ธํ๊ธฐ ์ด๋ ค์ธ ์ ์๋ค.(๊ฐ ๋ฐ์ดํฐ ๊ฐ์ ๊ฐ๊ฒฉ์ด width๊ฐ ์ข์ ๋งํผ ์ข์์ง๊ธฐ ๋๋ฌธ์ ํ์ธํ๊ธฐ ํ๋ค๋ค.)
๊ทธ๋์ mp android chart๋ ์ฐจํธ๋ x์ถ์ ๊ธฐ์ค์ผ๋ก(๊ฐ๋ก) ์คํฌ๋กค์ ํ ์ ์๋ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ค.(์ธ๋ก(y์ถ)๋ ๊ฐ๋ฅํ๋ค.)
์ด ์คํฌ๋กค ๊ธฐ๋ฅ์ ์ฌ์ฉํ๋ ค๋ฉด, kotlin ์ฝ๋๋ฟ๋ง ์๋๋ผ xml์ ์ฝ๋๋ ์ฝ๊ฐ ์ ๋ด์ค์ผ(?) ํ๋ค.
kotlin ์ฝ๋๋ ๋์ค์ ์ฐจํธ ์ค์ ์ ์์ ํ ๋ ๋ค๋ฃจ๋๋ก ํ๊ณ xml์์ ๋ฐ๊ฟ์ผ ํ ๋ถ๋ถ์
scrollView๋ฅผ ์ถ๊ฐํ๊ณ chart์ width๋ฅผ ์์ ์ด ์ํ๋ ๋งํผ ๋๋ ค์ฃผ๋ฉด ๋๋ค.
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:scrollbars="horizontal">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent">
<!-- add your chart code. -->
</LinearLayout>
</HorizontalScrollView>
๊ฐ๋ก๋ก ์คํฌ๋กค๋ผ์ผ ํ๊ธฐ์ horizontalScrollView๋ฅผ ์ฌ์ฉํ๋ค.
๋ํ scrollView ์์๋ LinearLayout์ ๋ฃ์ด์ฃผ๋ ๊ฒ์ ์์ง ๋ง์.
๊ทธ๋ฆฌ๊ณ linearLayout์ chart๋ฅผ ๋ฃ์ ๋ ๋ ์ฃผ์ํด์ผ ํ ์ ์ด ์๋๋ฐ width๋ฅผ match_parent๋ก ์ค์ ํ๋ฉด chart์ width๊ฐ ํ๋ฉด์ ๋ฑ ๋ง๊ฒ ๋ง์ถฐ์ง๊ธฐ ๋๋ฌธ์ scroll์ด ๋ฐ์ํ์ง ์์ ๊ฒ์ด๋ค.
์คํฌ๋กค์ด ๋๊ฒ ํ๋ ค๋ฉด xml์ ํ๋ฉด์ ๋๊ธธ ๋งํผ width๋ฅผ ์์ฃผ ํฌ๊ฒ ์ค์ ํด ์ฃผ์ด์ผ ํ ๊ฒ์ด๋ค.
์ฐจํธ ์์ฑ์ด ๋ชจ๋ ์๋ฃ๋์์ผ๋ฉด ์ด์ ๋ ์ฝ๋ ๋ถ๋ถ์์ ์ฐจํธ ๋ฐ์ดํฐ ์ถ๊ฐ ๋ฐ ์ฐจํธ ์์ ์ ํด์ผ ํ ์ฐจ๋ก์ด๋ค.
3. chart ์์ฑ ๋ฐ ์์
chart๋ฅผ ์์ ํ๊ธฐ ์ ์ ๋จผ์ chart๋ก ๋ณด์ฌ์ค data๋ค์ ๋ง๋ค์ด์ฃผ์ด์ผ ํ๋ค.
chart์ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ ํ๊ธฐ ์ํด chart์ ๊ฐ ๋ฐ์ดํฐ์ ์ขํ๋ฅผ ์ง์ ํ๋ arrayList๋ฅผ ๋ง๋ค์ด ์ฃผ์.
val chartEntry = arrayListOf<Entry>()
Entry()๋ก x์ถ๊ณผ y์ถ์ ์ค์ ํ ์ ์๋ค.(Entry(x =?, y =?) x, y๋ floatํ์ด๋ค.)
์ด์ ์์ ์ด ์์ฑํ list์์ chart๋ก ๋ณด์ฌ์ค ๋ถ๋ถ์ chartArray์ y์ถ์ผ๋ก ๋ฃ์ด ์ค๋ค.
๊ทธ๋ฆฌ๊ณ x์ถ์ 0๋ถํฐ ์์๋๋ก ์ฆ๊ฐํด์ผ ํ๊ธฐ ๋๋ฌธ์(x๊ฐ ๊ฐ์ผ๋ฉด ํ ๋ถ๋ถ์ ๋ฐ์ดํฐ๊ฐ ๋ชจ๋ ๋ชจ์ด๋ ๊ด๊ฒฝ์ ๋ณผ ์ ์์ ๊ฒ์ด๋ค ใ ใ ) for๋ฌธ ๋ฑ ๋ฐ๋ณต๋ฌธ์ ์ด์ฉํด์ผ ํธํ๋ค.
list.forEachIndexed { index, listItem ->
chartEntry.add(Entry(x=index.toFloat(), y=/*์ฐจํธ์ ๋ณด์ฌ์ค ๋ฐ์ดํฐ*/.toFloat()))
}
forEachIndexed๋ฅผ ์ด์ฉํ๋ฉด index์ list์ item๋ค์ ๋ชจ๋ ๋ณด์ฌ์ฃผ๊ธฐ ๋๋ฌธ์ ์ ์ฉํ๊ฒ ์ฌ์ฉํ ์ ์๋ค.
์ ์์ ๊น์ง ์๋ฃํ๋ฉด chart์ ๋ณด์ฌ์ค ๋ฐ์ดํฐ๋ฅผ ๋ง๋๋ ์์ ์ ์๋ฃํ ๊ฒ์ด๋ค!
์ด์ ์ง์ง๋ก chart๋ฅผ ๋ง๋ค์ด ๋ณด์.
lineChart๋ฅผ ๋ง๋ค๊ธฐ ์ํด lineChart๋ง์ ์ํ(?) dataSet์ด ํ์ํ๋ค.
val chartDataSet = LineDataSet(chartData, "")
๋ค์ string parameter๋ label๋ก ๋ฑํ ์ค์ํ ๋ถ๋ถ์ ์๋๊ธฐ ๋๋ฌธ์ ๋น ๋ฌธ์์ด๋ก ์ ์ด์ฃผ์ด๋ ์๊ด์๋ค.
๋ค์์๋ ์์ฑํ dataSet์ ์ด์ฉํด chart์ data๋ฅผ ์ค์ ํด ์ฃผ๊ณ chart๋ฅผ invalidate ํด์ฃผ๋ฉด ๊ธฐ๋ณธ์ ์ธ ์ฐจํธ ์์ฑ์ ๋๋๋ค.
binding.yourChartName.apply {
data = LineData(chartDataSet)
invalidate()
}
์ฐจํธ ์์ฑ์ ์๋ฃํ์ผ๋ ์ด์ ์ฐจํธ ์์ฑ์ ๋ณ๊ฒฝํ๋ ๋ฐฉ๋ฒ์ ์์๋ณด์.
์ฐจํธ์ ์์ฑ์ ํฌ๊ฒ 3๊ฐ์ง๋ก ๋๋ ์ ์์ ๊ฒ ๊ฐ๋ค.
x์ถ, y์ถ, chart item์ด ์๊ฒ ๋ค.
x, y๋ ๊ฐ๊ฐ ์ถ์ ๋ํ ์ค์ ์ ๋ณ๊ฒฝํ ์ ์๋ค.(y์ถ์ ๊ฒฝ์ฐ์๋ ์ค๋ฅธ์ชฝ ์ถ, ์ผ์ชฝ ์ถ์ผ๋ก ์ด๋ฆ ์ง์ด์ ธ ์๋ค.)
chart item์์๋ dataSet์์ ์ค์ ํ item๋ค์ด ๋ณด์ด๋ ์์ฑ์ ๋ณ๊ฒฝํ ์ ์๋ค.
x์ถ๋ถํฐ ์์ํด ๋ณด๊ฒ ๋ค.
x์ถ ์์ ๋ฐฉ๋ฒ์ chart ์์์ xAxis๋ฅผ ๋ถ๋ฌ์์ ์์ ํ ์ ์๋ค.
binding.yourChartName.xAxis.apply {
/*x์ถ ์์ฑ ๋ณ๊ฒฝ*/
}
์ด๋ฒ์ ํ์๊ฐ ์ฌ์ฉํ๋ ์์ฑ๋ค๋ง ์ค๋ช ํด ์ฃผ๊ฒ ๋ค.
์๋๋ ๋งค์ฐ ๋ค์ํ ์์ฑ๋ค์ด ์กด์ฌํ์ง๋ง, ํ์๋ ์ ๋ชจ๋ฅด๋ ํญ๋ชฉ๋ ๋ง๊ณ ๋ถ๋์ด ๋ง์ด ๊ธธ์ด์ง ๋ฏํด์ ํ์๊ฐ ์ฌ์ฉํ ์์ฑ๋ค๋ง ์๋ ค ์ฃผ๋๋ก ํ๊ฒ ๋ค.
๊ทธ๋ฌ๋ฉด ๋จผ์ ์ฌ์ฉํ ์์ ์ฝ๋๋ฅผ ๋ณด๊ฒ ๋ค.
xAxis.apply {
position = XAxis.XAxisPosition.BOTTOM
valueFormatter = IndexAxisValueFormatter(xAxisTitleData)
setLabelCount(xAxisTitleData.size, true)
}
- position: x์ถ์ ํ์ ์์น๋ฅผ ์ค์ ํ๋ค. ๊ธฐ๋ณธ๊ฐ์ TOP์ด๋ค.
- valueFormatter: chart data๋ง๋ค์ label์ ์ค์ ํ ์ ์๋ ํญ๋ชฉ์ด๋ค. ํ์๋ IndexAxisValueFormatter๋ฅผ ์ฌ์ฉํ์ง๋ง ๊ฐ๋ฐ์๊ฐ ์ง์ ์ปค์คํ ํ ์๋ ์๋ค.
- setLabelCount: chart์ label์ ๊ฐ์๋ฅผ ์ ํํ ์ ์๋ค. ๋ ๋ฒ์งธ parameter๋ force๋ก true๋ก ์ค์ ํ๋ฉด label์ ๋ฐ๋์ ๋ณด์ฌ์ค๋ค.
๋ค์์ y์ถ์ ์์ฑ์ ๋ณผ ์ฐจ๋ก์ด๋ค.
๊ทธ๋ฐ๋ฐ ํ์๋ y์ถ์ ๊ด๋ จ๋ ํญ๋ชฉ์ ํ๋๋ ์๋์ง ์์๊ธฐ ๋๋ฌธ์ ์ด ๋ถ๋ถ์ ์๋ตํ๊ณ ์ฐธ๊ณ ์๋ฃ๋ก ๋์ฒดํ๊ฒ ๋ค,
์ด ํฌ์คํ ์์ ๋ค์ํ ์ฐจํธ ์์ฑ์ ๋ค๋ฃฐ ์ ์๋ค.
๋ง์ง๋ง์ผ๋ก chart item ์์ฑ์ ๋ณ๊ฒฝํ๋ ์์ ์ด๋ค.
chartDataSet.apply {
lineWidth = 3f
circleRadius = 6f
color = resources.getColor(R.color.black, null)
setCircleColor(R.color.button_unselected)
mode = LineDataSet.Mode.CUBIC_BEZIER
valueTextSize = 10f
}
- lineWidth: lineChart์ line์ ๋๊ป๋ฅผ ๋ณ๊ฒฝํ๋ค.
- circleRadius: chart์์๋ ํญ๋ชฉ์ด ๋ฅ๊ทผ ์์ผ๋ก ๋์ค๋๋ฐ, ์์ ํฌ๊ธฐ๋ฅผ ๋๋ ค์ค๋ค.
- mode: lineChart์ mode๋ฅผ ์ค์ ํ๋ค. ํ์๊ฐ ์ฌ์ฉํ mode๋ cubic_bezier๋ก chart data ๊ฐ์ line์ ์์ฐ์ค๋ฝ๊ฒ(๋ฅ๊ธ๊ฒ) ์ค์ ํ ์ ์๋ค.(linear, stepped, cubic_bezier, horizontal_bezier ์ด 4๊ฐ์ mode๊ฐ ์กด์ฌํ๋ค.)
- valueTextSize: chart data๊ฐ ๋ณด์ฌ์ฃผ๋ value text์ ํฌ๊ธฐ๋ฅผ ๋ณ๊ฒฝํ๋ค.
4. ์์ ๊ฒฐ๊ณผ
๊ฐ๋จํ๊ฒ ํ์๊ฐ ๋ง๋ ์ฐจํธ ์ํ ์ฌ์ง์ ๋ณด์ฌ ์ฃผ๊ฒ ๋ค.
์ ๋ฆฌ
๊ฐ๋จํ๊ฒ ์ฐจํธ๋ฅผ ๋ง๋ค ์ ์๋ mpAndroidChart๋ฅผ ์ด์ฉํด ๋ณด์๋๋ฐ ์๋นํ ํธ๋ฆฌํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ธ ๊ฒ์ ํ์คํ๋ค.
ํ์ง๋ง ์ฐจํธ ์์ฑ์ด ๋งค์ฐ ๋ค์ํด์ ๋ชจ๋ ์์ฑ์ ์๋ฒฝํ ํ์ฉํ๋ ๊ฒ์ ์๋นํ ์ด๋ ค์ธ ๊ฒ ๊ฐ๋ค.
๋ค์ํ ์ฐจํธ๋ฅผ ์ง์ํ๊ธฐ ๋๋ฌธ์ ์ํฉ์ ๋ง๋ ์ฐจํธ๋ฅผ ์ด์ฉํ๋ฉด ๋ ๊ฒ ๊ฐ๋ค.
์๋ชป๋ ์ ๋ณด๋ ๋ ๋ง์ ์ ๋ณด๋ฅผ ์๊ณ ๊ณ์ ๋ถ๋ค์ ๋๊ธ ํ์ํฉ๋๋ค.
์ฐธ๊ณ ํ ๊ธ