Android的图文混合实现之TextView+html加载图片

Android的图文混合实现之TextView+html加载图片

最近在进行notepad的拓展开发,就想要能够在里面进行图片的添加删除,图文混合一起。这种应该要怎么才能实现呢?于是而我在网上搜索了大量的资料。发现实现这种有好几种方法。
TextView:文本展示控件,相信大家肯定都很熟悉了。
在textview中可以用这几种方式实现图片的显示

1.XML文件中指定属性值(activity_main.xml)

在TextView的左上右下显示图片,可用

android:drawableLeft
android:drawableTop
android:drawableRight
android:drawableBottom

代码:


效果图:

Android的图文混合实现之TextView+html加载图片_第1张图片

2. 通过解析HTML来显示图片

直接调用textView的setText(Html.fromHtml(html))的方法,会导致图片加载不出来,形成一个个小方块,

textView.setText(Html.fromHtml(“html”,null,null));

在htmldemo的文件夹下再创建两个子文件夹:html(里面是html的拓展类)

Imageload(里面是图片加载类)

文件目录如下:

Android的图文混合实现之TextView+html加载图片_第2张图片
各个类的作用:

html HtmlUtils: 调用接口Spanned,在TextView中显示html
URLDrawable: 返回异步回调的drawable对象
URLImageGetter: 加载获取图片标签,获得图片内容
URLTagHandler: 标签解析器:处理未知标签
ZoomImageView: 多点触控,手势图片缩放控件
imageload CompressTransformation: 图片压缩转换
ImageLoad : 图片加载url
ImageTransform: 图片缩放转换

(1)加载图片:

用一个类实现接口 Html的ImageGetter

继承于 ImageGetter,重写 getDrawable (String source)
方法。当解析到标签时就会回调getDrawable()方法,通过异步操作,读取本地/网络资源,获得Drawable
对象

URLImageGetter

//URLImageGetter:实现Html类中一个接口ImageGetter,用于检索获取HTML中的标签,给img标签获取图片内容

//URLImageGetter:实现Html类中一个接口ImageGetter,用于检索获取HTML中的标签,给img标签获取图片内容
public class URLImageGetter implements ImageGetter {
    Context c;
    TextView tv_image;
    private List targets = new ArrayList<>();

    public URLImageGetter(TextView t, Context c) {
        this.tv_image = t;
        this.c = c;
        tv_image.setTag(targets);
    }

    @Override
    public Drawable getDrawable(final String source) {
        // 获取图片的url和标签
        final URLDrawable urlDrawable = new URLDrawable();
        final Target target = new Target() {
            @Override
            public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
                Drawable drawable = new BitmapDrawable(bitmap);
                drawable.setBounds(0, 0, bitmap.getWidth(), bitmap.getHeight());
                urlDrawable.setDrawable(drawable);
                urlDrawable.setBounds(0, 0, bitmap.getWidth(), bitmap.getHeight());
                tv_image.invalidate();
                tv_image.setText(tv_image.getText());
            }

            @Override
            public void onBitmapFailed(Drawable errorDrawable) {
                //加载失败
                errorDrawable.setBounds(0, 0, errorDrawable.getIntrinsicWidth(), errorDrawable.getIntrinsicHeight());
                urlDrawable.setBounds(0, 0, errorDrawable.getIntrinsicWidth(), errorDrawable.getIntrinsicHeight());
                urlDrawable.setDrawable(errorDrawable);
                tv_image.invalidate();
            }

            @Override
            public void onPrepareLoad(Drawable placeHolderDrawable) {
                //准备加载
                placeHolderDrawable.setBounds(0, 0, placeHolderDrawable.getIntrinsicWidth(), placeHolderDrawable.getIntrinsicHeight());
                urlDrawable.setBounds(0, 0, placeHolderDrawable.getIntrinsicWidth(), placeHolderDrawable.getIntrinsicHeight());
                urlDrawable.setDrawable(placeHolderDrawable);
                tv_image.invalidate();
            }
        };

        targets.add(target);
        ImageLoad.loadPlaceholder(c, source, target);
        return urlDrawable;
    }

(2)返回异步回调的drawable

怎么把异步回调的drawable返回,因为图片是异步加载的,所以我们要先建立一个BitmapDrawable,当没有异步加载的时候用来getDrawable的返回。可以包装一个drawable,继承于html.drawable,当返回正确drawable的时候填充进去,刷新一下就可以显示内容

URLDrawable

public class URLDrawable extends BitmapDrawable {
    private Drawable drawable;

    @Override
    public void draw(Canvas canvas) {
        if (drawable != null) {
            drawable.draw(canvas);
        }
    }

    public void setDrawable(Drawable drawable) {
        this.drawable = drawable;
    }

加载出来效果:

Android的图文混合实现之TextView+html加载图片_第3张图片
Android的图文混合实现之TextView+html加载图片_第4张图片
Android的图文混合实现之TextView+html加载图片_第5张图片

(3)图片的点击放大

接着在编写一个类继承于 TagHandler,重写
handleTag()方法。支持img标签的点击处理,能够监听到点击事件。

URLTagHandler:

//标签解析器:处理未知标签,
public class URLTagHandler implements TagHandler {

    private Context mContext;
    private PopupWindow popupWindow;
    //需要放大的图片
    private ZoomImageView tecent_chat_image;

    public URLTagHandler(Context context) {
        mContext = context.getApplicationContext();
        View popView = LayoutInflater.from(context).inflate(R.layout.pub_zoom_popwindow_layout, null);
        tecent_chat_image = (ZoomImageView) popView.findViewById(R.id.image_scale_image);

        popView.findViewById(R.id.image_scale_rll).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (popupWindow != null && popupWindow.isShowing()) {
                    popupWindow.dismiss();
                }
            }
        });
        popupWindow = new PopupWindow(popView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        popupWindow.setFocusable(true);
        popupWindow.setOutsideTouchable(true);// 设置允许在外点击消失
        ColorDrawable dw = new ColorDrawable(0x50000000);
        popupWindow.setBackgroundDrawable(dw);
    }

    @Override
    public void handleTag(boolean opening, String tag, Editable output, XMLReader xmlReader) {
        // 处理标签
        if (tag.toLowerCase(Locale.getDefault()).equals("img")) {
            // 获取长度
            int len = output.length();
            // 获取图片地址
            ImageSpan[] images = output.getSpans(len - 1, len, ImageSpan.class);
            String imgURL = images[0].getSource();
            // 使图片可点击并监听点击事件
            output.setSpan(new ClickableImage(mContext, imgURL), len - 1, len, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        }
    }

    private class ClickableImage extends ClickableSpan {
        private String url;
        private Context context;

        public ClickableImage(Context context, String url) {
            this.context = context;
            this.url = url;
        }

        @Override
        public void onClick(View widget) {
            // 进行图片点击之后的处理
            popupWindow.showAtLocation(widget, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, 0);
            final Target target = new Target() {
                @Override
                public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
                    tecent_chat_image.setImageBitmap(bitmap);
                }

                @Override
                public void onBitmapFailed(Drawable errorDrawable) {
                    tecent_chat_image.setImageDrawable(errorDrawable);
                }

                @Override
                public void onPrepareLoad(Drawable placeHolderDrawable) {
                    tecent_chat_image.setImageDrawable(placeHolderDrawable);
                }
            };
            tecent_chat_image.setTag(target);
            ImageLoad.loadPlaceholder(context, url, target);
        }
    }


(4)自定义支持手势缩放

从网上找的代码感觉很好用:

ZoomImageView

import android.content.Context;
import android.graphics.Matrix;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.ScaleGestureDetector.OnScaleGestureListener;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewConfiguration;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.ImageView;
//图片手势缩放,点击放大
public class ZoomImageView extends ImageView implements OnGlobalLayoutListener, OnScaleGestureListener, OnTouchListener {

   private boolean mOnce = false;

   private float mInitScale;
   //初始化的缩放量
   private float mMidScale;
   //最大缩放量
   private float mMaxScale;
   //中间缩放量
   private Matrix mScaleMatrix = null;

   private ScaleGestureDetector mScaleGestureDetector = null;
   //缩放手势监听

   private int mLastPointerCount;
   //触摸点发生移动时的触摸点个数
   private float mLastX;
   private float mLastY;
   //记录移动之前按下去的那个坐标点

   private int mTouchSlop;
   //开始移动的滑动距离
   private boolean isCanDrag;
   //是否可以移动
   private boolean isCheckLeftAndRight;//是否需要考虑left和right出现白边
   private boolean isCheckTopAndBottom;//是否需要考虑top和boottom出现白边

   private GestureDetector mGestureDetector = null;
   //手势监听,如果正在缩放中就不向下执行,防止多次双击
   private boolean isAutoScale;
   /**
    * Matrix的对图像的处理
    * Translate 平移变换
    * Rotate 旋转变换
    * Scale 缩放变换
    * Skew 错切变换
    */


   public ZoomImageView(Context context) {
      this(context , null);
   }

   public ZoomImageView(Context context, AttributeSet attrs) {
      this(context, attrs , 0);
   }

   public ZoomImageView(Context context, AttributeSet attrs, int defStyle) {
      super(context, attrs, defStyle);

      mScaleMatrix = new Matrix();
      setScaleType(ScaleType.MATRIX);//设置缩放类型
      mScaleGestureDetector = new ScaleGestureDetector(context, this);
      setOnTouchListener(this);
      mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();

      mGestureDetector = new GestureDetector(
            context,
            new GestureDetector.SimpleOnGestureListener() {
               @Override
               public boolean onDoubleTap(MotionEvent e) {
                  
                  if(isAutoScale == true) {
                     return true;
                  }
                  //缩放的中心点
                  float x = e.getX();
                  float y = e.getY();

                  //如果当前缩放值小于这个临界值 则进行放大
                  if(getCurrentScale() < mMidScale) {
                     postDelayed(new AutoScaleRunnable(mMidScale, x, y) , 16);
                     isAutoScale = true;
                  }
                  else { //如果当前缩放值大于这个临界值 则进行缩小操作 缩小到mInitScale
                     postDelayed(new AutoScaleRunnable(mInitScale, x, y) , 16);
                     isAutoScale = true;
                  }
                  
                  return true;
               }
            });
   }

   
   /**
    * ImageView
    *图片初始化其大小,把图片定位到屏幕中央,并进行初始化缩放适应屏幕
    */
   @Override
   public void onGlobalLayout() {

      if(mOnce == false) {
         //获取imageview宽高
         int width = getWidth();
         int height = getHeight();
         
         Drawable drawable = getDrawable();
         if(drawable == null) {
            return;
         }
         int drawableWidth = drawable.getIntrinsicWidth();
         int drawableHeight = drawable.getIntrinsicHeight();
         

         float scale = 1.0f;

         // 如果图片的宽或者高大于屏幕,则缩放至屏幕的宽或者高
         if(drawableWidth > width && drawableHeight < height) {
            scale = width * 1.0f / drawableWidth;
         }
         if(drawableWidth < width && drawableHeight > height) {
            scale = height * 1.0f / drawableHeight;
         }

         // 如果宽和高都大于屏幕,则让其按按比例适应屏幕大小
         if(drawableWidth > width && drawableHeight > height) {
            scale = Math.min(width * 1.0f / drawableWidth , height * 1.0f / drawableHeight);
         }
         if(drawableWidth < width && drawableHeight < height) {
            scale = Math.min(width * 1.0f / drawableWidth , height * 1.0f / drawableHeight);
         }

         // 图片移动至屏幕中心
         mInitScale = scale;
         mMidScale = mInitScale * 2;
         mMaxScale = mInitScale * 4;
         int dx = width / 2 - drawableWidth / 2;
         int dy = height / 2 - drawableHeight / 2;
         mScaleMatrix.postTranslate(dx, dy);
         mScaleMatrix.postScale(mInitScale , mInitScale , width / 2 , height / 2);
         setImageMatrix(mScaleMatrix);
         mOnce = true;
      }
   }
   
   @Override
   protected void onAttachedToWindow() {
      super.onAttachedToWindow();
      
      getViewTreeObserver().addOnGlobalLayoutListener(this);
   }
   
   
   @SuppressWarnings("deprecation")
   @Override
   protected void onDetachedFromWindow() {
      super.onDetachedFromWindow();
      
      getViewTreeObserver().removeGlobalOnLayoutListener(this);
   }

   /**
    * 获取当前缩放比例
    */
   public float getCurrentScale() {
      //Matrix为一个3*3的矩阵,一共9个值,复制到这个数组当中
      float[] values = new float[9];
      mScaleMatrix.getValues(values);
      return values[Matrix.MSCALE_X];//取出图片宽度的缩放比例
   }



   /**
    *处理图片缩放
    */
   @Override
   public boolean onScale(ScaleGestureDetector detector) {
      float scale = getCurrentScale();
      //当前相对于初始尺寸的缩放(之前matrix中获得)
      float scaleFactor = detector.getScaleFactor();
      //这个时刻缩放的/当前缩放尺度 (现在手势获取)
      if(getDrawable() == null) {
         return true;
      }

      //按比例放大缩小
      if( (scale < mMaxScale && scaleFactor > 1.0f) || (scale > mInitScale && scaleFactor < 1.0f) ) {
         if(scale * scaleFactor < mInitScale) {
            scaleFactor = mInitScale / scale;
         }
         if(scale * scaleFactor > mMaxScale) {
            scaleFactor = mMaxScale / scale;
         }
      }

      //缩放中心是屏幕中心点
      mScaleMatrix.postScale(scaleFactor , scaleFactor , detector.getFocusX() , detector.getFocusY());
      checkBorderAndCenterWhenScale();
      setImageMatrix(mScaleMatrix);
      return true;
   }


   /**
    * 获得图片放大缩小以后的宽和高,以及l,r,t,b
    */
   private RectF getMatrixRectF() {
      Matrix matrix = mScaleMatrix;
      RectF rectF = new RectF();
      Drawable drawable = getDrawable();
      if(drawable != null) {
         rectF.set(0 , 0 , drawable.getIntrinsicWidth() , drawable.getIntrinsicHeight());
         matrix.mapRect(rectF);
      }
      return rectF;
   }



   /**
    * 在缩放时,解决上下左右留白的情况
    */
   private void checkBorderAndCenterWhenScale() {
      
      RectF rect = getMatrixRectF();
      float deltaX = 0.0f;
      float deltaY = 0.0f;

      int width = getWidth();
      int height = getHeight();

      if(rect.width() >= width) {
         if(rect.left > 0) {
            deltaX = -rect.left;
         }
         if(rect.right < width) {
            deltaX = width - rect.right;
         }
      }
      if(rect.height() >= height) {
         if(rect.top > 0) {
            deltaY = -rect.top;
         }
         if(rect.bottom < height) {
            deltaY = height - rect.bottom;
         }
      }

      if(rect.width() < width) {
         deltaX = width / 2f - rect.right + rect.width() / 2f;
      }
      if(rect.height() < height) {
         deltaY = height / 2f - rect.bottom + rect.height() / 2f;
      }

      mScaleMatrix.postTranslate(deltaX, deltaY);
   }

   //缩放开始一定要返回true该detector是否处理后继的缩放事件。返回false时,不会执行onScale()
   @Override
   public boolean onScaleBegin(ScaleGestureDetector detector) {
      return true;
   }

   //缩放结束时
   @Override
   public void onScaleEnd(ScaleGestureDetector detector) {
      // TODO Auto-generated method stub
   }

   /**
    *处理现图片放大后移动查看
    */
   @Override
   public boolean onTouch(View v, MotionEvent event) {
      //双击事件进行关联
      if(mGestureDetector.onTouchEvent(event)) {
         return true;
      }
      mScaleGestureDetector.onTouchEvent(event);
      //缩放的中心点
      float x = 0;
      float y = 0;

      int pointerCount = event.getPointerCount();
      //可能出现多手指触摸的情况 ACTION_DOWN事件只能执行一次所以多点触控不能在down事件里面处理
      for(int i = 0; i < pointerCount ; i++) {
         x += event.getX(i);
         y += event.getY(i);
      }
      //取平均值,得到的就是多点触控后产生的那个点的坐标
      x /= pointerCount;
      y /= pointerCount;
      
      if(mLastPointerCount != pointerCount) {
         isCanDrag = false;
         mLastX = x;
         mLastY = y;
      }
      mLastPointerCount = pointerCount;
      RectF rectF = getMatrixRectF();
      
      switch (event.getAction()) {
      case MotionEvent.ACTION_DOWN:
         if(rectF.width() > getWidth() + 0.01 || rectF.height() > getHeight() + 0.01) {
            if(getParent() instanceof ViewPager) {

               getParent().requestDisallowInterceptTouchEvent(true);
            }
         }
         break;
      case MotionEvent.ACTION_MOVE:
         if(rectF.width() > getWidth() + 0.01 || rectF.height() > getHeight() + 0.01) {
            if(getParent() instanceof ViewPager) {

               getParent().requestDisallowInterceptTouchEvent(true);
            }
         }
         float deltaX = x - mLastX;
         float deltaY = y - mLastY;
         if(isCanDrag == false) {
            isCanDrag = isMoveAction(deltaX , deltaY);
         }
         if(isCanDrag == true) {
            if(getDrawable() != null) {
               isCheckLeftAndRight = true;
               isCheckTopAndBottom = true;
               if(rectF.width() < getWidth()) {
                  isCheckLeftAndRight = false;
                  deltaX = 0;
               }
               if(rectF.height() < getHeight()) {
                  isCheckTopAndBottom = false;
                  deltaY = 0;
               }
               mScaleMatrix.postTranslate(deltaX, deltaY);
               checkBorderWhenTranslate();
               setImageMatrix(mScaleMatrix);
            }
         }
         mLastX = x;
         mLastY = y;
         break;
      case MotionEvent.ACTION_UP:
         mLastPointerCount = 0;
         break;
      case MotionEvent.ACTION_CANCEL:
         mLastPointerCount = 0;
         break;
      }
      return true;
   }

   /**
    * 放大移动的过程中解决上下左右留白的情况
    */
   private void checkBorderWhenTranslate() { 
      RectF rectF = getMatrixRectF();
      float deltaX = 0;
      float deltaY = 0;
      //可以上下拖动且距离屏幕上方留白 根据Android系统坐标系往上移动的值要取负值
      int width = getWidth();
      int height = getHeight();
      
      if(rectF.top > 0 && isCheckTopAndBottom) {
         deltaY = -rectF.top;
      }
      if(rectF.bottom < height && isCheckTopAndBottom) {
         deltaY = height - rectF.bottom;
      }
      if(rectF.left > 0 && isCheckLeftAndRight) {
         deltaX = -rectF.left;
      }
      if(rectF.right < width && isCheckLeftAndRight) {
         deltaX = width - rectF.right;
      }
      mScaleMatrix.postTranslate(deltaX, deltaY);
   }
   /**
    *判断是否可以拖动
    */
   private boolean isMoveAction(float deltaX, float deltaY) {
      return Math.sqrt(deltaX * deltaX + deltaY * deltaY) > mTouchSlop;
   }


   /**
    * View.postDelay()方法延时执行双击放大缩小 在主线程中运行 没隔16ms给用户产生过渡的效果的
    */
   private class AutoScaleRunnable implements Runnable {
      //缩放目标值
      private float mTargetScale;
      //缩放中心点
      private float x;
      private float y;
      
      private final float BIGGER = 1.07f;
      private final float SMALL = 0.93f;
      
      //可能是BIGGER可能是SMALLER
      private float tmpScale;

      //构造传入缩放目标值,缩放的中心点
      public AutoScaleRunnable(float mTargetScale, float x, float y) {
         this.mTargetScale = mTargetScale;
         this.x = x;
         this.y = y;
         
         if(getCurrentScale() < mTargetScale) {
            tmpScale = BIGGER; //双击放大
         }
         else if(getCurrentScale() > mTargetScale) {
            tmpScale = SMALL; ///双击缩小
         }
      }

      @Override
      public void run() {
         //执行缩放
         mScaleMatrix.postScale(tmpScale , tmpScale , x , y);
         checkBorderAndCenterWhenScale();
         setImageMatrix(mScaleMatrix);
         
         float currentScale = getCurrentScale();
         //如果当前正在放大操作并且当前的放大尺度小于缩放的目标值,或者正在缩小并且缩小的尺度大于目标值
         //则再次延时16ms递归调用直到缩放到目标值
         if( (tmpScale > 1.0f && currentScale < mTargetScale) || (tmpScale < 1.0f && currentScale > mTargetScale) ) {
            postDelayed(this , 16); //??this????????
         }
         else {
            //这里我们mTrgetScale / currentScale 用目标缩放尺寸除以当前的缩放尺寸
            //得到缩放比,重新执行缩放到
            //mMidScale或者mInitScale
            float scale = mTargetScale / currentScale;
            mScaleMatrix.postScale(scale, scale, x, y);
            checkBorderAndCenterWhenScale();
            setImageMatrix(mScaleMatrix);
            isAutoScale = false;
         }
      }   
   }
}

(5)图片变换与加载

其中transform(new ImageTransform())
是图片变换的,可以自定义实现图片展示的样子,这里我加了一个图片比例缩放的变换,和屏幕宽度匹配

CompressTransformation

public class CompressTransformation implements Transformation {

    public CompressTransformation() {
    }

    @Override
    public Bitmap transform(Bitmap source) {
        return WeChatBitmapToByteArray(source);
    }


    private Bitmap WeChatBitmapToByteArray(Bitmap source) {

        // 首先进行一次大范围的压缩
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        source.compress(Bitmap.CompressFormat.JPEG, 100, output);
        float zoom = (float) Math.sqrt(100 * 1024 / (float) output.toByteArray().length); //获取缩放比例
        // 设置矩阵数据
        Matrix matrix = new Matrix();
        matrix.setScale(zoom, zoom);
        // 根据矩阵数据进行新bitmap的创建
        Bitmap resultBitmap = Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, true);
        output.reset();
        resultBitmap.compress(Bitmap.CompressFormat.JPEG, 100, output);
        if (source != resultBitmap) {
            source.recycle();
        }
 
        try {
            output.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return resultBitmap;
    }

    @Override
    public String key() {
        return "CompressTransformation";
    }

ImageLoad

public class ImageLoad {

    public static void loadPlaceholder(Context context, String url, Target target) {

        Picasso picasso = new Picasso.Builder(context).loggingEnabled(true).build();
        picasso.load(url)
                .placeholder(R.drawable.moren)
                .error(R.drawable.moren)
                .transform(new ImageTransform())
                .into(target);
    }

}

ImageTransform

public class ImageTransform implements Transformation {
//图片处理
    private String Key = "ImageTransform";

    @Override
    public Bitmap transform(Bitmap source) {
        int targetWidth = MyApplication.applicationContext.getResources().getDisplayMetrics().widthPixels;
        if (source.getWidth() == 0) {
            return source;
        }

        double aspectRatio = (double) source.getHeight() / (double) source.getWidth();
        int targetHeight = (int) (targetWidth * aspectRatio);
        if (targetHeight != 0 && targetWidth != 0) {
            Bitmap result = Bitmap.createScaledBitmap(source, targetWidth, targetHeight, false);
            if (result != source) {
                source.recycle();
            }
            return result;
        } else {
            return source;
        }
    }

    @Override
    public String key() {
        return Key;
    }

主函数

调用textview.setText函数实现图片加载

MainActivity.java:

ublic class MainActivity extends AppCompatActivity {

    private static String HTML = "

\r\n\t这是我的第一次使用html实现图片加载\r\n

\r\n

\r\n\t" + "\"GRKC\"\n" "\"\"\n" + "\"\"\n" + "\"\"\n" + "\"\"\n" + "\"\"\n" + "\"\"\n" + "\"\"\n" + "\"\"\n" + "\"\"\n" + "\"\"\n" + "\"\"\n" + "\"\"\n" + "\n

"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView textView = (TextView) findViewById(R.id.textview); //强制转化,新建的ImageGetter 实例化传入 textView.setText(HtmlUtils.getHtml(getApplicationContext(),textView,HTML)); } }

Android的图文混合实现之TextView+html加载图片_第6张图片
Android的图文混合实现之TextView+html加载图片_第7张图片
Android的图文混合实现之TextView+html加载图片_第8张图片
Android的图文混合实现之TextView+html加载图片_第9张图片

点击放大效果:

Android的图文混合实现之TextView+html加载图片_第10张图片
Android的图文混合实现之TextView+html加载图片_第11张图片
整体效果:

参考博客:Android多点触控之ZoomImageView完全解析

你可能感兴趣的:(Android的图文混合实现之TextView+html加载图片)