下部の更新を参照してください (2015 年 4 月 30 日)
ios-charts を使用して Swift for iOS で円グラフを実装しており、凡例をカスタマイズすることを選択しました。注目すべきは、チャートが UICollectionView のセル内に表示されることです。問題は、最初の表示で、カスタム凡例のコンテンツが表示されないことです。代わりに、データから生成された凡例コンテンツを取得します。
ビューを画面外にスクロールしてから画面に戻すと、適切なカスタム凡例が表示されます。したがって、カスタム凡例を設定した後、再描画/再レイアウト/再作成を強制する必要があると推測しています。私はそれを行う方法を理解していません。 誰にもアイデアはありますか?私は何かを完全に見逃していますか?ありがとう!
初期表示のグラフ - データによって生成された (間違った) 凡例
スクロールして画面に戻った後のチャート - (適切な凡例)
このチャートを描画するための私のコードは次のとおりです。
func initChart(pieChart: PieChartView) {
numFormatter.maximumFractionDigits = 0
pieChart.backgroundColor = UIColor.whiteColor()
pieChart.usePercentValuesEnabled = false
pieChart.drawHoleEnabled = true
pieChart.holeTransparent = true
pieChart.descriptionText = ""
pieChart.centerText = "30%\nComplete"
pieChart.data = getMyData()
// Setting custom legend info, called AFTER setting data
pieChart.legend.position = ChartLegend.ChartLegendPosition.LeftOfChartCenter
pieChart.legend.colors = [clrGreenDk, clrGold, clrBlue]
pieChart.legend.labels = ["Complete","Enrolled","Future"]
pieChart.legend.enabled = true
}
func getMyData() -> ChartData {
var xVals = ["Q201","R202","S203","T204","U205", "V206"]
var courses: [ChartDataEntry] = []
courses.append(ChartDataEntry(value: 3, xIndex: 0))
courses.append(ChartDataEntry(value: 3, xIndex: 1))
courses.append(ChartDataEntry(value: 4, xIndex: 2))
courses.append(ChartDataEntry(value: 4, xIndex: 3))
courses.append(ChartDataEntry(value: 3, xIndex: 4))
courses.append(ChartDataEntry(value: 3, xIndex: 5))
let dsColors = [clrGreenDk, clrGreenDk, clrBlue, clrBlue, clrGold, clrGold]
let pcds = PieChartDataSet(yVals: courses, label: "")
pcds.sliceSpace = CGFloat(4)
pcds.colors = dsColors
pcds.valueFont = labelFont!
pcds.valueFormatter = numFormatter
pcds.valueTextColor = UIColor.whiteColor()
return ChartData(xVals: xVals, dataSet: pcds)
}
2015 年 4 月 30 日更新
MPAndroidChart (ios-charts のベース) の作成者との議論に基づいて、「最初の描画」で凡例を上書きできるグラフ表示ライフサイクルのポイントがないようです。基本的に、グラフは作成時にレンダリングされます。グラフにデータを設定すると、グラフはそのデータを使用して凡例を作成し、レンダリングします。データ設定時点とチャート描画時点の間で凡例を変更することはできません。
setNeedsDisplay()
場合によっては、チャートがレンダリングされるのを待って凡例を更新し、chart.setNeedsDisplay() を呼び出してチャートを再描画するように通知することができます。残念ながら、これにはタイミングの問題があります。グラフをレンダリングした直後にこのメソッドを呼び出すと、起動しないか、(可能性が高い) 起動が早すぎて事実上無視されます。私のコードでは、この呼び出しを viewDidLoad または viewDidAppear 内に配置しても効果はありませんでした。でも...
Java for Android (MPAndroidChart を使用) で同じグラフを作成すると、同じ問題が発生します。少しいじった後、(Handler.postDelayed() を使用して) 遅延後に chart.invalidate() を呼び出すと、適切に起動することに気付きました。iOS の ios-charts でも同様のアプローチが機能することがわかりました。
GCD を使用して setNeedsDisplay() の呼び出しを遅らせると、レンダリング後の数ミリ秒でもうまくいくようです。ViewController でチャートのビューを初期化した直後に次のコードを追加しました (「セル」は、チャート ビューを含む UICollectionViewCell です)。
delay(0.05) {
cell.pieChartView.legend.colors = [self.clrGreenDk, self.clrGold, self.clrBlue]
cell.pieChartView.legend.labels = ["Complete","Enrolled","Future"]
// Re-calc legend dimensions for proper position (Added 5/2/2015)
cell.pieChartView.legend.calculateDimensions(cell.pieChartView.labelFont!)
cell.pieChartView.setNeedsDisplay()
}
この SO 投稿のすばらしい「遅延」メソッドを使用する: https://stackoverflow.com/a/24318861
明らかに、これは厄介なハックですが、うまくいくようです。ただし、このハックを本番環境で使用するというアイデアが好きかどうかはわかりません。
この投稿に出くわした Android 関係者向け:
次のコードは、MPAndroidChart を使用して同じ効果を実現します。
// Inside onCreate()
pie = (PieChart) findViewById(R.id.chart1);
configPieChart(pie);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
String[] legLabels = new String[]{"Complete","Enrolled","Future"};
ArrayList<Integer> legColors = new ArrayList<Integer>();
legColors.add(blue);
legColors.add(gold);
legColors.add(green);
pie.getLegend().setPosition(Legend.LegendPosition.LEFT_OF_CHART_CENTER);
pie.getLegend().setColors(legColors);
pie.getLegend().setLabels(legLabels);
pie.invalidate();
}
}, 20);