Пробую это с утра, но не могу заставить работать.
Я пытаюсь создать что-то вроде длинной тени для TextView, которая похожа на следующее:
http://www.iceflowstudios.com/v3/wp-content/uploads/2013/07/long_shadow_banner.jpg http://web3canvas.com/wp-content/uploads/2013/07/lsd-ps-action-720x400.png
Мое решение до сих пор заключалось в том, чтобы создать множество TextView и каскадировать их друг под другом, но есть много проблем с производительностью, если я буду придерживаться текущего пути.
Другое решение - использование специального шрифта, который имеет такое же очарование, но я не могу найти ни одного шрифта, который соответствует шрифту, который я использую в настоящее время.
Поэтому мне было интересно, можно ли использовать: (я должен упомянуть, что текстовые представления создаются динамически)
TV.setShadowLayer(1f, 5f, 5f, Color.GREY);
Чтобы создать несколько из них в линию (как каскадный слой), чтобы тень казалась гладкой? Или вы, ребята, предлагаете какие-нибудь другие решения?
Заранее спасибо.
3 ответа
Попробуйте поиграть с растровыми изображениями:
- Определите границы текста с помощью
Paint.getTextBounds()
метод - Создайте прозрачный
Bitmap
с такими показателями(W + H) x H
(вы можете использоватьBitmap.Config.ALPHA_8
для оптимизации использования памяти) - Нарисуйте текст на этом
Bitmap
в позиции0x0
- Скопируйте первую строку
Bitmap
в новую с исходной шириной, но с высотой1px
- Обходите
Y-axis
изBitmap
(сверху вниз) и нарисуйте однострочныйBitmap
с соответствующим смещением наX-axis
(некоторые прозрачные пиксели будут перекрыты) - Теперь у вас есть верхняя часть вашей тени
- Нарисуйте нижнюю часть, используя ту же технику, но выбрав последний ряд этого
Bitmap
Этот алгоритм можно оптимизировать, если вы обнаружите, что все пиксели в последней строке имеют одинаковый цвет (полная тень).
ОБНОВЛЕНИЕ 1
Такого результата я добился с помощью этого быстрого решения:
MainActivity.java
import android.app.Activity;
import android.os.Bundle;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle state) {
super.onCreate(state);
LongShadowTextView longShadow = new LongShadowTextView(this);
longShadow.setText("Hello World");
setContentView(longShadow);
}
}
LongShadowTextView.java
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.view.View;
public class LongShadowTextView extends View {
private Bitmap mBitmap;
private String mText;
public LongShadowTextView(Context context) {
super(context);
}
public void setText(String text) {
Paint paint = new Paint();
// TODO provide setters for these values
paint.setColor(Color.BLACK);
paint.setTextSize(142);
Rect rect = new Rect();
paint.getTextBounds(text, 0, text.length(), rect);
Bitmap bitmap = Bitmap.createBitmap(rect.width() + rect.height(), rect.height(), Bitmap.Config.ALPHA_8);
Canvas canvas = new Canvas(bitmap);
canvas.drawText(text, 0, rect.height(), paint);
Rect src = new Rect();
RectF dst = new RectF();
int w = bitmap.getWidth();
int h = bitmap.getHeight();
src.left = 0;
src.right = w;
for (int i = 0; i < h; ++i) {
src.top = i;
src.bottom = i + 1;
dst.left = 1;
dst.top = i + 1;
dst.right = 1 + w;
dst.bottom = i + 2;
canvas.drawBitmap(bitmap, src, dst, null);
}
mText = text;
mBitmap = bitmap;
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(mBitmap, 0, 0, null);
}
}
ОБНОВЛЕНИЕ 2
Вот окончательный результат, которого я добился. Скопируйте эту демонстрацию из github.
Небольшой комментарий, если кто-то попытается запустить метод setText (). сейчас он не работает. Вы должны вызвать invalidate (); в setText (); метод
public void setText(String value) {
boolean changed =
mText == null && value != null || mText != null && !mText.equals(value);
mText = value;
if (changed) {
refresh();
}
invalidate();
}
Боюсь, что предложенный вами подход к использованию setShadowLayer()
не сработает, поскольку этот подход эффективно рисует второй TextPaint с размытием.
Наложение нескольких TextPaints друг на друга будет означать, что вам нужно смещать их на 1 пиксель для каждого шага, что очень графически интенсивно и будет иметь очень низкую производительность.
Это отличный вопрос и настоящий вызов!
Единственное решение, которое приходит на ум, - обрабатывать каждый глиф независимо, проверяя все элементы контура и увеличивая тень между самой дальней нижней левой и верхней правой точкой. Это кажется очень сложным, и я не знаю, есть ли в SDK какие-либо механизмы, облегчающие такой подход.
Предлагаемое чтение:
- Этот вопрос касается получения путей глифов из TTF.
- Этот ответ показывает, как можно использовать пути, хотя это касается подхода JavaScript.
drawPath()
. Для расширения тени вам нужно будет перемещаться по пути и определять границы каждого закрытого пути, чтобы выяснить, как расширить его внутри представления.
Похожие вопросы
Связанные вопросы
Новые вопросы
java
Java — это высокоуровневый объектно-ориентированный язык программирования. Используйте этот тег, если у вас возникли проблемы с использованием или пониманием самого языка. Этот тег часто используется вместе с другими тегами для библиотек и/или фреймворков, используемых разработчиками Java.
mBitmap
внутрь методаonDraw()
и нарисовать исходный текст над тенью.