Android TextView Long Shadow

Я пробовал это с утра, но я не могу заставить его работать.

То, что я пытаюсь сделать, это создать несколько длинную тень для 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-720×400 .png

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

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

Поэтому мне было интересно, можно ли использовать: (я должен упомянуть, текстовые представления создаются динамически)

TV.setShadowLayer(1f, 5f, 5f, Color.GREY); 

Чтобы создать несколько из них в строке (как каскадный слой), сделать тень гладкой? Или вы предлагаете какие-либо другие решения?

Заранее спасибо.

Попробуйте сыграть с растровыми изображениями:

  1. Обнаружение границ текста с использованием Paint.getTextBounds()
  2. Создайте прозрачный Bitmap с такими метриками (W + H) x H (вы можете использовать Bitmap.Config.ALPHA_8 для оптимизации использования памяти)
  3. Нарисуйте текст на этом Bitmap в позиции 0x0
  4. Скопируйте первый ряд Bitmap в новый с оригинальной шириной, но с высотой 1px
  5. Итерация по Y-axis Bitmap (сверху вниз) и рисование однострочного Bitmap с соответствующим смещением по X-axis (вы будете перегружать некоторые прозрачные пиксели)
  6. Теперь у вас есть верхняя часть вашей тени
  7. Нарисуйте нижнюю часть, используя ту же технику, но выбрав последнюю строку этого 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.

Введите описание изображения здесь

Боюсь, ваш предложенный подход использования setShadowLayer() будет работать, так как этот подход эффективно привлекает второй TextPaint с размытием.

Наложение нескольких TextPaint поверх друг друга будет означать, что вам нужно компенсировать его на 1 пиксель за каждый шаг, что очень графически интенсивно и будет иметь очень низкую производительность.

Это отличный вопрос и настоящий вызов!

Единственное решение, которое приходит на ум, – это обрабатывать каждый глиф независимо, проверяя все элементы пути и расширяя тень между самыми дальними нижними и верхними правыми точками. Это кажется очень сложным, и я не знаю, есть ли какая-либо механика в SDK, которая облегчает такой подход.

Предлагаемое чтение:

  • Этот вопрос решает получить пути глифов от TTF.
  • Этот ответ иллюстрирует, как вы можете использовать пути , хотя это касается подхода JavaScript.

Небольшой комментарий, если кто-то попытается запустить метод 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(); } 
Intereting Posts