Чтобы создать объект изображения, нужно переопределить View. Назовём наш объект ChartView:
Рассмотрим наш класс подробнее.
- public class ChartView extends View {
- private int width = 10;
- ArrayList<ChartItem> charts;
- int max = 0;
- ShapeDrawable background;
- public ChartView(Context context, ArrayList<ChartItem> charts, int top, int bgColor) {
- super(context);
- Resources res = getResources();
- int ws = res.getDisplayMetrics().widthPixels;
- ArrayList<ChartItem> gencharts = new ArrayList<ChartItem>();
- for (ChartItem ci : charts) {
- int[] points = scaleTo(ci.getPoints(), top);
- ArrayList<ShapeDrawable> myDraws = new ArrayList<ShapeDrawable>();
- for (int i=0; i<points.length; i++) {
- int h = points[i];
- ShapeDrawable mDrawable = new ShapeDrawable(new RectShape());
- mDrawable.getPaint().setColor(ci.getColor());
- mDrawable.getPaint().setAlpha(ci.getAlpha());
- mDrawable.setBounds(width*i, top-h, width*(i+1), top);
- mDrawable.getPaint().setShader(new LinearGradient(width*i, top-h, width*(i+1), top-h, ci.getColor(), Color.WHITE, Shader.TileMode.REPEAT));
- myDraws.add(mDrawable);
- }
- ci.setDraws(myDraws);
- gencharts.add(ci);
- }
- this.charts = gencharts;
- background = new ShapeDrawable(new RectShape());
- background.setBounds(0, 0, ws, top);
- background.getPaint().setColor(bgColor);
- }
- @Override
- protected void onDraw(Canvas canvas) {
- background.draw(canvas);
- for (ChartItem ci : charts) {
- ArrayList<ShapeDrawable> draws = ci.getDraws();
- for (int i=0; i<draws.size(); i++) {
- ShapeDrawable d = draws.get(i);
- d.draw(canvas);
- }
- }
- }
- private int getMax(int[] ii) {
- for (int i : ii) {
- if (max<i) max = i;
- }
- return max;
- }
- private int[] scaleTo(int[] ii, int vmax) {
- int[] scaled = new int[ii.length];
- double k = (double) vmax / getMax(ii);
- for(int i=0; i<ii.length; i++) {
- scaled[i] = (int) (ii[i]*k);
- }
- return scaled;
- }
- }
В конструктор обязательно нужно передавать Context - его мы сразу же отдадим в конструктор предка. Кроме этого в конструктор мы передаём массив объектов ChartItem, которые представляют данные для каждой из диаграмм, которые мы собираемся построить на нашем изображении. Следующие два параметра общие для всех диаграмм на изображении: максимальная высота и фон.
В строках 9-10 получаем текущую ширину экрана, чтобы полностью закрасить её фоном.
Все графические примитивы создаются как объекты ShapeDrawable. В конструкторе мы устанавливаем параметры для прямоугольников, составляющих столбцы диаграмм: ширину, высоту, цвет. Делаем их симпатичнее с помощью градиента (строка 22). Все созданные объекты должны быть нарисованы на канве, для чего переопределяем метод protected void onDraw(Canvas canvas) и в нём для всех ShapeDrawable вызываем метод draw(canvas) (строки 35-44). Делать это нужно в правильном порядке: следующий объект будет рисоваться поверх предыдущего.
Определённая сложность есть в расчёте высоты столбцов диаграммы: нужно чтобы они поместились в максимальную высоту и при этом сохранили пропорции. Это решаем с помощью метода private int[] scaleTo(int[] ii, int vmax) в который передаём массив данных для конкретной диаграммы и максимальную высоту. На выходе получаем уже масштабированный массив (строки 53-60).
Добавляя в setContentView вашего Activity созданный экземпляр СhartView, получаете результат вроде того, что на картинке. В данном случае выбран серый фон и две диаграммы с прозрачностью 50% синего и зелёного цвета.
Круто, но где описание класса ChartItem?
ОтветитьУдалитьНа самом деле круто. Но сложновато без разъяснения всех строк и команд. Если бы автор расписал все от А до Я то тогда бы эта статья имела море просмотров.
ОтветитьУдалить