Android TextView Long Shadow

I tried this in the morning, but I can't get it to work.

What I'm trying to do is create a somewhat long shadow for the TextView, which is similar to the following:

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

My solution so far has been to create many text elements and cascade them under each other, but there are many performance problems if I go with the current way.

Another solution is to use a custom font that has a similar allure, but I cannot find one that matches the font that I am currently using.

So I was wondering if it is possible to use: (I have to mention, text views are created dynamically)

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

To create several of them in a line (like a cascade layer), make the shadow smooth? Or do you offer any other solutions?

Thanks in advance.

+8
java android design xml textview
source share
3 answers

Try playing with bitmaps:

  • Define text boundaries using the Paint.getTextBounds() method
  • Create a transparent Bitmap with such metrics (W + H) x H (you can use Bitmap.Config.ALPHA_8 to optimize memory usage)
  • Draw text on this Bitmap at 0x0 position
  • Copy the first line of Bitmap to a new one with the original width, but with a height of 1px
  • Let's move on to the Y-axis from Bitmap (top to bottom) and draw a single-line Bitmap with the appropriate offset on the X-axis (you will overload a few transparent pixels).
  • You now have the top of your shadow.
  • Draw the bottom using the same technique, but selecting the last line of this Bitmap

This algorithm can be optimized if you find that all the pixels in the last row have the same color (full shadow).

UPDATE 1

I achieved this result using this quick solution:

enter image description here

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); } } 

UPDATE 2

Here is the end result that I have achieved. Clone this demo from github.

enter image description here

+12
source share

I am afraid that your proposed approach of using setShadowLayer() will not work, as this approach effectively draws a second TextPaint with blur.

Putting several text labels on top of each other essentially means that you need to compensate for it by 1 pixel for each step, which is very graphically intensive and will have very low performance.

This is a great question and a real challenge!

The only solution that comes to mind is to process each glyph independently, checking all the elements of the path and expanding the shadow between the farthest left and top right points. It seems very complicated, and I don’t know if there is any mechanics in the SDK that facilitates this approach.

Recommended reading:

  • This question decides to get glyph paths from TTF.
  • This answer illustrates how you can use path usage , although this pertains to the JavaScript approach.
+1
source share

A short comment if someone tries to run the setText () method. now it does not work. You must call invalidate (); in setText (); Method

  public void setText(String value) { boolean changed = mText == null && value != null || mText != null && !mText.equals(value); mText = value; if (changed) { refresh(); } invalidate(); } 
0
source share

All Articles