Android TextView长影

时间:2014-10-12 14:20:08

标签: java android xml textview

我从早上开始尝试这个,但我无法让它发挥作用。

我要做的是为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并将它们相互级联,但如果我按照当前的方式使用它会有很多性能问题。

另一种解决方案是使用具有类似诱惑力的自定义字体,但我找不到与我当前使用的字体相匹配的字体。

所以我想知道,是否可以使用:(我必须提一下,textviews是动态创建的)

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

要在一行中创建多个(作为级联图层),使阴影看起来很平滑?或者你们建议其他任何解决方案吗?

提前致谢。

3 个答案:

答案 0 :(得分:12)

尝试使用光栅图像:

  1. 使用Paint.getTextBounds()方法
  2. 检测文本范围
  3. 使用此类指标Bitmap创建透明的(W + H) x H(您可以使用Bitmap.Config.ALPHA_8来优化内存使用情况)
  4. Bitmap位置0x0上绘制文字
  5. Bitmap第一行行复制到原始宽度的新行中,但高度为1px
  6. 迭代Y-axis Bitmap(从上到下)并绘制单行Bitmap,其对应的偏移量为X-axis(您将透支一些透明像素) )
  7. 现在你拥有阴影的顶部
  8. 使用相同的技术绘制底部,但选择此Bitmap最后
  9. 如果您检测到最后一行中的所有像素具有相同的颜色(全阴影),则可以优化此算法。

    更新1

    我使用这个快速解决方案实现了这样的结果:

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

    更新2

    这是我取得的最终结果。从github克隆this demo

    enter image description here

答案 1 :(得分:1)

我担心你建议的使用setShadowLayer()的方法不会起作用,因为这种方法会有效地绘制第二个带有模糊的TextPaint。

将几个TextPaints叠加在一起将基本上意味着您需要为每个步骤将其偏移1px,这非常非常图形密集且性能非常差。

这是一个很好的问题,也是一个真正的挑战!

想到的唯一解决方案是独立处理每个字形,检查所有路径元素并在最远的左下角和右上角之间扩展阴影。这看起来非常复杂,我不知道SDK中是否有任何机制可以促进这样的方法。

建议阅读:

答案 2 :(得分:0)

如果有人试图运行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();
}