Android自定义View实现HTML图文环绕效果

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

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

 

代码如下:
TextView tv  =  new TextView  (  this  )  ; 
        
SpannableString spanStr  =  new SpannableString  (  "掌声那历史的房间里是副经理撒旦法阿斯顿及福利费是到发顺丰"  )  ; 
ImageSpan imageSpan  =  new ImageSpan  (  this, R.  drawablea  )  ; 
spanStr.  setSpan  (imageSpan,  35, Spannable.  SPAN_INCLUSIVE_INCLUSIVE  )  ; 
tv.  setText  (spanStr  )  ; 
        
setContentView  (tv  )  ;

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

代码如下:

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

 

 

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  (  PaintANTI_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  (  ColorRED  )  ; 
        
     } 
    
    

    @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  (  IntegerMAX_VALUE, widthMeasureSpec  )  ; 
            measureAndSplitText  (mPaint, mText, size  )  ; 
             final  int textWidth  = textSize  [  0  ], textHeight  = textSize  [  1  ]  ; 
            w  += textWidth  ;  //内容宽度 
             if  (< textHeight  )  {  //内容高度 
                h  =  (  int  ) textHeight  ; 
             } 
         } 
        
        w  =  Mathmax  (w, getSuggestedMinimumWidth  (  )  )  ; 
        h  =  Mathmax  (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  ()  ; 
            canvas.  drawText  (line.  text, line.  x, line.  y, mPaint  )  ; 
         } 
         Systemoutprintln  (mTextLines  )  ; 
     } 
    
    
     public  void setImageBitmap  (Bitmap bm  )  { 
        setImageBitmap  (bm,  null  )  ; 
     } 
    
     public  void setImageBitmap  (Bitmap bm,  int left,  int top  )  { 
        setImageBitmap  (bm,  new Rect  (left, top,  00  )  )  ; 
     } 
    
     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  +  "]"  ; 
         } 
     } 
}

 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值