Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android TextView Long Shadow

I've been trying this since morning, yet I can't get it to work.

What I'm trying to do is create a somewhat like 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 was to create a lot of TextViews and cascade them under each other, but there are a lot of performance issues if I go with the current way.

Another solution is the usage of a custom font that has that similar allure, yet I cannot find any that matches the font I am currently using.

So I was wondering, is it possible to use: (I have to mention, the textviews are created dynamically)

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

To create several of them in a line (as a cascading layer), making the shadow seem smooth? Or do you guys suggest any other solutions?

Thanks in advance.

like image 502
Johnaudi Avatar asked Oct 12 '14 14:10

Johnaudi


1 Answers

Try to play with raster images:

  1. Detect bounds of text using Paint.getTextBounds() method
  2. Create transparent Bitmap with such metrics (W + H) x H (you may use Bitmap.Config.ALPHA_8 to optimize memory usage)
  3. Draw text on this Bitmap at 0x0 position
  4. Copy first row of Bitmap into new one with original width, but with height of 1px
  5. Iterate over the Y-axis of Bitmap (from top to bottom) and draw single-line Bitmap with the corresponding offset by X-axis (you will overdraw some transparent pixels)
  6. Now you have the top-part of your shadow
  7. Draw the bottom part using same technique, but choosing last row of this Bitmap

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

UPDATE 1

I achieved such 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 final result which I achieved. Clone this demo from github.

enter image description here

like image 188
Oleksii K. Avatar answered Oct 19 '22 22:10

Oleksii K.