Урок 144. Рисование. Matrix-преобразования

Обсуждение уроков
Ответить
Аватара пользователя
damager82
Администратор
Сообщения: 1383
Зарегистрирован: 07 янв 2012, 11:32
Контактная информация:

Урок 144. Рисование. Matrix-преобразования

Сообщение damager82 » 24 фев 2014, 05:00

В этом уроке:
- используем Matrix для геометрических преобразований фигур


Click here to read this article!
Последний раз редактировалось damager82 29 май 2017, 23:20, всего редактировалось 3 раза.
Добро пожаловать на форум сайта StartAndroid
ИзображениеИзображение

Sunnar
Сообщения: 3
Зарегистрирован: 15 фев 2014, 23:21

Re: Урок 144. Рисование. Matrix-преобразования

Сообщение Sunnar » 24 фев 2014, 22:58

Спасибо за урок! Вопрос появился: в setContentView мы ставим view, а не layout-файл, как в этом случае добавлять кнопки и т.д. или самим рисовать и в обработчике касания проверять когда нажимаешь? Еще не получается перейти в другой активити из-за того, что класс, который рисует фигуры наследует View, а не Activity, что можно сделать?

Аватара пользователя
damager82
Администратор
Сообщения: 1383
Зарегистрирован: 07 янв 2012, 11:32
Контактная информация:

Re: Урок 144. Рисование. Matrix-преобразования

Сообщение damager82 » 25 фев 2014, 20:37

Вы можете использовать этот DrawView в своем layout-файле, как обычный View.

Для этого вынесите его из Activity в отдельный класс DrawView.
Конструктор надо будет добавить:
[syntax=java]public class DrawView extends View {

public DrawView(Context context) {
this(context, null);
}

public DrawView(Context context, AttributeSet attrs) {
super(context, attrs);
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.GREEN);
}

}[/syntax]

А в layout пропишите так:
[syntax=xml] <ru.startandroid.develop.p1431drawingpath.DrawView
android:layout_width="300dp"
android:layout_height="200dp" />[/syntax]

Ну и хелп посмотрите на эту тему
http://developer.android.com/training/c ... index.html
Добро пожаловать на форум сайта StartAndroid
ИзображениеИзображение

Аватара пользователя
damager82
Администратор
Сообщения: 1383
Зарегистрирован: 07 янв 2012, 11:32
Контактная информация:

Re: Урок 144. Рисование. Matrix-преобразования

Сообщение damager82 » 25 фев 2014, 20:38

А чтобы вызывать другое Activity вам достаточно Context, который в конструкторе приходит.
Метод startActivity у него есть.
Добро пожаловать на форум сайта StartAndroid
ИзображениеИзображение

sheyninvlad
Сообщения: 1
Зарегистрирован: 04 апр 2014, 11:22

Re: Урок 144. Рисование. Matrix-преобразования

Сообщение sheyninvlad » 04 апр 2014, 11:56

Выделил DraView в отдельный файл. добавил его в разметку, но при обращении к нему по findViewById получаю ошибку.
Помогите пожалуйста понять в чем ошибка. (в строке myDraw.clearPath();) ошибка NullPointerException - то есть получается что findViewById возвращает NULL

Код: Выделить всё

public class MainActivity extends Activity {
    DrawView myDraw;
    Button myButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        myButton = (Button)findViewById(R.id.button);
        myButton.setText("myButton");

    }
    public void onClickButton(View v)
    {
        myDraw=new DrawView(this);
        myDraw= (DrawView)findViewById(R.id.thisDrawView);
        myDraw.clearPath();
    }
activity_main.xml

Код: Выделить всё

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context="ru.startandroid.develop.p1411canvasview.MainActivity">

    <TextView
        android:text="@string/hello_world"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/textView" />

    <ru.startandroid.develop.p1411canvasview.DrawView
        android:layout_width="300dp"
        android:layout_height="200dp"
        android:id="@+id/thisDrawView"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="New Button"
        android:id="@+id/button"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:onClick="onClickButton"/>

</RelativeLayout>

DrawView

Код: Выделить всё

class DrawView extends View {
        public DrawView(Context context,AttributeSet attrs)
        {
            this(context);
        }

        Paint p;
        Path path;
        Point point1;
        Point point21;
        Point point22;


        public DrawView(Context context) {
            super(context);
            p = new Paint(Paint.ANTI_ALIAS_FLAG);
            p.setStrokeWidth(3);
            path = new Path();
            point1 = new Point(200,300);
            point21 = new Point(500,600);
            point22 = new Point(900,200);
            path.reset();
            path.moveTo(100,100);
        }
        //переменные для координат
        float x = 0;
        float y = 0;
        //прямо в классе DrawView реализуем метод onTouchEvent() без присвоения OnTouchListener,
        //затем вызываем invalidate(), который, в сою очередь,     вызовет onDraw()
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            if(event.getAction() == MotionEvent.ACTION_DOWN){
                x = event.getX();
                y = event.getY();
                //point1.x= (int) x;
                //point1.y=(int) y;
                path.lineTo(x,y);
                invalidate();
                Log.d("LOGTAG", "x=" + x + " y=" + y);
            }
            return true;
        }
        public void clearPath()
        {
            Log.d("LOGTAG", "Clearpath");
            path.reset();
            path.moveTo(100,100);
            path.lineTo(150,150);
            invalidate();
        }
      @Override
        protected void onDraw(Canvas canvas) {
            canvas.drawARGB(80, 102, 204, 255);
            // точка отклонения для первой линии
            p.setStyle(Paint.Style.STROKE);
            p.setColor(Color.RED);
            canvas.drawPath(path,p);
        }
    }

Аватара пользователя
damager82
Администратор
Сообщения: 1383
Зарегистрирован: 07 янв 2012, 11:32
Контактная информация:

Re: Урок 144. Рисование. Matrix-преобразования

Сообщение damager82 » 04 апр 2014, 23:14

sheyninvlad писал(а):Выделил DraView в отдельный файл. добавил его в разметку, но при обращении к нему по findViewById получаю ошибку.
Помогите пожалуйста понять в чем ошибка. (в строке myDraw.clearPath();) ошибка NullPointerException - то есть получается что findViewById возвращает NULL
Я немного неверно описал конструкторы. Исправил свое предыдущее сообщение, теперь должно работать.
[syntax=java] public DrawView(Context context) {
this(context, null);
}

public DrawView(Context context, AttributeSet attrs) {
super(context, attrs);
}[/syntax]
Добро пожаловать на форум сайта StartAndroid
ИзображениеИзображение

OrcSin
Сообщения: 8
Зарегистрирован: 18 дек 2014, 12:45

Re: Урок 144. Рисование. Matrix-преобразования

Сообщение OrcSin » 09 окт 2015, 18:42

API 16, AndroidStudio
Скопировал весь листинг в студию:

Код: Выделить всё

package ru.startandroid.develop.p1441matrixtransform;

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

public class MainActivity extends Activity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(new DrawView(this));
  }

  class DrawView extends View {

    Paint p;
    Path path;
    Matrix matrix;

    public DrawView(Context context) {
      super(context);
      p = new Paint();
      p.setStrokeWidth(3);
      p.setStyle(Paint.Style.STROKE);

      path = new Path();
      matrix = new Matrix();
    }

    @Override
    protected void onDraw(Canvas canvas) {
      canvas.drawARGB(80, 102, 204, 255);

      // создаем крест в path
      path.reset();
      path.addRect(300, 150, 450, 200, Path.Direction.CW);
      path.addRect(350, 100, 400, 250, Path.Direction.CW);

      // рисуем path зеленым
      p.setColor(Color.GREEN);
      canvas.drawPath(path, p);

      // настраиваем матрицу на перемещение на 300 вправо и 200 вниз
      matrix.reset();
      matrix.setTranslate(300, 200);
      
      // применяем матрицу к path
      path.transform(matrix);

      // рисуем path синим
      p.setColor(Color.BLUE);
      canvas.drawPath(path, p);

    }

  }

}
, запустил, один квадрат перекрывает второй, то есть не хватает две полосы, нет как бы прозрачности.
Так же почему то не срабатывает трансформация:

Код: Выделить всё

// настраиваем матрицу на перемещение на 300 вправо и 200 вниз
      matrix.reset();
      matrix.setTranslate(300, 200);
      
      // применяем матрицу к path
      path.transform(matrix);
Фигура зелёного цвета закрашивается синим цветом и всё.

В чём может быть ошибка, если листинг полностью копирую без изменений.

lightstar
Сообщения: 3
Зарегистрирован: 09 мар 2016, 15:59

Re: Урок 144. Рисование. Matrix-преобразования

Сообщение lightstar » 10 мар 2016, 11:06

На версии 4.1 (API 16), удалось получить правильный результат только так.

Код: Выделить всё

        @Override
        protected void onDraw(Canvas canvas) {
            canvas.drawARGB(80, 102, 204, 255);

            // создаем крест в path
            path.reset();
            path.addRect(300, 150, 450, 200, Path.Direction.CW);
            path.addRect(350, 100, 400, 250, Path.Direction.CW);
            path.close();

            // рисуем path зеленым
            p.setColor(Color.GREEN);
            canvas.drawPath(path, p);

            // настраиваем матрицу на перемещение на 300 вправо и 200 вниз
            matrix.reset();
            matrix.setTranslate(300, 200);

            // применяем матрицу к path
            path.transform(matrix, pathDst);
            pathDst.close();

            // рисуем path синим
            p.setColor(Color.BLUE);
            canvas.drawPath(pathDst, p);
        }
Т.е., во-первых, перед выводом на канву path надо закрывать (path.close()). Во-вторых, нужно использовать вариант метода path.transform с двумя параметрами, используя для результата другой экземпляр path (pathDst в коде выше). В третьих, после применения матрицы path нужно тоже закрывать (pathDst.close()). Иначе трансформация не работает почему-то, и крест выводится криво (как будто нет прозрачности, как указали выше).

Segen
Сообщения: 2
Зарегистрирован: 20 фев 2016, 11:54

Re: Урок 144. Рисование. Matrix-преобразования

Сообщение Segen » 27 мар 2016, 16:00

У меня также один зеленый прямоугольник перекрывал другой (в эмуляторе версия 5.1.0). Погуглил и понял, что это как-то связано с включением по умолчанию аппаратного ускорения, начиная с версии Android 3.0 (API level 11). Если в конструкторе DrawView выключить аппаратное ускорение, вставив строку this.setLayerType(View.LAYER_TYPE_SOFTWARE, null), то всё отображается корректно.

Ответить