質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

Q&A

解決済

1回答

4771閲覧

Android Studio MPAndroidChartで、X軸ラベル表記の方法

jissin12

総合スコア6

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

0グッド

0クリップ

投稿2021/08/22 03:15

いつもお世話になっております。

Android Studioにて家計簿アプリを作成しております。
その中で、データベースから日別の支出金額を取得し、日別で棒グラフを作成しようとしております。
(MPAndroidChartを利用)

イメージとして、以下のような棒グラフを表示する事が目標です。
(x軸:日付 y軸:金額。図はExcelにて作成したグラフです。)
イメージ説明

ところが、MPAndroidChartで作成したグラフは以下のようになります。
イメージ説明

AndroidStudioで作成したx軸のラベルは、棒グラフに1対1で対応しておらず
1本の棒グラフに対して同じ日付のラベルが複数表示されております。

Java

1public class AnalysisKodukaiByDate extends AppCompatActivity { 2 3 //バーチャートフィールド 4 BarChart barChart; 5 List<BarEntry> barEntryList; 6 List<List<String>> barList; 7 List<String> barXAxisList; 8 BarDataSet barDataSet; 9 10 BarData barData; 11 12 //データベース関係 13 private DatabaseHelper _helper; 14 private static final String TABLE_NAME = "catkakeibopayment"; 15 private Cursor cursorTotal; 16 private Cursor cursor; 17 private String[] from; 18 private static final int[] to = {R.id.itemName, R.id.amount, R.id.percent}; 19 private SimpleCursorAdapter adapter; 20 int totalIndex = 0; 21 String total; 22 23 @Override 24 protected void onCreate(Bundle savedInstanceState) { 25 super.onCreate(savedInstanceState); 26 setContentView(R.layout.activity_analysis_kodukai_by_date); 27 28 //日付でグループ化し、支出金額を合計するSQL文 29 String selectByDate = "SELECT _id, date, SUM(amount) AS total, ROUND(CAST(SUM(amount) AS REAL) / CAST((SELECT SUM(amount) FROM " + TABLE_NAME + " WHERE date BETWEEN '" + fromDate + "' AND '" + toDate + "') AS REAL) * 100, 1) AS per FROM (SELECT * FROM " + TABLE_NAME + " WHERE date BETWEEN '" + fromDate + "' AND '" + toDate + "') GROUP BY date ORDER BY date ASC;"; 30 31 //データベースに接続し、select文を発行。 32 _helper = new DatabaseHelper(AnalysisKodukaiByDate.this); 33 SQLiteDatabase db = _helper.getWritableDatabase(); 34 35 cursor = db.rawQuery(selectByDate, null); 36 37 //barchart準備 38 barChart = (BarChart) findViewById(R.id.analysisBarChart); 39 barEntryList = new ArrayList<>(); 40 barListSon = new ArrayList<>(); 41 barXAxisList = new ArrayList<>(); 42 43 //SQL結果をループして取得しリストに格納。なお、cursorには_idも含まれる為、indexの数字に注意。 44 int i = 0; 45 while(cursor.moveToNext()) { 46 barEntryList.add(new BarEntry(i, Integer.parseInt(cursor.getString(2)))); 47 barXAxisList.add(cursor.getString(1)); 48 i ++; 49 } 50 51 //グラフの設定 52 barChart.getLegend().setEnabled(true); 53 XAxis xAxis = barChart.getXAxis(); 54 xAxis.setDrawLabels(true); 55 xAxis.setPosition(XAxis.XAxisPosition.BOTTOM); 56 xAxis.setDrawGridLines(false); 57 xAxis.setLabelCount(7, true); 58 xAxis.setValueFormatter(new MyValueFormatter(barChart, barXAxisList)); 59 60 //グラフにデータ格納 61 barDataSet = new BarDataSet(barEntryList, analysisRule); 62 barDataSet.setColors(ColorTemplate.COLORFUL_COLORS); 63 64 barData = new BarData(barDataSet); 65 barData.setValueTextSize(12f); 66 67 barChart.setData(barData); 68 barChart.invalidate(); 69 } 70 71 //グラフのX軸フォーマッタークラス 72 public class MyValueFormatter extends ValueFormatter { 73 private final BarChart chart; 74 private final List<String> barXAxisList; 75 76 public MyValueFormatter(BarChart chart, List<String> barXAxisList) { 77 this.chart = chart; 78 this.barXAxisList = barXAxisList; 79 } 80 @Override 81 public String getFormattedValue(float value) { 82 return ""; 83 } 84 85 @Override 86 public String getAxisLabel(float value, AxisBase axis) { 87 String date = barXAxisList.get((int) value).substring(5,10); 88 return date; 89 }

以下サイトを読み、公式ドキュメントも読んでみたのですが、
サンプルで当たり前に実現していることが自分には出来ず、打開できずにおります。

https://qiita.com/c60evaporator/items/14e63d22d860b73e6f22
https://moneyforward.com/engineers_blog/2015/10/20/mpandroidchart/
https://github.com/PhilJay/MPAndroidChart

何か根本的に分かっておらず、解決出来ないのではないかと思います。
上記の図やコードから、誤っている部分等ご教示頂けないでしょうか。
お手数ですが、どうぞ宜しくお願い致します。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

ぱっと見ですが xAxis.setLabelCount(7, true); 横方向のラベルは 7 個・・・と指定しているのでは無いでしょうか?


xAxis.setLabelCount() の第二引数 force は false にしてください。


データベースのアクセス部分に付きましてコメントした関係上、対処例をご提示させて頂きます。
データベースに関する部分をメソッド化(readData)します。

java

1 interface ReadDataCallback { 2 enum Column { DATE, TOTAL } 3 void set(int row, Column column, String value); 4 } 5 6 private static final String COLUMN_DATE = "date"; 7 private static final String COLUMN_AMOUNT = "amount"; 8 private static final String COLUMN_AS_TOTAL = "total"; 9 10 private void readData(String fromDate, String toDate, ReadDataCallback callback) { 11 DatabaseHelper helper = new DatabaseHelper(this); 12 SQLiteDatabase db = helper.getReadableDatabase(); 13 14 try(Cursor cursor = db.query( 15 TABLE_NAME, //table 16 new String[]{COLUMN_DATE,"SUM("+COLUMN_AMOUNT+") AS "+COLUMN_AS_TOTAL}, //columns 17 COLUMN_DATE+" BETWEEN ? AND ?", //selection(WHERE) 18 new String[]{fromDate, toDate}, //selectionArgs 19 COLUMN_DATE, //groupBy 20 null, //having 21 COLUMN_DATE+" ASC" //orderBy 22 );) { 23 24 int dateIndex = cursor.getColumnIndex(COLUMN_DATE); 25 int totalIndex = cursor.getColumnIndex(COLUMN_AS_TOTAL); 26 for(int i=0; cursor.moveToNext(); i++) { 27 callback.set(i, ReadDataCallback.Column.DATE, cursor.getString(dateIndex)); 28 callback.set(i, ReadDataCallback.Column.TOTAL, cursor.getString(totalIndex)); 29 } 30 } 31 }

読み込む際はコールバックからラムダ式等を利用して各リストに格納します。

java

1 //barchart準備 2 barEntryList = new ArrayList<>(); 3 barXAxisList = new ArrayList<>(); 4 5 readData(fromDate, toDate, (row,column,value)->{ 6 switch(column) { 7 case DATE: 8 barXAxisList.add(value); 9 break; 10 case TOTAL: 11 barEntryList.add(new BarEntry(row, Integer.parseInt(value))); 12 break; 13 } 14 });

こうすると onCreate 内からはデータベースアクセスが無くなりますので、今回の件のようにデータベースは関係無い問題の場合に、

java

1 private void testData(String fromDate, String toDate, ReadDataCallback callback) { 2 callback.set(0, ReadDataCallback.Column.DATE, "2021-08-08"); 3 callback.set(0, ReadDataCallback.Column.TOTAL, "17278"); 4 callback.set(1, ReadDataCallback.Column.DATE, "2021-08-09"); 5 callback.set(1, ReadDataCallback.Column.TOTAL, "4114"); 6 }

といったテスト用メソッドを作成して readData の呼び出しを testData の呼び出しに変更することで、データベースが無い環境(回答者側)でも再現がし易くなります。

投稿2021/08/22 03:22

編集2021/08/23 10:03
jimbe

総合スコア13209

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jimbe

2021/08/22 04:10 編集

SQL 文がちょっとヒドイ状態に思えます。( GROUP BY で _id は意味が無いでしょうし、per は使われていないようです。) カーソルも閉じられていません。 また、自分で文字列として SQL 文を生成するのではなく、 query メソッド等でデータベースのオブジェクトに SQL を生成させるようにしたほうが、データの変換やクオーティングを適切に行ってくれ、データベースのバージョンアップにも強くなります。 ご利用をご検討ください。
jissin12

2021/08/22 10:29

回答して頂きまして有難う御座います。 仰る通り以下の部分が問題でした。(7を指定したのは、当初1週間分のグラフを表示する事を考えた為…?) xAxis.setLabelCount(7, true); ↓ xAxis.setLabelCount(barXAxisList.size(), false); のように修正した所、棒グラフと日付ラベルが対応するようになりました。 カーソル、try-catchで閉じる処理を追加します。 SQLやqueryメソッドについて、もっと勉強します。 有難う御座いました。
jimbe

2021/08/22 11:17

> 当初1週間分のグラフを表示 ~ ? なるほど。何故 7 なのかちょっと不思議でしたが確かにそれなら 7 ですね ^^;
jissin12

2021/08/24 11:34

追加のご回答有難う御座います! ベストアンサーが一度しか選べないのですが、 ベストアンサー×2させて頂きたいくらいです。 教えて頂いたコードを自分で使いこなすのは時間がかかるかもしれませんが、 今作成中のアプリを完成させ、身に着けていきたいと思います。
jimbe

2021/08/24 13:01

このご質問の場合、行毎に読むデータベースを列毎の保存領域(barXAxisListとbarEntryList)に入れるのにどのような形にするかで少し悩みました。 ただ読んで入れるだけなら、両リストを含むクラスを作って readData メソッドがそれを返すようにしても良かったのですが、クラスを増やしたくなかったこと、 barEntryList の中身が MPAndroidChart のクラスで、出来ればデータベース関係のモノに入れたくなかったこと、等がありまして、コールバックを使うことにしました。 わたしの拘りで面倒になってしまってすいません(>_<) readData メソッドを作った本当の意味は、最後のほうに書きましたように、onCreate メソッド内からデータベース関係のコードを隠して、データベースが無い状態(環境)でも表示のテストが出来るようにするということです。 jissin12 さんも、データベースを設定してデータを準備しての後にやっとグラフ表示となったのではないでしょうか。 もし最初に「データベースからデータを読み込む部分はメソッド(readData)にするとして、取り敢えずデータベース読んだテイでデータを返すメソッド(testData)を作っておこう」としていたら、グラフの表示の問題に気付くのももっと早く…いえ多少は早く…まぁ少し位は早く、なってたかもしれません。 何はともあれ、前向きなお言葉を頂けただけで満足です。ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問