Страницы

Поиск по вопросам

воскресенье, 8 марта 2020 г.

Создание анимации через потоки на Android

#java #android #многопоточность #canvas #анимация


Здравствуйте, стоит задача, на языке Java под ОС Android нужно написать задачу: создать
снеговика и сделать так, чтобы его составляющие объекты меняли цвет с разной скоростью.
Смена цветов должна быть реализована в потоке.
У меня получилось написать код, но не понимаю, как именно эта анимация должна в этот
поток помещаться. Вот собственно полный код, написан в Eclipse:

package ru.ucheba;

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.os.Bundle;
import android.os.SystemClock;
import android.view.View;

public class Zadanie2 extends Activity {
    int a = 255;
    int r = 100;
    int g = 0;
    int b = 0;

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

    }

    class Panel extends View {
        public Panel(Context context) {
            super(context);
        }

        @Override
        public void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            Paint p1 = new Paint();
            p1.setStyle(Style.FILL);

            p1.setARGB(a, r, g, b);
            canvas.drawCircle(270, 170, 70, p1);
            for (int i = 0; i < 5; i++) {
                r--;
                SystemClock.sleep(10);
                invalidate();
            }

            for (int j = 0; j < 15; j++) {
                p1.setARGB(a, r, g, b);
                g--;
                canvas.drawCircle(270, 310, 100, p1);
                SystemClock.sleep(20);
                invalidate();
            }

            for (int k = 0; k < 30; k++) {
                p1.setARGB(a, r, g, b);
                b--;
                canvas.drawCircle(270, 510, 150, p1);
                SystemClock.sleep(40);
                invalidate();
            }
        }

        class Task extends Thread {
            @Override
            public void run() {

            }
        }
    }
}


Чем заполнять метод run() понимаю, но ругается либо на canvas, p1, или invalidate().
Прошу помощи
    


Ответы

Ответ 1



Ваш код принципиально неверен. В методе onDraw() нельзя вызывать sleep() и invalidate(). Это все вместе с изменением переменных argb должно происходить в отдельном потоке, а метод onDraw() только отрисовывать экран в соответствии с их состоянием. @Override public void onDraw(Canvas canvas) { super.onDraw(canvas); p.setARGB(a, r1, g1, b1); canvas.drawCircle(270, 170, 70, p); p.setARGB(a, r2, g2, b2); canvas.drawCircle(270, 310, 100, p); p.setARGB(a, r3, g3, b3); canvas.drawCircle(270, 510, 150, p); } Перенести в конструктор и сделать переменной класса: p = new Paint(); p.setStyle(Style.FILL); В run() меняйте rX, gX, bX как вам надо и вызывайте синхронно с основным потоком invalidate() когда надо перерисовать.

Ответ 2



Выполнил вот таким образом, может кому-то поможет. Думаю, этот код можно написать гораздо лучше. Поэтому кто сможет, укажите на ошибки, буду благодарен. 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; public class Zadanie2 extends Activity { int[] Colo = { 10, 20, 30 }; // массив со значениями исп. для цветов // снеговика public Thread myThread1, myThread2, myThread3; // создание переменных для потоков @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(new Panel(this)); // использование класса Panel в качестве активити myThread1 = new Thread(new Runnable() { @Override public void run() { int znak = 1; while (true) { if ((znak > 0) && (Colo[0] > 250)) { znak = -znak; } if ((znak < 0) && (Colo[0] < 5)) { znak = -znak; } Colo[0] += znak; try { Thread.sleep(30); } catch (InterruptedException e) { e.printStackTrace(); } } } }); myThread2 = new Thread(new Runnable() { @Override public void run() { int znak2 = 1; while (true) { if ((znak2 > 0) && (Colo[1] > 250)) { znak2 = -znak2; } if ((znak2 < 0) && (Colo[1] < 5)) { znak2 = -znak2; } Colo[1] += znak2; try { Thread.sleep(30); } catch (InterruptedException e) { e.printStackTrace(); } } } }); myThread3 = new Thread(new Runnable() { @Override public void run() { int znak3 = 1; while (true) { if ((znak3 > 0) && (Colo[2] > 250)) { znak3 = -znak3; } if ((znak3 < 0) && (Colo[2] < 5)) { znak3 = -znak3; } Colo[2] += znak3; try { Thread.sleep(30); } catch (InterruptedException e) { e.printStackTrace(); } } } }); // запуск потоков myThread1.start(); myThread2.start(); myThread3.start(); } class Panel extends View { public Panel(Context context) { super(context); } @Override public void onDraw(Canvas canvas) { super.onDraw(canvas); float w, h, cx, cy, radius; // переменные, для адаптивного расположения снеговика w = getWidth(); // считывает ширину h = getHeight(); // считывает высоту cx = w / 2; cy = h / 2; // для ориентации экрана if (w > h) { radius = h / 8; } else { radius = w / 8; } Paint p1 = new Paint(); p1.setStyle(Paint.Style.FILL); p1.setColor(Color.rgb(Colo[0], 255, 255)); canvas.drawCircle(cx, cy - h / 3, radius, p1); Paint p2 = new Paint(); p2.setStyle(Paint.Style.FILL); p2.setColor(Color.rgb(255, Colo[1] * 2, 255)); canvas.drawCircle(cx, cy - h / 3 + radius * 2, (float) (radius * 1.5), p2); Paint p3 = new Paint(); p3.setStyle(Paint.Style.FILL); p3.setColor(Color.rgb(255, 255, Colo[2] * 3)); canvas.drawCircle(cx, cy - h / 3 + radius * 5, radius * 2, p3); invalidate(); // перерисовка объектов } } }

Комментариев нет:

Отправить комментарий