2017-01-13 8 views
4

は私がStackedBarChart示す3つのyの値を構築するためにMPAndroidChartライブラリを使用し始めています。ここでは、コードは次のとおりです。私のFragmentで次にMPAndroidChart StackedBarChart示す値が、ノーバー

public class Plot 
{ 
    final Context context; 
    final BarData data; 

    private int count; 

    public StackedBarPlot(Context context) 
    { 
     this.context = context; 
     data = setData(); 
    } 

    protected BarData setData() 
    { 
     final List<BarEntry> entries = new ArrayList<>(); 
     for (DatabaseEntry entry : entryList) 
     { 
      final float total = (float) entry.getTotal(); 
      final float[] y = {100 * entry.getN1()/total, 
        100 * entry.getN2()/total, 100 * entry.getN3()/total}; 
      entries.add(new BarEntry(/*long*/entry.getDate(), y)); 
     } 
     count = entries.size(); 


     final BarDataSet dataset = new BarDataSet(entries, null); 
     dataset.setColors(new int[]{R.color.green, R.color.blue, R.color.red}, context); 
     dataset.setStackLabels(labels); 
     dataset.setDrawValues(true); 
     dataset.setVisible(true); 

     final BarData data = new BarData(dataset); 
     data.setBarWidth(0.9f); 
     return data; 
    } 

    public BarChart getChart(int id, View view) 
    { 
     final BarChart chart = (BarChart) view.findViewById(id); 

     chart.getAxisRight().setEnabled(false); 
     chart.getAxisLeft().setEnabled(false); 
     final Legend legend = chart.getLegend(); 
     legend.setDrawInside(true); 
     legend.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP); 
     legend.setHorizontalAlignment(Legend.LegendHorizontalAlignment.CENTER); 

     final XAxis xAxis = chart.getXAxis(); 
     xAxis.setValueFormatter(dateFormatter); 
     xAxis.setPosition(XAxis.XAxisPosition.BOTTOM); 
     xAxis.setDrawGridLines(false); 
     xAxis.setLabelCount(count); 

     chart.getDescription().setEnabled(false); 
     chart.setData(data); 
     chart.setFitBars(true); 
     chart.invalidate(); 
     return chart; 
    } 

    private final IAxisValueFormatter dateFormatter = new IAxisValueFormatter() 
    { 
     @Override 
     public String getFormattedValue(float value, AxisBase axis) 
     { 
      return new DateTime((long) value).toString(context.getString("E, MMM d")); 
     } 
    }; 
} 

、私が呼ん:

public class MyFragment extends Fragment 
{ 
    private Plot plot; 

    @Override 
    public void onCreate(Bundle savedInstanceState) 
    { 
     super.onCreate(savedInstanceState); 
     plot = new Plot(getActivity()); 
    } 

    @Nullable 
    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) 
    { 
     final View view = inflater.inflate(R.layout.fragment, parent, false); 
     plot.getChart(R.id.chart, view); 
     return view; 
    } 
} 

そしてMainActivity.java

getFragmentManager().beginTransaction().replace(R.id.content, fragment).commit(); 

main_activity.xml

<android.support.v4.widget.DrawerLayout 
    android:id="@+id/drawer_layout" 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:app="http://schemas.android.com/apk/res-auto" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    tools:context=".MainActivity"> 

    <android.support.design.widget.CoordinatorLayout 
     android:layout_width="match_parent" 
     android:layout_height="match_parent"> 

     <android.support.design.widget.AppBarLayout 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:theme="@style/AppTheme.AppBarOverlay"> 

      <android.support.v7.widget.Toolbar 
       android:id="@+id/toolbar" 
       android:layout_width="match_parent" 
       android:layout_height="?attr/actionBarSize" 
       android:background="?attr/colorPrimary" 
       app:popupTheme="@style/AppTheme.PopupOverlay"/> 

     </android.support.design.widget.AppBarLayout> 

     <FrameLayout 
      android:id="@+id/content" 
      android:layout_width="match_parent" 
      android:layout_height="match_parent" 
      app:layout_behavior="@string/appbar_scrolling_view_behavior"/> 
    </android.support.design.widget.CoordinatorLayout> 

    <android.support.design.widget.NavigationView 
     android:id="@+id/navigation" 
     android:layout_width="wrap_content" 
     android:layout_height="match_parent" 
     android:layout_gravity="start" 
     android:fitsSystemWindows="true" 
     app:headerLayout="@layout/drawer_header" 
     app:menu="@menu/navigation"/> 

</android.support.v4.widget.DrawerLayout> 

fragment.xml

<RelativeLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:padding="16dp"> 

    <com.github.mikephil.charting.charts.BarChart 
     android:id="@+id/chart" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent"/> 
</RelativeLayout> 

問題はバーが正しくレンダリングされていないです。私は値を見ることができますが、バーはグラフに表示されません。何かアドバイス?

+0

私はコピーして、それを試してみて、デバッグするために私のIDEにコードを貼り付けたが、それは困難を見て作るいくつかの未解決の依存関係とあなたがチャートを消費しているかについての情報が不足しています。人々があなたのプロジェクトを読み込まなくても使うことができる[MCVE]を作成してください。しかし、これは、グラフのコンテナにXMLを設定した方法の問題であると思われます。 –

+0

@DavidRawson追加レイアウトファイルと完全なフラグメント・コードの更新のため –

+0

おかげで - 私はあなたがナビゲーションドロワーでの活動内のチャートを入れたときに、これはおそらくライブラリのバグかもしれないと思います。私はさらに確認する必要があります –

答えて

1

私はこのStackedBarActivity exampleから始めなければならなかったと私は問題を引き起こしているものを考え出しまで、一度に1つのビットを下って行きます。これは、カスタムIAxisValueFormatterの有無にかかわらずX軸の値についてentry.getDate()からの長いタイムスタンプを使用することです。ライブラリのバグはhereと報告されています。ここで

は、私が回避策としてやってしまったものです。私は、日中のタイムスタンプ以降の期間を得た:

long diff = new Duration(entry.getDate(), DateTime.now().getMillis()).getStandardDays(); 
entries.add(new BarEntry(diff, y)); 

、その後、私のカスタムIAxisValueFormatterに:

private final IAxisValueFormatter dateFormatter = new IAxisValueFormatter() 
{ 
    @Override 
    public String getFormattedValue(float value, AxisBase axis) 
    { 
     return LocalDate.now().minusDays((int) value).toString("EEE"); 
    } 
}; 
+1

ありがとう、この便利な答えは非常にありがとう。このような他のいくつかの質問もありました! –

+0

ライブラリはそのx位置によってソートされたDataSetに追加エントリのみを受け入れるので、あなたは、過去と一緒に未来の日付のタイムスタンプを持っている場合、これは動作しません。あなたの日付とDateTime.now()間の期間を計算した後にエントリをソートする必要がありますが、それはまだあなたが説明した場合のために働くだろう@Keridano、あなたのデータは、 – Keridano

+0

を台無しにされます。 'diff'の値は正または負になります。そして、フォーマッタでは' minusDays() 'は差分を減算/加算した後に正しい日付を返します。 –

0

私はあなたの日付のタイムスタンプを持っている場合でも動作する別の回避策を、見つけました過去と未来の両方で、(全文のためのAA回答のコメントを見てください)。トリックはあなたがX軸方向の異なる値(https://stackoverflow.com/a/28549480/5098038を参照)で複数のデータセットをプロットする必要があるときに使用できるものと類似しています。タイムスタンプを直接BarEntriesのx値に入れるのではなく、タイムスタンプを含むArrayListを作成し、そのインデックスをBarEntriesに入れます。その後、フォーマッタで、データセット(インデックス)に含まれる値を取り出し、アライラリストに含まれるタイムスタンプを取得するために使用します。


元のタイムスタンプ値から配列を作成します。

Long[] xTimestamps = { t1, t2, t3 }; 
List<Long> xArray = new ArrayList<>(Arrays.asList(xTimestamps)); 

BarEntriesにインデックスを追加:

0:

entries.add(new BarEntry(xArray.indexOf(t1), y)); 

フォーマッタを使用してデータを取得します

private static final SimpleDateFormat CHART_SDF = new SimpleDateFormat("dd/MM/yyyy", getApplicationContext().getResources().getConfiguration().locale); private final IAxisValueFormatter dateFormatter = new IAxisValueFormatter() { @Override public String getFormattedValue(float value, AxisBase axis) { Long timestamp = xArray.get((int)value); return Chart_SDF.format(new Date(timestamp)); } }); 
0

さらに詳しい回避策ただ、BarEntryとTimeUnit.DAYSでTimeUnit.MILLISECONDS.toDaysを使用しています。フォーマッタ私のカスタムIAxisValueFormatterで

Long dateInMills = someDateObject.getTime(); 
entries.add(new BarEntry(TimeUnit.MILLISECONDS.toDays(dateInMills), y)); 

、その後でtoMillis:前回の記事のいくつかが示唆されているよう

private final IAxisValueFormatter dateFormatter = new IAxisValueFormatter() 
{ 
    @Override 
    public String getFormattedValue(float value, AxisBase axis) 
    { 
      Float fVal = value; 
      long mills = TimeUnit.DAYS.toMillis(fVal.longValue()); 
      .... 
      //here convert mills to date and string 
      .... 
      return convertedString; 
    } 
}; 
+0

注意してください。時間は四捨五入され、あなたの時間がGMTでない場合、時間は1日だけシフトされます... – Dmitry

1

これは、ライブラリ内のエラーではありません。おそらく、私は最初にしたように各バーの幅がどのように決められているのか誤解しています。私は私の棒グラフで私のx軸のための長い、ミリ秒単位のタイムスタンプを使用していた

。私はデフォルトでMPAndroidChartがバーの幅を0.85fに設定することに気付きました。これが何を意味するのか考えてみてください。私の最初のタイムスタンプは1473421800000fで、次は1473508200000fでした:86400000fの違い!今、観測の各ペアの間に86400000fがあるとき、どのようにして0.85fの幅のバーが表示されると思いますか?

barData.setBarWidth(0.6f * widthBetweenObservations); 

したがって、上記のセットの観測間の距離の60%と等しくなるようにバーの幅:この問題を解決するには、次のような何かをする必要があります。

+0

根本的な問題を説明しているので、これは受け入れられた答えです。 – leoderprofi

関連する問題