android 图文 环绕实现

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

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

Android中TextView实现图文环绕

代码如下:

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


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

android自定义view实现图文环绕

代码如下:

FloatImageText view  =  new FloatImageText ( this ) ;
view. setText ( "电视里发生了房间里是积分拉萨积分拉萨积分拉萨减肥啦空间  撒旦法发大水发撒旦法看完了鸡肉味容积率为热键礼物i经二路文件容量为积分拉萨解放路口上飞机撒离开房间爱水立方法拉圣诞节福禄寿" ) ;
Bitmap bm  = BitmapFactory. decodeResource (getResources ( ), R. drawable. a ) ;
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 ( 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 ( <  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  +   "]" ;
         }
     }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值