【Kotlin/Android】MPAndroidChartでグラフを実装する方法!

【Kotlin/Android】MPAndroidChartでグラフを実装する方法!

この記事からわかること

  • Android Studio/KotlinMPAndroidChartを使用したグラフ実装方法
  • グラフや折れ線グラフの実装方法
  • 機能デザイン設定するには?
  • ポインタアイコン変更するには?

index

[open]

\ アプリをリリースしました /

みんなの誕生日

友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-

posted withアプリーチ

環境

MPAndroidChartとは?

公式リファレンス:MPAndroidChart

MPAndroidChartAndroidアプリで簡単に折れ線グラフや円グラフ、棒グラフなどの図を実装することのできるライブラリです。MPAndroidChart自体はJavaで開発されているようですが、Kotlinと互換性があるのでどちらの言語でも問題なく機能を利用することが可能です。

またMPAndroidChartはiOSのDGChartsと同じ開発者であり、基本的な操作やAPIなども比較的同じように実装されているようでした。

導入方法

Android StudioでMPAndroidChartを使用するためには「settings.gradle」に maven { url 'https://jitpack.io' }を追加します。


dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
        // MPAndroidChart
        maven { url 'https://jitpack.io' }
    }
}

続いて「build.grade(Module)」にimplementation 'com.github.PhilJay:MPAndroidChart:v3.1.0'を追加します。。


dependencies {
  // MPAndroidChart
  implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0'
}

折れ線グラフの実装方法

MPAndroidChartを使用して折れ線グラフを実装してみます。どのグラフでも基本的に以下の流れでグラフを作成していきます。

MPAndroidChartでグラフを実装する流れ

  1. レイアウトファイルにViewを追加
  2. 元データの準備
  3. 元データをEntry型に変換したリストを準備
  4. グラフ線やポインタなどの機能、デザインなどを設定
  5. ラベルやグラフなどの機能、デザインなどを設定
  6. グラフのデータに格納

まずはレイアウトファイルにViewを追加します。折れ線グラフであればcom.github.mikephil.charting.charts.LineChartになります。

<!-- ①折れ線グラフ -->
  <com.github.mikephil.charting.charts.LineChart
      android:id="@+id/lineChart"
      android:layout_width="match_parent"
      android:layout_height="400dp"
      android:layout_margin="10dp"
      app:layout_constraintBottom_toBottomOf="parent"
      app:layout_constraintEnd_toEndOf="parent"
      app:layout_constraintStart_toStartOf="parent"
      app:layout_constraintTop_toTopOf="parent" />

続いてグラフに表示させるためのデータをFloat型で用意し、X軸とY軸に表示させる値を定義するEntry型の配列を作成し、LineChartdataプロパティに設定すればグラフが表示されるようになります。

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.github.mikephil.charting.charts.LineChart
import com.github.mikephil.charting.components.XAxis
import com.github.mikephil.charting.data.Entry
import com.github.mikephil.charting.data.LineData
import com.github.mikephil.charting.data.LineDataSet

class MainActivity : AppCompatActivity() {
    // ②元データの準備
    private val data: List<Float> = listOf(100.0f, 65.0f, 90.0f, 30.0f, 45.0f)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        var lineChart: LineChart = findViewById(R.id.lineChart)

        // ③元データをEntry型に変換したリストを準備
        val dataEntries = mutableListOf<Entry>()
        data.forEachIndexed { index, value ->
            // X軸は配列のインデックス番号
            val dataEntry = Entry(index.toFloat(), value)
            dataEntries.add(dataEntry)
        }
        // ④グラフ線やポインタなどの機能、デザインなどを設定
        val lineDataSet = LineDataSet(dataEntries, "グラフ名")
        // グラフの線の太さ
        lineDataSet.lineWidth = 5.0f

        // ⑤ラベルやグラフなどの機能、デザインなどを設定
        // x軸のラベルをbottomに表示
        lineChart.xAxis.position = XAxis.XAxisPosition.BOTTOM
        // x軸のラベル数をデータの数にする
        lineChart.xAxis.labelCount = dataEntries.size - 1

        // ⑥グラフのデータに格納
        lineChart.data = LineData(lineDataSet)
    }
}
【Kotlin/Android】MPAndroidChartでグラフを実装する方法!

グラフのデザインを変更する

【Kotlin/Android】MPAndroidChartでグラフを実装する方法!

グラフのデザインを変更するにはLineDataSetのプロパティを操作します。

// グラフの線の太さ
lineDataSet.lineWidth = 5.0f
// グラフモード(曲線)
lineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER
// グラフの色
lineDataSet.colors = listOf(Color.BLACK)
// 点の色
lineDataSet.circleColors = listOf(Color.RED)
// 点の大きさ
lineDataSet.circleRadius = 5.0f
// 塗りつぶし
lineDataSet.setDrawFilled(true)
// 値非表示
lineDataSet.setDrawValues(false)
// ポインタ非表示
lineDataSet.setDrawCircles(true)

グラフ自体の機能を設定する

デフォルトではグラフの点をタップするとフォーカスが写ったり、ピンチやダブルタップでズームできるようになっています。これらを無効にするにはLineChartのプロパティを操作します。

他にもデータ数が多い場合に一部分だけを最初にズームした状態にするためのsetVisibleXRangeMaximumなどがあります。※印がついている設定はlineChart.dataプロパティにデータを格納した後でないと動作しないので注意してください。

// データがない場合のテキスト
lineChart.setNoDataText("データがありません")
// タップでの点の選択を無効
lineChart.isHighlightPerTapEnabled = false
// ピンチでのズームを無効
lineChart.setPinchZoom(false)
// データの最大表示範囲を制限 (データ数が多い場合横にスクロールで表示エリアを移動可能)
lineChart.setVisibleXRangeMaximum(10f) // ※
// データの最小表示範囲を制限 (データ数が多い場合横にスクロールで表示エリアを移動可能)
lineChart.setVisibleXRangeMinimum(5f) // ※
// データの表示位置を指定したX軸の値にする(インデックスではなくX軸の値を指定)
lineChart.moveViewToX((data.size - 1).toFloat()) // ※
// 選択したX軸の位置をハイライト表示 
lineChart.highlightValue(5f,0) // ※
// 表示されているデータの一番低い値を取得
lineChart.lowestVisibleX
// 表示されているデータの一番高い値を取得
lineChart.highestVisibleX
// ダブルタップでのズームを無効
lineChart.isDoubleTapToZoomEnabled = false
// グラフアニメーション
lineChart.animateXY(1, 1)
// グラフUI全体の背景色を変更
lineChart.setBackgroundColor(Color.TRANSPARENT)
// グラフ描画エリアの背景色を変更
lineChart.setDrawGridBackground(true)
lineChart.setGridBackgroundColor(Color.WHITE)
// グラフ描画エリアの枠線を描画
lineChart.setDrawBorders(true)
lineChart.setBorderColor(Color.WHITE)
lineChart.setBorderWidth(2f)

またanimateプロパティを設定することでグラフ描画時にアニメーションがついて描画されます。

ラベルのカスタマイズ

グラフに表示しているラベルをカスタマイズするにはLineChartのプロパティを操作します。

// 右下のDescription Labelを非表示
lineChart.description.isEnabled = false
// グラフ名ラベルを非表示
lineChart.legend.isEnabled = false
// Y軸右側ラベルを非表示
lineChart.axisRight.isEnabled = false
// y左軸最大値
lineChart.axisLeft.axisMaximum = 100f
// y左軸最小値
lineChart.axisLeft.axisMinimum = 0f
// y軸ラベルの表示個数
lineChart.axisLeft.labelCount = 10
// 上からのオフセット
lineChart.extraTopOffset = 30f

データのポインタを画像(Image)にする

データのポインタを画像(Image)に変更するにはEntry(float x, float y, Drawable icon)を使用します。

var icon: Drawable? = ResourcesCompat.getDrawable(getResources(), R.drawable.android, null)
val dataEntry = Entry(key.toFloat(), value.toFloat(), icon)
【Kotlin/Android】MPAndroidChartでグラフを実装する方法!

明示的にアイコン表示しないようにするにはsetDrawIconsfalseを指定します。

// アイコンを非表示にする
lineDataSet.setDrawIcons(false)

一度に表示するデータ数が多い場合は非表示になってしまうのでsetMaxVisibleValueCountで明示的に表示させたい個数を指定することができます。デフォルト値は100です。

// 表示するデータ値数を指定
lineChart.setMaxVisibleValueCount(200)

自分で用意した画像を使用する際は大きさを変更しないとグラフのポインタのサイズを大幅にズレてしまうので画像をリサイズして使用します。

val icon: Drawable? = ResourcesCompat.getDrawable(getResources(), R.drawable.myImage, null)
val bitmap = (icon as BitmapDrawable).bitmap
val resizeDrawable = BitmapDrawable(resources, Bitmap.createScaledBitmap(bitmap, 40, 40, true))
val dataEntry = Entry(value.first, value.second, resizeDrawable)

タップした際にデータを取得する

表示されているグラフでタップした箇所のデータを取得するにはsetOnChartGestureListenerメソッドにOnChartGestureListener型のオブジェクトを渡し各メソッドからタップなどのジェスチャーでMotionEvent型で情報を取得することが可能になります。

// Chartのリスナーを設定します
lineChart.setOnChartGestureListener(object : OnChartGestureListener {
    override fun onChartGestureStart(me: MotionEvent?, lastPerformedGesture: ChartTouchListener.ChartGesture?) {
        // タッチジェスチャーが開始された際の処理
    }

    override fun onChartGestureEnd(me: MotionEvent?, lastPerformedGesture: ChartTouchListener.ChartGesture?) {
        // タッチジェスチャーが終了した際の処理
    }

    override fun onChartLongPressed(me: MotionEvent?) {
        // 長押しされた際の処理
    }

    override fun onChartDoubleTapped(me: MotionEvent?) {
        // ダブルタップされた際の処理
    }

    override fun onChartSingleTapped(me: MotionEvent?) {
        // シングルタップされた際の処理
        // タップされた位置にあるデータを取得してみる
        val highlight = lineChart.getHighlightByTouchPoint(me?.x ?: 0f, me?.y ?: 0f)
        if (highlight != null) {
            val entry = lineChart.data.getDataSetByIndex(highlight.dataSetIndex).getEntryForIndex(highlight.x.toInt())
            Log.e("------", entry.x.toString())
        }
    }

    override fun onChartFling(me1: MotionEvent?, me2: MotionEvent?, velocityX: Float, velocityY: Float) {
        // フリックされた際の処理
    }

    override fun onChartScale(me: MotionEvent?, scaleX: Float, scaleY: Float) {
        // ズームされた際の処理
    }

    override fun onChartTranslate(me: MotionEvent?, dX: Float, dY: Float) {
        // 移動された際の処理
    }
})

グラフをリセットする

グラフに表示しているデータをリセットしたい場合はclearValuesメソッドとclearメソッドを使用します。これでグラフの設定も初期化されnotifyDataSetChangedでデータの変更をUIへと反映させinvalidateで再描画をさせています。

lineChart.data?.clearValues()
lineChart.clear()
lineChart.notifyDataSetChanged()
lineChart.invalidate()

実際に使用して開発したアプリのソースコードを公開中

まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。

ご覧いただきありがとうございました。

searchbox

スポンサー

ProFile

ame

趣味:読書,プログラミング学習,サイト制作,ブログ

IT嫌いを克服するためにITパスを取得しようと勉強してからサイト制作が趣味に変わりました笑
今はCMSを使わずこのサイトを完全自作でサイト運営中〜

New Article

index