Snippet: align a TextView around an image

A few weeks ago I discovered the Spans on Android,after reading the wonderful post by Flavien Laurent.

In this post I will describe how to realize a particular layout not very common on Android: a text around an image.

This layout is not an Android Pattern, but it can be useful in same cases.
As always it is just an example, and you should improve some points in your real project.

Use a simple layout:

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <TextView
                android:id="@+id/text"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"></TextView>

            <ImageView
                android:id="@+id/icon"
                android:src="@drawable/rectangle"
                android:layout_width="150dp"
                android:layout_height="150dp"></ImageView>

        </RelativeLayout>

    </ScrollView>

To achieve our scope, we can use a LeadingMarginSpan.LeadingMarginSpan2.
This span allows the implementor to specify the number of lines of text to which this object is attached that the "first line of paragraph" margin width will be applied to.

    /**
     *
     */
    class MyLeadingMarginSpan2 implements LeadingMarginSpan.LeadingMarginSpan2 {

        private int margin;
        private int lines;

        MyLeadingMarginSpan2(int lines, int margin) {
            this.margin = margin;
            this.lines = lines;
        }

        /**
         * Apply the margin
         *
         * @param first
         * @return
         */
        @Override
        public int getLeadingMargin(boolean first) {
            if (first) {
                return margin;
            } else {
                return 0;
            }
        }

        @Override
        public void drawLeadingMargin(Canvas c, Paint p, int x, int dir,
                                      int top, int baseline, int bottom, CharSequence text,
                                      int start, int end, boolean first, Layout layout) {}

        @Override
        public int getLeadingMarginLineCount() {
            return lines;
        }
    };

We only need to calculate the number of lines where we would like applying a margin and the right margin.
In this case we will get number of lines = height of image and margin = width of image + little extra margin.

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mTextView = (TextView) findViewById(R.id.text);
        mImageView = (ImageView) findViewById(R.id.icon);

        final ViewTreeObserver vto = mImageView.getViewTreeObserver();
        vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                mImageView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                finalHeight = mImageView.getMeasuredHeight();
                finalWidth = mImageView.getMeasuredWidth();
                makeSpan();
            }
        });
    }
}

This code can be improved.
I am using a very simple (and raw) float textLineHeight = mTextView.getPaint().getTextSize(); to calculate the number of lines.
You can add paddings, margins or you can use a Rect to calculate the text bounds.

    /**
     * This method builds the text layout
     */
    private void makeSpan() {

        /**
         * Get the text
         */
        String plainText=getResources().getString(R.string.text_sample);

        int allTextStart = 0;
        int allTextEnd = htmlText.length() - 1;

        /**
         * Calculate the lines number = image height.
         * You can improve it... it is just an example
         */
        int lines;
        Rect bounds = new Rect();
        mTextView.getPaint().getTextBounds(plainText.substring(0,10), 0, 1, bounds);

        //float textLineHeight = mTextView.getPaint().getTextSize();
        float fontSpacing=mTextView.getPaint().getFontSpacing();
        lines = (int) (finalHeight/fontSpacing);

        /**
         * Build the layout with LeadingMarginSpan2
         */
        MyLeadingMarginSpan2 span = new MyLeadingMarginSpan2(lines, finalWidth +10 );
        mSpannableString.setSpan(span, allTextStart, allTextEnd,
                   Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

        mTextView.setText(mSpannableString);
    }

You can get code from GitHub:

时间: 2024-10-07 21:19:37

Snippet: align a TextView around an image的相关文章

TextView实战之你真的懂我么?

不要以为别人是赢在了起跑线上,他们其实生在了终点. 写在前面的话 对于TextView,我想大家都已经熟的不能再熟了.但是它的用法我们真的熟么?为了避免总是一言不合就去翻官方文档,在这里我总结一下我也可能是你容易忽视的一些细节. TextView设置基础 字符串资源里变量替换 Android开发中是拒绝硬编码的,我们可能会把一些字符串放在xml中当作资源使用,假设有如下情况: <string name="welcome">你好A,欢迎使用我们的App.</string

Android之TextView文字绘制流程

一:TextView的onDraw()方法: 1.第一句restartMarqueeIfNeeded()绘制字幕滚动. protected void onDraw(Canvas canvas) { restartMarqueeIfNeeded(); // Draw the background for this view super.onDraw(canvas); ...} 首先我们看一个东西: android.text.TextUtils.java public enum TruncateAt

TextView 的隐藏技能

TextView 的隐藏技能 字符串资源里变量替换 Android开发中是拒绝硬编码的,我们需要把一些字符串放在xml中当作资源使用,假设有如下情况: <string name="welcome">你好A,欢迎使用我们的App.</string> 我们在程序中需要使用这个字符串,但是A是一个变量,很常规的办法是取出这个字符串,然后用String的replace方法把A替换成用户的昵称. 其实,在android中有这样一个东西,那就是 XLIFF,全称叫 XML

textview 显示html方法解析

现在网络的繁盛时代,光文字是不能满足人们的胃口的,图片,flash,音频,视频就成为浏览网页的主流显示,在手机上也一样.在手机上显示从网络端获取的数据显示,大家很自然的想起两种方式,一种就是webview,一种就是TextView.当然webView直接显示html页面就行了,我主要说的TextView显示html内容. 首先,说下TextView到底支持那些标签呢,通过对源码的查看,发现Textview可以解析一部分html标签,如: 复制代码代码如下: <a href="...&quo

TextView的纵向排列

通用情况下,我们都是用TextView的横向排列,但有时候需求需要用到纵向排列,此时就傻眼了,本人也因此摘了两篇文章,供参考: 1.仅文字方向纵向排列,文字并没有翻转 public class VerticalTextView extends TextView{ final boolean topDown; public VerticalTextView(Context context, AttributeSet attrs){ super(context, attrs); final int

TextView 高级教程

前言 光看题目,估计有人已经忍不住吐槽了:尼玛,TextView 这么简单的控件,还有什么高级用法吗?放在以前,我也会这么想,但是随着开发经验的积累,我愈发觉得 TextView 简直就是一座宝藏,里面有很多宝贝值得研究. 本文基于 @Chiuki 的讲座,并结合我自己的经验整理而成. 视频地址:Youtube 讲稿地址:Github 部分 demo 对应的代码地址:Github 文章中的大部分图片和代码均摘自讲稿,感谢原作者的分享. Compound Drawable 如下图1中的效果,我们可

歌词 Lrc 自定义TextView

演示     <uses-permission android:name="android.permission.INTERNET" />     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />     <uses-permission android:name="android.permission.READ_EXTER

TextView里的文 html

一.[Android实例]实现TextView里的文字有不同颜色 转eoe:http://www.eoeandroid.com/thread-4496-1-1.html import android.text.Html; TextView t3 = (TextView) findViewById(R.id.text3);        t3.setText(            Html.fromHtml(                "<b>text3:</b>  

Android自定义控件垂直TextView

正常情况下TextView的文本内容是水平显示的,那如何做到让内容垂直显示呢,于是做了一些尝试,自定义控件继承TextView,重写onDraw函数,代码如下: @Override protected void onDraw(Canvas canvas) { canvas.rotate(-90); canvas.translate(-getHeight(), 0); super.onDraw(canvas); } 以上实现确实做到了让内容垂直显示,但是存在宽度与高度无法适配的问题,比如在指定宽度