

Android グラフ描画ライブラリ AchartEngine の `CubicLineChart`
を使用し、横長の曲線グラフの一覧を表示する画面を作成しようとしています。

まず `TemplatureChart.class` の `execute` メソッドで `GraphicalView` を返すように作成します。

**【グラフのView作成クラス】**

[code]

    public class TemplatureChart  {
        public GraphicalView execute(Context context) {
            String[] titles = new String[] { "Sales for 2008", "Sales for 2007",
                "Difference between 2008 and 2007 sales" };
            List<double[]> values = new ArrayList<double[]>();
            values.add(new double[] { 14230, 12300, 14240, 15244, 14900, 12200, 11030, 12000, 12500, 15500,
                    14600, 15000 });
            values.add(new double[] { 10230, 10900, 11240, 12540, 13500, 14200, 12530, 11200, 10500, 12500,
                    11600, 13500 });
            int length = values.get(0).length;
            double[] diff = new double[length];
            for (int i = 0; i < length; i++) {
                diff[i] = values.get(0)[i] - values.get(1)[i];
            }
            values.add(diff);
            int[] colors = new int[] { Color.BLUE, Color.CYAN, Color.GREEN };
            PointStyle[] styles = new PointStyle[] { PointStyle.POINT, PointStyle.POINT, PointStyle.POINT };
            XYMultipleSeriesRenderer renderer = buildRenderer(colors, styles);
            setChartSettings(renderer, "Monthly sales in the last 2 years", "Month", "Units sold", 0.75,
                    12.25, -5000, 19000, Color.GRAY, Color.LTGRAY);
            renderer.setXLabels(12);
            renderer.setYLabels(10);
            renderer.setChartTitleTextSize(20);
            renderer.setTextTypeface("sans_serif", Typeface.BOLD);
            renderer.setLabelsTextSize(14f);
            renderer.setAxisTitleTextSize(15);
            renderer.setLegendTextSize(15);
            length = renderer.getSeriesRendererCount();
    
            for (int i = 0; i < length; i++) {
                XYSeriesRenderer seriesRenderer = (XYSeriesRenderer) renderer.getSeriesRendererAt(i);
                if (i == length - 1) {
                    FillOutsideLine fill = new FillOutsideLine(FillOutsideLine.Type.BOUNDS_ALL);
                    fill.setColor(Color.GREEN);
                    seriesRenderer.addFillOutsideLine(fill);
                }
                seriesRenderer.setLineWidth(2.5f);
                seriesRenderer.setDisplayChartValues(true);
                seriesRenderer.setChartValuesTextSize(10f);
            }
            return ChartFactory.getCubeLineChartView(context, buildBarDataset(titles, values), renderer,
                    0.5f);
        }
    
        /**
         * Builds a bar multiple series dataset using the provided values.
         * 
         * @param titles the series titles
         * @param values the values
         * @return the XY multiple bar dataset
         */
        protected XYMultipleSeriesDataset buildBarDataset(String[] titles, List<double[]> values) {
            XYMultipleSeriesDataset dataset = new XYMultipleSeriesDataset();
            int length = titles.length;
            for (int i = 0; i < length; i++) {
                CategorySeries series = new CategorySeries(titles[i]);
                double[] v = values.get(i);
                int seriesLength = v.length;
                for (int k = 0; k < seriesLength; k++) {
                    series.add(v[k]);
                }
                dataset.addSeries(series.toXYSeries());
            }
            return dataset;
        }
    
        public static XYMultipleSeriesRenderer getRenderer(){
            XYSeriesRenderer renderer1 = new XYSeriesRenderer(); //個別のグラフ
            renderer1.setColor(Color.rgb(51,181,229)); //グラフの色
            renderer1.setLineWidth(2); //グラフの幅
            renderer1.setPointStyle(PointStyle.SQUARE); //ポイント設定
            renderer1.setPointStrokeWidth(8);
            renderer1.setFillPoints(true);
    
            XYMultipleSeriesRenderer mRenderer = new XYMultipleSeriesRenderer(); //グラフ全体
            mRenderer.setApplyBackgroundColor(true); //背景色変更
            mRenderer.setBackgroundColor(Color.BLACK);
            mRenderer.setMarginsColor(Color.argb(0x00, 0x01, 0x01, 0x01)); //余白色変更    
            mRenderer.setPanEnabled(true);  //グラフを固定
            mRenderer.setZoomEnabled(false); //ズームを不可に
            mRenderer.setShowLegend(false); //凡例非表示
            mRenderer.setAxesColor(Color.GRAY); //軸の色
            mRenderer.setShowGrid(true); //グリッド表示
            mRenderer.setGridColor(Color.parseColor("lightgray")); //グリッドの色
            mRenderer.setXAxisMin(0);
            //mRenderer.setXAxisMax(23); //表示範囲
            //mRenderer.setLabelsTextSize(24); //ラベル文字サイズ
            // mRenderer.setXLabels(0); //X軸ラベル非表示
            //Y軸ラベル設定
            mRenderer.setYLabels(5);//Y軸グリッドの密度？
            mRenderer.setYLabelsColor(0, Color.GRAY);
            mRenderer.setYLabelsPadding(20);
            mRenderer.setYLabelsVerticalPadding(-8);
            mRenderer.addSeriesRenderer(renderer1);
            return mRenderer;
        }
    
    
        /**
         * Builds an XY multiple dataset using the provided values.
         * 
         * @param titles the series titles
         * @param xValues the values for the X axis
         * @param yValues the values for the Y axis
         * @return the XY multiple dataset
         */
        protected XYMultipleSeriesDataset buildDataset(String[] titles, List<double[]> xValues,
                List<double[]> yValues) {
            XYMultipleSeriesDataset dataset = new XYMultipleSeriesDataset();
            addXYSeries(dataset, titles, xValues, yValues, 0);
            return dataset;
        }
    
        public void addXYSeries(XYMultipleSeriesDataset dataset, String[] titles, List<double[]> xValues,
                List<double[]> yValues, int scale) {
            int length = titles.length;
            for (int i = 0; i < length; i++) {
                XYSeries series = new XYSeries(titles[i], scale);
                double[] xV = xValues.get(i);
                double[] yV = yValues.get(i);
                int seriesLength = xV.length;
                for (int k = 0; k < seriesLength; k++) {
                    series.add(xV[k], yV[k]);
                }
                dataset.addSeries(series);
            }
        }
    
        /**
         * Builds an XY multiple series renderer.
         * 
         * @param colors the series rendering colors
         * @param styles the series point styles
         * @return the XY multiple series renderers
         */
        protected XYMultipleSeriesRenderer buildRenderer(int[] colors, PointStyle[] styles) {
            XYMultipleSeriesRenderer renderer = new XYMultipleSeriesRenderer();
            setRenderer(renderer, colors, styles);
            return renderer;
        }
    
        protected void setRenderer(XYMultipleSeriesRenderer renderer, int[] colors, PointStyle[] styles) {
            renderer.setAxisTitleTextSize(16);
            renderer.setChartTitleTextSize(20);
            renderer.setLabelsTextSize(15);
            renderer.setLegendTextSize(15);
            renderer.setPointSize(5f);
            renderer.setMargins(new int[] { 20, 30, 15, 20 });
            int length = colors.length;
            for (int i = 0; i < length; i++) {
                XYSeriesRenderer r = new XYSeriesRenderer();
                r.setColor(colors[i]);
                r.setPointStyle(styles[i]);
                renderer.addSeriesRenderer(r);
            }
        }
        /**
         * Sets a few of the series renderer settings.
         * 
         * @param renderer the renderer to set the properties to
         * @param title the chart title
         * @param xTitle the title for the X axis
         * @param yTitle the title for the Y axis
         * @param xMin the minimum value on the X axis
         * @param xMax the maximum value on the X axis
         * @param yMin the minimum value on the Y axis
         * @param yMax the maximum value on the Y axis
         * @param axesColor the axes color
         * @param labelsColor the labels color
         */
        protected void setChartSettings(XYMultipleSeriesRenderer renderer, String title, String xTitle,
            String yTitle, double xMin, double xMax, double yMin, double yMax, int axesColor,
            int labelsColor) {
            renderer.setChartTitle(title);
            renderer.setXTitle(xTitle);
            renderer.setYTitle(yTitle);
            renderer.setXAxisMin(xMin);
            renderer.setXAxisMax(xMax);
            renderer.setYAxisMin(yMin);
            renderer.setYAxisMax(yMax);
            renderer.setAxesColor(axesColor);
            renderer.setLabelsColor(labelsColor);
        }
    }
    
[/code]

次に下記のような XML ファイルを作成します。

**【レイアウトxmlファイル】**

[code]

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/LinearLayout1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        tools:context="com.example.templature.MainActivity$PlaceholderFragment" >
    
        <HorizontalScrollView
            android:id="@+id/horizontalScrollView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" >
    
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical" >
    
                <LinearLayout
                    android:id="@+id/graph1"
                    android:layout_width="1000dp"
                    android:layout_height="100dp"
                    android:orientation="vertical" >
                </LinearLayout>
    
                <LinearLayout
                    android:id="@+id/graph2"
                    android:layout_width="2000dp"
                    android:layout_height="100dp"
                    android:orientation="vertical" >
                </LinearLayout>
    
                <LinearLayout
                    android:id="@+id/graph3"
                    android:layout_width="3000dp"
                    android:layout_height="100dp"
                    android:orientation="vertical" >
                </LinearLayout>
            </LinearLayout>
    
        </HorizontalScrollView>
    
    </LinearLayout>
    
[/code]

上記のレイアウトに`execute`で設定したidが`graph1`,
`graph2`、`graph3`の`LinearLayout`に`addView`します。

**【addView部分】**

[code]

    LinearLayout graph1 = (LinearLayout) rootView.findViewById(R.id.graph1);
    LinearLayout graph2 = (LinearLayout) rootView.findViewById(R.id.graph2);
    LinearLayout graph3 = (LinearLayout) rootView.findViewById(R.id.graph3);
    
    TemplatureChart chart1 = new TemplatureChart();
    GraphicalView chartA = chart1.execute(getActivity());  
    graph1.addView(chartA);
    TemplatureChart chart2 = new TemplatureChart();
    GraphicalView chartB = chart2.execute(getActivity());  
    graph2.addView(chartB);
    TemplatureChart chart3 = new TemplatureChart();
    GraphicalView chartC = chart3.execute(getActivity());  
    graph3.addView(chartC);
    
[/code]

実行結果は下記のようになります。

![実行結果](https://i.stack.imgur.com/AQY8V.png)  
上記のように大きなレイアウト入れたビューのグラフが消えてしまいます。

この問題の原因と解決方法をご存知の方は御教授いただければ幸いです。  
よろしくお願いします。


CC BY-SA 3.0
2015-01-21T17:01:57.907
5015
2015-01-23T16:56:26.423
2015-01-22T14:29:45.227
4978
7652
question
android android-support-library
Androidグラフ描画ライブラリAChartEngine：大きいレイアウトで表示時にグラフが消える問題


グラフが消える理由ですが、LogCatに以下のような原因が出ていないでしょうか？

> Path too large to be rendered into a texture

Android 4.0以降では、デフォルトでハードウェアレンダリングが有効となっているのですが、このときOpenGLの制約として`2048 x 2048
px`を超える巨大なテクスチャを扱えないというものがあります。

端末密度にもよりますが`2000 x 100dp`ですとその制約を超えるチャートを、テクスチャとして描画しようとして失敗しているのかと思われます。

横長の曲線グラフを表示したい場合、`HorizontalScrollView`で囲うのではなく、グラフを表示するレイアウト自体は`width="match_parent"`を指定した上で、

[code]

    // Y軸方向のみスクロールを許可
    renderer.setPanEnabled(true, false);
    // （ほとんどの場合）余計なズーム機能が付いてくるので無効化
    renderer.setZoomEnabled(false, false);
    // 表示するX軸の最大値を設定
    renderer.setXAxisMax(4);
    // スクロール範囲を固定
    double[] panLimits = {1, 12, 0, 0};
    renderer.setPanLimits(panLimits);
    
[/code]

のような形でスクロールを実現するのがいいかと思います。


CC BY-SA 3.0
2015-01-22T14:12:24.913
5095
2015-01-22T14:20:40.193
2015-01-22T14:20:40.193
5337
5337
5015
answer


御回答頂きありがとうございます。  
Logcatには御指摘頂きました通り【Path too large to be rendered into a texture】  
が出力されていました。

また、グラフの消える境界値を調査した値が2040～2050dpでしたので、  
制約の理由だということで納得することができました。

横長グラフにつきましても、的確なソースコードの設定箇所をご教授頂き有難うございます。  
achartengineの使用方法のいい勉強になりました。

大変参考になりました。  
ありがとうございました。


CC BY-SA 3.0
2015-01-23T16:56:26.423
5173
2015-01-23T16:56:26.423
7653
5015
answer