9

I am successfully displaying pie chart using achart engine.I want to customize my labels text size according to the screen size.Thanks in advance.

hcp
  • 279
  • 1
  • 5
  • 13

7 Answers7

23

This problem comes down to resolution. achartengine seems to have been designed with raw pixels in mind while display quality and pixel density has increased dramatically over the last couple years. The labels from the achartengine sample are tiny on my HTC One!

Android has introduced scale-independent pixels. The key to using them with achartengine is the TypedValue class. Here's what I did:

DisplayMetrics metrics = context.getResources().getDisplayMetrics();
float val = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 18, metrics);

I got 18 from "text size medium" in the link above.

You can then use val anywhere you want to use medium sized text. For example:

renderer.setLabelsTextSize(val);
Andy Gaskell
  • 31,495
  • 6
  • 74
  • 83
13

This a summarised version of what I did:

public static final int TEXT_SIZE_XHDPI = 24;
public static final int TEXT_SIZE_HDPI = 20;
public static final int TEXT_SIZE_MDPI = 18;
public static final int TEXT_SIZE_LDPI = 13;

XYMultipleSeriesRenderer renderer = new XYMultipleSeriesRenderer();

    switch (getResources().getDisplayMetrics().densityDpi) {
        case DisplayMetrics.DENSITY_XHIGH:
                renderer.setMargins(new int[] { 40, 90, 25, 10 });
                renderer.setAxisTitleTextSize(Constants.TEXT_SIZE_XHDPI);
                renderer.setChartTitleTextSize(Constants.TEXT_SIZE_XHDPI);
                renderer.setLabelsTextSize(Constants.TEXT_SIZE_XHDPI);
                renderer.setLegendTextSize(Constants.TEXT_SIZE_XHDPI);
                break;
        case DisplayMetrics.DENSITY_HIGH:
                renderer.setMargins(new int[] { 30, 50, 20, 10 });
                renderer.setAxisTitleTextSize(Constants.TEXT_SIZE_HDPI);
                renderer.setChartTitleTextSize(Constants.TEXT_SIZE_HDPI);
                renderer.setLabelsTextSize(Constants.TEXT_SIZE_HDPI);
                renderer.setLegendTextSize(Constants.TEXT_SIZE_HDPI);
                break;
        default:
                renderer.setMargins(new int[] { 30, 50, 20, 10 });
                renderer.setAxisTitleTextSize(Constants.TEXT_SIZE_LDPI);
                renderer.setChartTitleTextSize(Constants.TEXT_SIZE_LDPI);
                renderer.setLabelsTextSize(Constants.TEXT_SIZE_LDPI);
                renderer.setLegendTextSize(Constants.TEXT_SIZE_LDPI);
                break;
    }

So I basically customised the margins and text sizes of the chart depending of the device's screen density. Note: I excluded the medium density case for now.

Ryan
  • 1,331
  • 2
  • 12
  • 18
  • It is not good idea to hard-code the sizes. I have proposed a better, more flexible solution. – Athlan Aug 06 '13 at 10:17
3

I wrote two methods called _dp and _sp to convert to dp and sp values.

private DisplayMetrics displayMetrics;
private boolean isPortrait;
int _dp(float pixels) {
   return (int)(pixels * displayMetrics.density);
}
float _sp(float pixels) {
    return (pixels * displayMetrics.scaledDensity);
}

In your onCreate you need to set the displayMetrics value:

displayMetrics = (this.getResources()).getDisplayMetrics();

Then you just use _sp and _dp to get the sp/dp value. For instance to set a font scaled to 18

renderer.setAxisTitleTextSize(_sp(18));

And to set margins with dp values:

renderer.setMargins(new int[] {_dp(25), _dp(30), _dp(35), _dp(20)});

NOTE: I made one change to this code. It is possible to get a 0 value for these functions -- which is a real problem if you are dividing by the return value. I added a test to return 1 if the return value is < 1. ie: return ((rv < 1) ? 1 : v);

steven smith
  • 1,519
  • 15
  • 31
2

You can set the labels text size this way:

renderer.setLabelsTextSize(size);

You will have to find the best logic for finding the best proportion between the screen size and the labels size.

Dan D.
  • 32,246
  • 5
  • 63
  • 79
2

The best practice is to place dummy TextView into layout to obtain the textSize:

<TextView
        android:id="@+id/dummyTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:visibility="gone"
        android:text="TextView" />

And in your code for example:

TextView testTextView = (TextView) rootView.findViewById(R.id.dummyTextView);
float textSize = testTextView.getTextSize();
renderer.setLabelsTextSize(textSize);
renderer.setLegendTextSize(textSize);
Athlan
  • 6,389
  • 4
  • 38
  • 56
2

I think the best way to do it is to define sizes in the file dimens.xml in dp and sp like so:

<dimen name="graph_chart_text_size">16sp</dimen>
<dimen name="graph_axis_title_text_size">14sp</dimen>
<dimen name="graph_labels_text_size">12sp</dimen>
<dimen name="graph_labels_padding">5dp</dimen>
<dimen name="graph_legend_text_size">14sp</dimen>
<dimen name="graph_legend_height">40dp</dimen>
<dimen name="graph_point">3dp</dimen>
<dimen name="graph_line">3dp</dimen>
<dimen name="graph_margin_top">10dp</dimen>
<dimen name="graph_margin_left">40dp</dimen>
<dimen name="graph_margin_right">10dp</dimen>
<dimen name="graph_margin_bottom">20dp</dimen>

And then use getDimension and getDimensionPixelOffset to convert to pixels when configuring the renderer, such as:

renderer.setChartTitleTextSize(context.getResources().getDimension(R.dimen.graph_chart_text_size));
renderer.setAxisTitleTextSize(context.getResources().getDimension(R.dimen.graph_axis_title_text_size));
renderer.setLabelsTextSize(context.getResources().getDimension(R.dimen.graph_labels_text_size));
renderer.setLegendTextSize(context.getResources().getDimension(R.dimen.graph_legend_text_size));
renderer.setLegendHeight(context.getResources().getDimensionPixelOffset(R.dimen.graph_legend_height));
renderer.setMargins(new int[]{
        context.getResources().getDimensionPixelOffset(R.dimen.graph_margin_top),
        context.getResources().getDimensionPixelOffset(R.dimen.graph_margin_left_mood),
        context.getResources().getDimensionPixelOffset(R.dimen.graph_margin_bottom),
        context.getResources().getDimensionPixelOffset(R.dimen.graph_margin_right)});
    }

I testing in phones that range from 800x480 to 1920x1080 and the design is very consistent.

Tiago A.
  • 2,568
  • 1
  • 22
  • 27
0

You can try this:

renderer.setLegendTextSize(textSize);
trinaldi
  • 2,872
  • 2
  • 32
  • 37
h.boulla
  • 21
  • 1