package kr.kdev.dg1s.biowiki.util; import android.graphics.Canvas; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.text.Html; import android.text.TextUtils; import android.widget.TextView; import com.android.volley.VolleyError; import com.android.volley.toolbox.ImageLoader; import java.lang.ref.WeakReference; import kr.kdev.dg1s.biowiki.BioWiki; import kr.kdev.dg1s.biowiki.R; /** * Created by nbradbury on 10/11/13. * ImageGetter for Html.fromHtml() * adapted from existing ImageGetter code in NoteCommentFragment */ public class BWImageGetter implements Html.ImageGetter { private WeakReference<TextView> mWeakView; private int mMaxSize; public BWImageGetter(TextView view) { this(view, 0); } public BWImageGetter(TextView view, int maxSize) { mWeakView = new WeakReference<TextView>(view); mMaxSize = maxSize; } private TextView getView() { return mWeakView.get(); } @Override public Drawable getDrawable(String source) { if (TextUtils.isEmpty(source)) return null; // images in reader comments may skip "http:" (no idea why) so make sure to add protocol here if (source.startsWith("//")) source = "http:" + source; // use Photon if a max size is requested (otherwise the full-sized image will be downloaded // and then resized) if (mMaxSize > 0) source = PhotonUtils.getPhotonImageUrl(source, mMaxSize, 0); TextView view = getView(); Drawable loading = view.getContext().getResources().getDrawable(R.drawable.remote_image); Drawable failed = view.getContext().getResources().getDrawable(R.drawable.remote_failed); final RemoteDrawable remote = new RemoteDrawable(loading, failed); BioWiki.imageLoader.get(source, new ImageLoader.ImageListener() { @Override public void onErrorResponse(VolleyError error) { remote.displayFailed(); TextView view = getView(); if (view != null) view.invalidate(); } @Override public void onResponse(ImageLoader.ImageContainer response, boolean isImmediate) { if (response.getBitmap() != null) { // make sure view is still valid TextView view = getView(); if (view == null) { AppLog.w(AppLog.T.UTILS, "BWImageGetter view is invalid"); return; } Drawable drawable = new BitmapDrawable(view.getContext().getResources(), response.getBitmap()); final int oldHeight = remote.getBounds().height(); int maxWidth = view.getWidth() - view.getPaddingLeft() - view.getPaddingRight(); if (mMaxSize > 0 && (maxWidth > mMaxSize || maxWidth == 0)) maxWidth = mMaxSize; remote.setRemoteDrawable(drawable, maxWidth); // image is from cache? don't need to modify view height if (isImmediate) return; int newHeight = remote.getBounds().height(); view.invalidate(); // For ICS view.setHeight(view.getHeight() + newHeight - oldHeight); // Pre ICS view.setEllipsize(null); } } }); return remote; } private static class RemoteDrawable extends BitmapDrawable { protected Drawable mRemoteDrawable; protected Drawable mLoadingDrawable; protected Drawable mFailedDrawable; private boolean mDidFail = false; public RemoteDrawable(Drawable loadingDrawable, Drawable failedDrawable) { mLoadingDrawable = loadingDrawable; mFailedDrawable = failedDrawable; setBounds(0, 0, mLoadingDrawable.getIntrinsicWidth(), mLoadingDrawable.getIntrinsicHeight()); } public void displayFailed() { mDidFail = true; } public void setBounds(int x, int y, int width, int height) { super.setBounds(x, y, width, height); if (mRemoteDrawable != null) { mRemoteDrawable.setBounds(x, y, width, height); return; } if (mLoadingDrawable != null) { mLoadingDrawable.setBounds(x, y, width, height); mFailedDrawable.setBounds(x, y, width, height); } } public void setRemoteDrawable(Drawable remote) { mRemoteDrawable = remote; setBounds(0, 0, mRemoteDrawable.getIntrinsicWidth(), mRemoteDrawable.getIntrinsicHeight()); } public void setRemoteDrawable(Drawable remote, int maxWidth) { // null sentinel for now if (remote == null) { // throw error return; } mRemoteDrawable = remote; // determine if we need to scale the image to fit in view int imgWidth = remote.getIntrinsicWidth(); int imgHeight = remote.getIntrinsicHeight(); float xScale = (float) imgWidth / (float) maxWidth; if (xScale > 1.0f) { setBounds(0, 0, Math.round(imgWidth / xScale), Math.round(imgHeight / xScale)); } else { setBounds(0, 0, imgWidth, imgHeight); } } public boolean didFail() { return mDidFail; } public void draw(Canvas canvas) { if (mRemoteDrawable != null) { mRemoteDrawable.draw(canvas); } else if (didFail()) { mFailedDrawable.draw(canvas); } else { mLoadingDrawable.draw(canvas); } } } }