Android中并没有提供HTML图文环绕效果的View,最接近的算是TextView中的ImageSpan了,但并未完全实现图文环绕(图文混排)的效果。

1、Android系统TextView的ImageSpan实现图文环绕

代码如下:

1
2
3
4
5
6
7
8
TextView tv = new TextView ( this ) ;

SpannableString spanStr = new SpannableString ( "掌声那历史的房间里是副经理撒旦法阿斯顿及福利费是到发顺丰" ) ;
ImageSpan imageSpan = new ImageSpan ( this, R. drawable. a ) ;
spanStr. setSpan (imageSpan, 3, 5, Spannable. SPAN_INCLUSIVE_INCLUSIVE ) ;
tv. setText (spanStr ) ;

setContentView (tv ) ;


2、Android中自定义View实现图文环绕

代码如下:

1
2
3
4
FloatImageText view = new FloatImageText ( this ) ;
view. setText ( "电视里发生了房间里是积分拉萨积分拉萨积分拉萨减肥啦空间 撒旦法发大水发撒旦法看完了鸡肉味容积率为热键礼物i经二路文件容量为积分拉萨解放路口上飞机撒离开房间爱水立方法拉圣诞节福禄寿" ) ;
Bitmap bm = BitmapFactory. decodeResource (getResources ( ), R. drawable. a ) ;
view. setImageBitmap (bm, 30, 30 ) ;
package com.orgcent.view ;

import java.util.ArrayList ;

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.Paint.FontMetrics ;
import android.util.AttributeSet ;
import android.util.DisplayMetrics ;
import android.view.View ;
/**
* 模拟CSS中的float浮动效果
*/

public class FloatImageText extends View {
private Bitmap mBitmap ;
private final Rect bitmapFrame = new Rect ( ) ;
private final Rect tmp = new Rect ( ) ;
private int mTargetDentity = DisplayMetrics. DENSITY_DEFAULT ;

private final Paint mPaint = new Paint ( Paint. ANTI_ALIAS_FLAG ) ;
private String mText ;
private ArrayList <TextLine > mTextLines ;
private final int [ ] textSize = new int [ 2 ] ;

public FloatImageText ( Context context, AttributeSet attrs, int defStyle ) {
super (context, attrs, defStyle ) ;
init ( ) ;
}

public FloatImageText ( Context context, AttributeSet attrs ) {
super (context, attrs ) ;
init ( ) ;
}

public FloatImageText ( Context context ) {
super (context ) ;
init ( ) ;
}

private void init ( ) {
mTargetDentity = getResources ( ). getDisplayMetrics ( ). densityDpi ;
mTextLines = new ArrayList <TextLine > ( ) ;

mPaint. setTextSize ( 14 ) ;
mPaint. setColor ( Color. RED ) ;

}



@Override
protected void onMeasure ( int widthMeasureSpec, int heightMeasureSpec ) {
int w = 0, h = 0 ;
//图片大小
w += bitmapFrame. width ( ) ;
h += bitmapFrame. height ( ) ;

//文本宽度
if ( null != mText && mText. length ( ) > 0 ) {
mTextLines. clear ( ) ;
int size = resolveSize ( Integer. MAX_VALUE, widthMeasureSpec ) ;
measureAndSplitText (mPaint, mText, size ) ;
final int textWidth = textSize [ 0 ], textHeight = textSize [ 1 ] ;
w += textWidth ; //内容宽度
if (h < textHeight ) { //内容高度
h = ( int ) textHeight ;
}
}

w = Math. max (w, getSuggestedMinimumWidth ( ) ) ;
h = Math. max (h, getSuggestedMinimumHeight ( ) ) ;

setMeasuredDimension (
resolveSize (w, widthMeasureSpec ),
resolveSize (h, heightMeasureSpec ) ) ;
}

@Override
protected void onDraw ( Canvas canvas ) {
//绘制图片
if ( null != mBitmap ) {
canvas. drawBitmap (mBitmap, null, bitmapFrame, null ) ;
}

//绘制文本
TextLine line ;
final int size = mTextLines. size ( ) ;
for ( int i = 0 ; i < size ; i ++ ) {
line = mTextLines. get (i ) ;
canvas. drawText (line. text, line. x, line. y, mPaint ) ;
}
System. out. println (mTextLines ) ;
}


public void setImageBitmap (Bitmap bm ) {
setImageBitmap (bm, null ) ;
}

public void setImageBitmap (Bitmap bm, int left, int top ) {
setImageBitmap (bm, new Rect (left, top, 0, 0 ) ) ;
}

public void setImageBitmap (Bitmap bm, Rect bitmapFrame ) {
mBitmap = bm ;
computeBitmapSize (bitmapFrame ) ;
requestLayout ( ) ;
invalidate ( ) ;
}

public void setText ( String text ) {
mText = text ;
requestLayout ( ) ;
invalidate ( ) ;
}

private void computeBitmapSize (Rect rect ) {
if ( null != rect ) {
bitmapFrame. set (rect ) ;
}
if ( null != mBitmap ) {
if (rect. right == 0 && rect. bottom == 0 ) {
final Rect r = bitmapFrame ;
r. set (r. left, r. top,
r. left + mBitmap. getScaledHeight (mTargetDentity ),
r. top + mBitmap. getScaledHeight (mTargetDentity ) ) ;
}
} else {
bitmapFrame. setEmpty ( ) ;
}
}

private void measureAndSplitText ( Paint p, String content, int maxWidth ) {
FontMetrics fm = mPaint. getFontMetrics ( ) ;
final int lineHeight = ( int ) (fm. bottom - fm. top ) ;

final Rect r = new Rect (bitmapFrame ) ;
// r.inset(-5, -5);

final int length = content. length ( ) ;
int start = 0, end = 0, offsetX = 0, offsetY = 0 ;
int availWidth = maxWidth ;
TextLine line ;
boolean onFirst = true ;
boolean newLine = true ;
while (start < length ) {
end ++;
if (end == length ) { //剩余的不足一行的文本
if (start <= length - 1 ) {
if (newLine ) offsetY += lineHeight ;
line = new TextLine ( ) ;
line. text = content. substring (start, end - 1 ) ;
line. x = offsetX ;
line. y = offsetY ;
mTextLines. add (line ) ;
}
break ;
}
p. getTextBounds (content, start, end, tmp ) ;
if (onFirst ) { //确定每个字符串的坐标
onFirst = false ;
final int height = lineHeight + offsetY ;
if (r. top >= height ) { //顶部可以放下一行文字
offsetX = 0 ;
availWidth = maxWidth ;
newLine = true ;
} else if (newLine && (r. bottom >= height && r. left >= tmp. width ( ) ) ) { //中部左边可以放文字
offsetX = 0 ;
availWidth = r. left ;
newLine = false ;
} else if (r. bottom >= height && maxWidth - r. right >= tmp. width ( ) ) { //中部右边
offsetX = r. right ;
availWidth = maxWidth - r. right ;
newLine = true ;
} else { //底部
offsetX = 0 ;
availWidth = maxWidth ;
if (offsetY < r. bottom ) offsetY = r. bottom ;
newLine = true ;
}
}

if (tmp. width ( ) > availWidth ) { //保存一行能放置的最大字符串
onFirst = true ;
line = new TextLine ( ) ;
line. text = content. substring (start, end - 1 ) ;
line. x = offsetX ;
mTextLines. add (line ) ;
if (newLine ) {
offsetY += lineHeight ;
line. y = offsetY ;
} else {
line. y = offsetY + lineHeight ;
}

start = end - 1 ;
}
}
textSize [ 1 ] = offsetY ;
}

class TextLine {
String text ;
int x ;
int y ;

@Override
public String toString ( ) {
return "TextLine [text=" + text + ", x=" + x + ", y=" + y + "]" ;
}
}
}

更多相关文章

  1. 自定义View实现HTML图文环绕效果
  2. 【Android】虚拟环绕声
  3. 在文字周围环绕一层阴影效果[android:shadow] 使用
  4. MixtureTextView 支持Android图文混排、文字环绕图片等效果
  5. android的数据库API操作
  6. android TextView 容纳不下内容,让字向左滚动的办法

随机推荐

  1. Android之VideoView播放视频
  2. 平安金融科技移动技术周报(第六期)
  3. appium(一) 自动测试环境搭建
  4. Android(安卓)Studio(二):基本配置
  5. Android(安卓)App内文档展示方案整理
  6. Appium移动自动化框架初探
  7. Android学习系列一用按钮实现显示时间
  8. 谷歌宣布Android(安卓)Studio将取代Eclip
  9. Android(安卓)蓝牙相关开发
  10. Android(安卓)实现锚点定位