Ещё немного о 2D графике под Android

Здравствуйте, читатели Хабра!

Не так давно я начал изучать программирование под Android и некоторое время назад столкнулся с проблемой, решением которой хочу поделиться со всеми, кто ещё не начинал, но планирует посвятить себя разработке приложений под эту платформу.

Немного теории

1) Обычно при поиске основ 2D графики под Android вы встретите примеры расширения класса View. В этом случае мы, по сути, рисуем статичную картинку, либо выводим уже существующую.

2) Рисование происходит с использованием класса Canvas. Если обратиться к аналогии, то это — ваш холст, на котором вы, словно вдохновлённый музой художник, творите свои шедевры. Мы в этом топике шедевры творить не будем, но основы взаимодействия постараемся обозначить.

3) Вывод рисунка на экран происходит добавлением объекта созданного класса на экран.

Напомню, что про основы графики в Android уже шла речь. Давайте немного дополним существующую статью.

Возникшая проблема

Увлечённо проделывая различные интересные и не очень задания, я столкнулся с задачей, поставившей меня в тупик. Её суть состояла в том, что необходимо было выводить наши «шедевры» непосредственно на уже созданную область, изменять рисунки по нажатию кнопки и прочие довольно тривиальные с первого взгляда вещи.

Радостно вздохнув, я понёсся штудировать мануалы и не нашёл ничего, что помогло бы мне в этом деле, потому что, в основном, все ссылки пестрели выводом непосредственно класса, расширяющего View, а не добавлением его на существующую область.

Теперь, когда мы определили задачу, приступим к её решению.

Решение задачи

Для того, чтобы проиллюстрировать работу, сформулируем задание. Пусть на каждое нажатие кнопки у нас выводится треугольник.

Итак, для начала импортируем нужные пакеты, хотя многие, наверняка, импортируют их непосредственно по мере надобности:

import java.util.Random;

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup.LayoutParams; 


Великолепно. Теперь нам необходимо создать кнопку, на которую мы и будем кликать. Идём в /res/layout/activity_main.xml и дописываем необходимые данные. Например, так:

<Button
        android:id="@+id/Button1"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/TextView1"
        android:layout_below="@+id/TextView1"
        android:layout_marginTop="35dp"
        android:onClick="onClick"
        android:text="@string/click" />


Здесь TextView1 — стандартный, оставшийся от дефолтного проекта. Теперь, при нажатии на кнопку, будет вызываться метод onClick, который и должен будет выводить на экран новый треугольник.

Некоторое время поискав в Сети, мне не удалось найти примеров, когда класс, расширяющий View рисовал бы на уже существующим layout, потому, поломав голову, я решил немного переработать уже существующую задачу.

Для начала создадим второй класс, назвав его, например, DrawTriangles, конструктор и метод onDraw, где, собственно, будем рисовать.


import android.content.Context;
import android.graphics.Canvas;
import android.view.View;

public class DrawTriangles extends View {

	public DrawTriangles(Context context) {
		super(context);
	}
	
	@Override
	public void onDraw(Canvas c) {
		super.onDraw(c);
	}

}


Теперь подумаем над рисованием треугольника. Задача достаточно тривиальная и не требует особенного напряжения. Добавляем шесть координат и рисуем линии, связывающие их между собой.


                    
           float x = 350;
		   float y = 250;
		   float x1 = 950;
		   float y1 = 250;
		   float x2 = 950;
		   float y2 = 1050;
		    
		  
		    paint.setColor(Color.BLUE);
		    c.drawLine(x, y, x1, y1, paint);
		    c.drawLine(x1, y1, x2, y2, paint);
		    c.drawLine(x2, y2, x, y, paint);



Все приготовления готовы, можно орудовать с главным классом.

Добавляем метод onClick:


public void onClick(View v){
}


Теперь нам необходимо по его вызову добавить на экран нарисованный треугольник. Очевидно, что для этого понадобится объект класса DrawTriangles

DrawTriangles d = new DrawTriangles(this);


Теперь необходимо добавить полученный элемент на экран. Нам известен метод setContentView, но он не добавляет элементы, а заменяет ими всё остальное, потому нам не подходит. Подумав, я пришёл к выводу, что, наверняка, существует метод addContentView. И, о правда, такой метод существует. Давайте его рассмотрим:

public void addContentView (View view, ViewGroup.LayoutParams params)


Первый элемент — то, что мы будем добавлять, а второй — параметры его отображения. Нам необходимо вывести треугольник, потому не будем особенно извращаться:
addContentView(d,new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));


Великолепно. Теперь осталось только запустить приложение и полюбоваться тем, что получилось.

Результаты

image

И после нажатия на кнопку (у меня выводится другой треугольник! В данном топике описано построение прямоугольного треугольника):

image

Надеюсь, что это поможет кому-нибудь, кто, как и я, будет искать необходимый материал, но уже не потратит время на подобные манипуляции. Успеха!
  • –6
  • 2,9k
  • 4
Поделиться публикацией
Ой, у вас баннер убежал!

Ну. И что?
Реклама
Комментарии 4
    +2
    А в чем главный смысл этой статьи? Показать как рисовать на View или как добавлять View к разметке? Извините, я какого-либо полезного посыла не нашел
      +1
      Я своей целью обозначил обозначить примитивы добавления View на существующую разметку. Дело в том, что почти везде в основах графики говорится, что разметка не нужна при работе с графикой и все взаимодействия сводятся непосредственно к работе с классом, расширяющим View. Возможно, эта статья убережёт кого-то ещё от длительных поисков.

      З.Ы. Либо я просто не умею гуглить, что также присуще не мне одному.
    +2
    Если ваша задача рисовать графику — то стоит использовать SurfaceView и рисовать на его канвасе.
    Если задача строить интерактивный интерфейс — используйте View.
    Случаев, когда стоит писать своего наследника View, не так много, и на мой взгляд этого стоит избегать. Для их написание надо понимать системный фреймворк, когда, в каком порядке и в каком потоке вызываются методы (там далеко не только onDraw, там еще onLayout, onMeasure и т.д.)
    Мне кажется статья ни о чем и может только подтолкнуть в неправильную сторону начинающих.

    Я пишу довольно давно, а от класса View не наследовался ни разу (наследовался от более выскоуровневых элементов вроде ListView, когда их поведения не хватает).

    Тут поведения никакого нет, поэтому и смысла кастомизировать нету. В крайнем случае можно создать в коде Bitmap, нарисовать на его канвасе треугольник и сунуть какому-нибудь ImageView. Это и то более правильный путь.

    P.S. По нажатию на кнопку у ImageView можно заменить картинку быстрее и проще.
    P.S.S. AddContentView использовать не понятно зачем, вы знаете куда в иерархию он добавит созданную View? Кто будет родителем и какие LayoutParams передавать?

    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

    Самое читаемое