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:

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

  1. textview 显示html方法解析

    现在网络的繁盛时代,光文字是不能满足人们的胃口的,图片,flash,音频,视频就成为浏览网页的主流显示,在手机上也一样.在手机上显示从网络端获取的数据显示,大家很自然的想起两种方式,一种就是webvi ...

  2. Android之TextView文字绘制流程

    一:TextView的onDraw()方法: 1.第一句restartMarqueeIfNeeded()绘制字幕滚动. protected void onDraw(Canvas canvas) { r ...

  3. TextView里的文 html

    一.[Android实例]实现TextView里的文字有不同颜色 转eoe:http://www.eoeandroid.com/thread-4496-1-1.html import android. ...

  4. 自定义控件 TextView 歌词 Lrc

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

  5. Android的TextView使用Html来处理图片显示、字体样式、超链接等

    一.[Android实例]实现TextView里的文字有不同颜色 转eoe:http://www.eoeandroid.com/thread-4496-1-1.html import android. ...

  6. Android 获取View的高度或TextView的行数, 实现自适应的textview

    大家都遇到过项目中需要获控件的的高度或者列如文章开头说TextView的行数 但是很多人在实际操作中getLineCount()获取到值是零,其实只是我们没在正确的位置获取. 这是因为activtiy ...

  7. 【转载】TextView源码解析

    原文地址:https://github.com/7heaven/AndroidSdkSourceAnalysis/blob/master/article/textview%E6%BA%90%E7%A2 ...

  8. 关于textview显示特殊符号居中的问题

    话说这是2017年的第一篇博客,也是一篇技术博客.先从简单的一篇解决问题开始吧,千里之行,始于足下! ------------------------------------------------- ...

  9. 奇葩问题-TextView无法获取值

    问题场景 前几天写一个界面的时候,遇到一个非常奇葩的问题.app第一次安装的时候,这里针对用户第一次安装的时候,后来是不会出现这个问题了.我明明是对某个界面的一个textview赋值了,而且服务端也返 ...

随机推荐

  1. Sudoku Solver Backtracking

    该博客好好分析 Write a program to solve a Sudoku puzzle by filling the empty cells. Empty cells are indicat ...

  2. log-malloc2 0.2.4 发布

    log-malloc2 0.2.4 发布了,该版本修复了日志格式输出的 bug. og-malloc2 是一个 malloc 日志预加载库,用于检测内存泄漏问题.

  3. Linux Kernel 3.11 正式版发布

    Linus 发布 了 3.11 版本的 Linux 内核.该版本值得关注的新特性有: Lustre 分布式文件系统.透明的 ARM 架构的大数据页支持:ARM64 上的 Xen 和 KVM 虚拟化:O ...

  4. http://www.cnbeta.com/articles/306769.htm

    事实上,很少有方法可以帮你做到.有些人可能会想到试着把Vim打造成C语言IDE的,比如c.vim:也有把Vim集成到Eclipse里的Eclim .但是我想要告诉你的是一个更加通用的,只用插件实现的方 ...

  5. Asp.Net Web API 2第六课——Web API路由和动作选择

    Asp.Net Web API 导航 Asp.Net Web API第一课——入门http://www.cnblogs.com/aehyok/p/3432158.html Asp.Net Web AP ...

  6. 记录ASP.NET Web API 服务接口响应时间

    实现起来很简单,一个Filter就可以搞定!!! /// <summary> /// 监控接口执行时间 /// </summary> public class TimingAc ...

  7. Mac OS X上用CoreCLR运行一个真正的.NET控制台程序

    这个真正的控制台程序来自corefxlab,名叫CoreClrHelloWorld,是一个跨平台的.NET控制台演示程序,可以显示微软.Linux.苹果的logo. CoreClrHelloWorld ...

  8. javascript中的call()和apply()方法的使用

    1.方法定义 call方法: 语法:call([thisObj[,arg1[, arg2[,   [,.argN]]]]]) 定义:调用一个对象的一个方法,以另一个对象替换当前对象. 说明: call ...

  9. 设计模式之美:Adapter(适配器)

    索引 别名 意图 结构 参与者 适用性 效果 相关模式 实现 实现方式(一):简单直接的对象适配器. 实现方式(二):实现双向类适配器. 别名 包装器(Wrapper) 意图 将一个类的接口转换成客户 ...

  10. RoboGuice :Could not load finalizer in its own class loader 警告

    RoboGuice提示的错误信息 01-17 11:48:14.929: W/nalizableReferenceQueue(1871): Could not load Finalizer in it ...