TextView Loading HTML images asynchronous display (Picasso)

Source: Internet
Author: User

The project has such a requirement:

TextView loads an HTML tag that contains a "

Ideas:

Override the TextView html.fromhtml method and the image Picasso display (two conversion classes with Picasso are included later)

Feel that there is no suitable or use the Gilde loading in fact, whether it is Gilde or Picasso loaded beans can meet our needs.

Description of the need to complete the picture of the handsome:

  

Okay, nonsense, not much. Directly on the implementation code

RichText:

public class RichText extends TextView {

Private drawable PlaceHolder, errorimage;//bitmap, error map
Private Onimageclicklistener onimageclicklistener;//Picture Click Callback
Private hashset<target> targets;
private int d_w = 500;
private int d_h = 500;

Public RichText (Context context) {
This (context, NULL);
}

Public RichText (context context, AttributeSet Attrs) {
This (context, attrs, 0);
}

Public RichText (context context, AttributeSet attrs, int defstyleattr) {
Super (context, attrs, defstyleattr);

Init (context, attrs);
}

private void init (context context, AttributeSet Attrs) {
Targets = new hashset<> ();
TypedArray TypedArray = context.obtainstyledattributes (Attrs, R.styleable.richtext);
PlaceHolder = typedarray.getdrawable (R.styleable.richtext_placeholder);
Errorimage = typedarray.getdrawable (r.styleable.richtext_errorimage);

D_w = Typedarray.getdimensionpixelsize (R.styleable.richtext_default_width, D_w);
D_h = Typedarray.getdimensionpixelsize (R.styleable.richtext_default_height, D_h);

if (PlaceHolder = = null) {
PlaceHolder = new Colordrawable (Color.gray);
}
Placeholder.setbounds (0, 0, D_w, d_h);
if (errorimage = = null) {
Errorimage = new Colordrawable (Color.gray);
}
Errorimage.setbounds (0, 0, D_w, d_h);
Typedarray.recycle ();
}


/**
* Set Rich Text
*
* @param text Rich Text
*/
public void Setrichtext (String text) {
Targets.clear ();
spanned spanned = html.fromhtml (text, asyncimagegetter, null);
Spannablestringbuilder Spannablestringbuilder;
if (spanned instanceof Spannablestringbuilder) {
Spannablestringbuilder = (spannablestringbuilder) spanned;
} else {
Spannablestringbuilder = new Spannablestringbuilder (spanned);
}

imagespan[] Imagespans = Spannablestringbuilder.getspans (0, Spannablestringbuilder.length (), ImageSpan.class);
Final list<string> imageurls = new arraylist<> ();

for (int i = 0, size = imagespans.length; i < size; i++) {
Imagespan Imagespan = imagespans[i];
String imageUrl = Imagespan.getsource ();
int start = Spannablestringbuilder.getspanstart (Imagespan);
int end = Spannablestringbuilder.getspanend (Imagespan);
Imageurls.add (IMAGEURL);

final int finali = i;
Clickablespan Clickablespan = new Clickablespan () {
@Override
public void OnClick (View widget) {
if (Onimageclicklistener! = null) {
Onimageclicklistener.imageclicked (Imageurls, Finali);
}
}
};
clickablespan[] Clickablespans = Spannablestringbuilder.getspans (Start, end, Clickablespan.class);
if (Clickablespans! = NULL && clickablespans.length! = 0) {
for (Clickablespan Cs:clickablespans) {
Spannablestringbuilder.removespan (CS);
}
}
Spannablestringbuilder.setspan (Clickablespan, start, end, spanned.span_exclusive_exclusive);
}
Super.settext (spanned);
Setmovementmethod (Linkmovementmethod.getinstance ());
}

private void AddTarget (target target) {
Targets.add (target);
}

/**
* Load images asynchronously (dependent on Picasso)
*/
Private Html.imagegetter Asyncimagegetter = new Html.imagegetter () {
@Override
Public drawable getdrawable (String source) {
Final urldrawable urldrawable = new urldrawable ();
Target target = new target () {
@Override
public void onbitmaploaded (Bitmap Bitmap, picasso.loadedfrom from) {
drawable drawable = new Bitmapdrawable (GetContext (). Getresources (), bitmap);
Drawable.setbounds (0, 0, bitmap.getwidth (), Bitmap.getheight ());
Urldrawable.setbounds (0, 0, bitmap.getwidth (), Bitmap.getheight ());
Urldrawable.setdrawable (drawable);
RichText.this.setText (GetText ());
}

@Override
public void onbitmapfailed (drawable errordrawable) {
Urldrawable.setbounds (Errordrawable.getbounds ());
Urldrawable.setdrawable (errordrawable);
}

@Override
public void Onprepareload (drawable placeholderdrawable) {
Urldrawable.setbounds (Placeholderdrawable.getbounds ());
Urldrawable.setdrawable (placeholderdrawable);
}
};
AddTarget (target);
Picasso.with (GetContext ()). Load (source). Transform (New Imagetransform ()). into (target);//.placeholder (placeholder ). Error (Errorimage)
return urldrawable;
}
};

Private static final class Urldrawable extends Bitmapdrawable {
Private drawable drawable;

@SuppressWarnings ("deprecation")
Public urldrawable () {
}

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

public void setdrawable (drawable drawable) {
this.drawable = drawable;
}
}

public void Setplaceholder (drawable placeHolder) {
This.placeholder = PlaceHolder;
This.placeHolder.setBounds (0, 0, D_w, d_h);
}

public void Seterrorimage (drawable errorimage) {
This.errorimage = Errorimage;
This.errorImage.setBounds (0, 0, D_w, d_h);
}

public void Setonimageclicklistener (Onimageclicklistener onimageclicklistener) {
This.onimageclicklistener = Onimageclicklistener;
}

Public interface Onimageclicklistener {
/**
* Callback method after the image is clicked
*
* @param imageurls all the pictures in this rich text content
* @param position click on the position of the picture in Imageurls
*/
void imageclicked (list<string> imageurls, int position);
}
}

============================imagetransform Processing Picture Scale display
public class Imagetransform implements transformation {

Private String Key = "Imagetransform";

@Override
Public Bitmap transform (Bitmap source) {//40 is the picture spacing in my project
int targetwidth = Screenutil.getscreenwidth (App.getcontext ())-displayutil.dp2px (App.getcontext (), 40);
if (source.getwidth () = = 0) {
return source;
}
If the picture is less than the set width, do the processing
if (Source.getwidth () < Targetwidth) {
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) {
Same bitmap is returned if sizes is the same
Source.recycle ();
}
return result;
} else {
return source;
}
} else {
return source;
}
}

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

========================= 40 is the distance between the left and right sides of my project.
Configuration
<!--attrs Rich Text---
<declare-styleable name= "RichText" >
<attr name= "PlaceHolder" format= "Reference"/>
<attr name= "Errorimage" format= "Reference"/>
<attr name= "Default_width" format= "Dimension"/>
<attr name= "Default_height" format= "Dimension"/>
</declare-styleable>
/**
* Get the width of the screen px
*/
public static int Getscreenwidth (context context) {
WindowManager WindowManager = (windowmanager) context.getsystemservice (Context.window_service);
Displaymetrics outmetrics = new Displaymetrics ();//Create a blank sheet of paper
Windowmanager.getdefaultdisplay (). Getmetrics (outmetrics);//Set wide for white paper
return outmetrics.widthpixels;
}
public static int dp2px (context context, float Dpvalue) {
Final float scale = context.getresources (). Getdisplaymetrics (). density;
return (int) (Dpvalue * scale + 0.5f);
}


Richtext.setrichtext (); just fine.


============================================================================= extension Picasso loading a circular picture solving the scale distortion problem
/**
* Picasso set Round Head
* Created by Swplzj on 16/12/10.
*/

public class Circletransform implements transformation {


Private String Key = "Circletransform";

Private Context Mcontext;

private int h = 60;
Public Circletransform (Context context) {
This.mcontext = context;
}


Public Circletransform (Context context,int height) {
This.mcontext = context;
This.h = height;
}


@Override
Public Bitmap transform (Bitmap source) {//60 is the width-height compression of my picture avatar
Bitmap zoombitmp = bitmaputils.zoom (source, displayutil.dp2px (Mcontext, h), displayutil.dp2px (Mcontext, h));
Bitmap Bitmap = Bitmaputils.circlebitmap (zoombitmp);
Source.recycle ();
Return bitmap;//returns the bitmap object of the Circle
}

/**
* This method does not have any practical significance, but to ensure that the value returned cannot be null!
* @return
*/
@Override
Public String key () {
return Key;
}
}


public class Bitmaputils {

/** converts a rectangle's bitmap object to a circular bitmap
* @param Source: Bitmap of the rectangle to be processed
* @return: Circular bitmap to be returned
*/
public static Bitmap Circlebitmap (Bitmap source) {
Gets the width of the bitmap
int width = source.getwidth ();
Returns a bitmap object of a square
Bitmap Bitmap = Bitmap.createbitmap (width, width, Bitmap.Config.ARGB_8888);
Provides a canvas with a specified width and height
Canvas canvas = new canvas (bitmap);
Provide brushes
Paint paint = new paint ();
Paint.setantialias (TRUE);
Background: Draw a circle on the canvas
Canvas.drawcircle (WIDTH/2, WIDTH/2, WIDTH/2, paint);

Set how images are handled when they intersect
Setxfermode: Sets the way in which the drawn image is handled when it intersects, and what kinds of common patterns it contains
PorterDuff.Mode.SRC_IN take two layers of image intersection department, show only the upper image, note that this refers to the intersection of the section, and then display the upper image
PorterDuff.Mode.DST_IN two-layer image intersection department, showing only the underlying image
Paint.setxfermode (New Porterduffxfermode (PorterDuff.Mode.SRC_IN));
Foreground: Draw a bitmap on the canvas
Canvas.drawbitmap (source, 0, 0, paint);

return bitmap;

}

/** compression of the bitmap
* @param Source: Bitmap to be processed
* @param width must be compressed into a floating-point type
* @param height must be compressed to a floating-point type
* @return return the bitmap after compression
Note The parameter 2,3 must be supplied as a floating-point type.
*/
public static Bitmap Zoom (Bitmap source,float width,float height) {
Matrix matrix = new Matrix ();
float ScaleX = Width/source.getwidth ();
float ScaleY = Height/source.getheight ();
Matrix.postscale (ScaleX, ScaleY);

Bitmap Bitmap = Bitmap.createbitmap (Source,0,0,source.getwidth (), Source.getheight (), matrix,true);
return bitmap;
}
}
Missing or unclear can contact me QQ Group: 521039620 Android&go,let ' s go!
Thanks to the author Https://github.com/zzhoujay/RichText (Gilde method implementation)
And no mention of the online reference thank you all.

TextView Loading HTML images asynchronous display (Picasso)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.