Intereting Posts
Команда ADB перечисляет только количество запущенных приложений на устройстве Android устарел модуль apache (HttpClient, HttpResponse и т. Д.) Android-декодер-> декодирование возвращено false для Bitmap download Отправляйте SMS до тех пор, Потребление памяти андроидов Xamarin растет бесконечно после того, как использование достигнет определенного порога Какова история с пространством имен Android для Android? Как получить список фреймов ключевых кадров (синхронизирующих кадров) для видеофайла в Android? Значок на Android TabHost Google navigation api для проезда Получить толкаемый идентификатор для определенного значения в firebase android React native: как получить размер файла, тип mime и расширение? Android-приложение для Android с автономной базой данных Android: активируйте взаимодействие для переключения между активностью, например, Tab Tab Management «Это приложение не будет работать, если вы не обновите сервисы Google Play», когда приложение установлено на реальном устройстве Создание потока, который отменяет вызов InputStream.read (), если прошло время «x»

Android-трейлер

В моем приложении есть шары, которые просто пролетают через дисплей. Они рисуют, как я хочу. Но теперь я хочу проследить за ними.

Все, что я мог сделать, это просто рисовать canvas.drawPath примерно следующим образом:

У меня сейчас

Но это не то, что я хочу. Он должен иметь указанный хвост и цвет градиента следующим образом:

Я хочу чтобы

Я понятия не имею, как это сделать. Пробовал BitmapShader – не мог сделать что-то правильно. Помоги пожалуйста.

Код:

Прежде всего, есть класс Point для отображения позиции:

 class Point { float x, y; ... } 

И след хранится как очередь Point :

 private ConcurrentLinkedQueue<Point> trail; 

Неважно, как это заполняется, просто знайте, что он имеет ограничение по размеру:

 trail.add(position); if(trail.size() > TRAIL_MAX_COUNT) { trail.remove(); } 

И рисунок произошел в методе DrawTrail :

 private void DrawTrail(Canvas canvas) { trailPath.reset(); boolean isFirst = true; for(Point p : trail) { if(isFirst) { trailPath.moveTo(px, py); isFirst = false; } else { trailPath.lineTo(px, py); } } canvas.drawPath(trailPath, trailPaint); } 

Кстати, trailPaint – это просто толстая краска 🙂

 trailPaint = new Paint(); trailPaint.setStyle(Paint.Style.STROKE); trailPaint.setColor(color); trailPaint.setStrokeWidth(radius * 2); trailPaint.setAlpha(150); 

Я вижу, что вы хотите увидеть градиент на шаре, вы можете использовать что-то вроде этого

  int x1 = 0, y1 = 0, x2 = 0, y2 = 40; Shader shader = new LinearGradient(0, 0, 0, 40, Color.WHITE, Color.BLACK, TileMode.CLAMP); trailPaint = new Paint(); trailPaint.setShader(shader); 

Это то, что вы должны изменить свой trailPaint и посмотреть, работает ли он.

Отсюда .

Я нашел решение. Но все же думайте, что это не самый лучший.

Прежде всего, для этой задачи используются поля класса.

 static final int TRAIL_MAX_COUNT = 50; //maximum trail array size static final int TRAIL_DRAW_POINT = 30; //number of points to split the trail for draw private ConcurrentLinkedQueue<Point> trail; private Paint[] trailPaints; private float[][] trailPoss, trailTans; private Path trailPath; 

Кроме объекта trailPath я использовал объект PathMeasure для разделения пути на несколько равных частей.

После заполнения объекта массива trail добавлен вызов функции вычисления траектории.

 lastTrailAdd = now; trail.add(pos.Copy()); if (trail.size() > TRAIL_MAX_COUNT) { trail.remove(); } FillTrail(); 

Затем моя функция FillTrail .

 private void FillTrail() { trailPath.reset(); boolean isFirst = true; for(Point p : trail) { if(isFirst) { trailPath.moveTo(px, py); trailPoss[0][0] = px; trailPoss[0][1] = py; isFirst = false; } else { trailPath.lineTo(px, py); } } PathMeasure path = new PathMeasure(trailPath, false); float step = path.getLength() / TRAIL_DRAW_POINT; for(int i=0; i<TRAIL_DRAW_POINT; i++) { path.getPosTan(step * i, trailPoss[i], trailTans[i]); } } 

Он отделен от рисованной нитки. Следующий код – это функция рисования.

 private void DrawTrail(Canvas canvas) { if(trail.size() > 1) { float prevWidthHalfX = 0f, prevWidthHalfY = 0f, prevX = 0f, prevY = 0f; Path trailStepRect = new Path(); boolean isFirst = true; for (int i = 0; i < TRAIL_DRAW_POINT; i++) { float currWidthHalf = (float) (radius) * i / TRAIL_DRAW_POINT / 2f, currWidthHalfX = currWidthHalf * trailTans[i][1], currWidthHalfY = currWidthHalf * trailTans[i][0], currX = trailPoss[i][0], currY = trailPoss[i][1]; if (!isFirst) { trailStepRect.reset(); trailStepRect.moveTo(prevX - prevWidthHalfX, prevY + prevWidthHalfY); trailStepRect.lineTo(prevX + prevWidthHalfX, prevY - prevWidthHalfY); trailStepRect.lineTo(currX + currWidthHalfX, currY - currWidthHalfY); trailStepRect.lineTo(currX - currWidthHalfX, currY + currWidthHalfY); canvas.drawPath(trailStepRect, trailPaints[i]); } else { isFirst = false; } prevX = currX; prevY = currY; prevWidthHalfX = currWidthHalfX; prevWidthHalfY = currWidthHalfY; } } } 

Главным моментом этого является рисование следов по частям с разными красками. Ближе к мячу – шире след. Я думаю, что буду оптимизировать его, но он уже работает.

Если вы хотите посмотреть, как это выглядит, просто установите мое приложение из игры Google .