Java tutorial
/** * Copyright 2016 YouVersion * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.nuclei.cyto.ui.view; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.BitmapShader; import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.RectF; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.net.Uri; import android.support.v4.graphics.drawable.RoundedBitmapDrawable; import android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory; import android.support.v7.widget.AppCompatImageView; import android.util.AttributeSet; import android.util.Log; import com.bumptech.glide.Glide; import com.bumptech.glide.RequestManager; import com.bumptech.glide.load.Transformation; import com.bumptech.glide.load.engine.DiskCacheStrategy; import com.bumptech.glide.load.engine.Resource; import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool; import com.bumptech.glide.load.resource.bitmap.BitmapResource; import io.nuclei.cyto.R; public class GlideImageView extends AppCompatImageView { static final String TAG = GlideImageView.class.getSimpleName(); boolean mCircle = false; float mRadius; float mRatio; int mPlaceholderId; Uri mUri; Transformation mTransformation; GlideDrawableListener mListener; boolean mSet; public GlideImageView(Context context) { super(context); init(context, null, 0, 0); } public GlideImageView(Context context, AttributeSet attrs) { super(context, attrs); init(context, attrs, 0, 0); } public GlideImageView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context, attrs, defStyleAttr, 0); } protected DiskCacheStrategy getStrategy() { return DiskCacheStrategy.ALL; } void init(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.GlideImageView, defStyleAttr, defStyleRes); mCircle = a.getBoolean(R.styleable.GlideImageView_circle, false); mRatio = a.getFloat(R.styleable.GlideImageView_ratio, 0); mRadius = a.getDimensionPixelSize(R.styleable.GlideImageView_radius, 0); mPlaceholderId = a.getResourceId(R.styleable.GlideImageView_placeholder, 0); String uri = a.getString(R.styleable.GlideImageView_url); a.recycle(); if (uri == null) { if (mPlaceholderId > 0) { if (mCircle || mRadius > 0) { if (mTransformation == null) mTransformation = new CornerTransformation(getContext(), mCircle, mRadius); Glide.with(getContext()).load(mPlaceholderId).asBitmap().diskCacheStrategy(getStrategy()) .transform(mTransformation).into(this); } else Glide.with(context).load(mPlaceholderId).into(this); } } else setImageURI(uri); } @Override public void setImageDrawable(Drawable drawable) { if (mCircle && drawable instanceof BitmapDrawable) { Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap(); RoundedBitmapDrawable d = RoundedBitmapDrawableFactory.create(getResources(), bitmap); d.setCornerRadius(d.getIntrinsicWidth() / 2); d.setAntiAlias(true); drawable = d; } super.setImageDrawable(drawable); if (mListener != null) mListener.onDrawable(drawable); } public void setListener(GlideDrawableListener listener) { mListener = listener; } public void setAspectRatio(float ratio) { mRatio = ratio; requestLayout(); } public void setUrl(String url) { setImageURI(url); } public void setImageURI(String uri) { setImageURI(uri == null ? null : Uri.parse(uri)); } @Override public void setImageURI(Uri uri) { mSet = true; try { mUri = uri; RequestManager mgr = Glide.with(getContext()); if (uri == null) { if (mPlaceholderId == 0) { Glide.clear(this); setImageDrawable(null); } else { if (mCircle || mRadius > 0) { if (mTransformation == null) mTransformation = new CornerTransformation(getContext(), mCircle, mRadius); mgr.load(mPlaceholderId).asBitmap().transform(mTransformation).into(this); } else mgr.load(mPlaceholderId).into(this); } } else { if (mCircle || mRadius > 0) { if (mTransformation == null) mTransformation = new CornerTransformation(getContext(), mCircle, mRadius); if (mPlaceholderId != 0) mgr.load(uri).asBitmap().diskCacheStrategy(getStrategy()).placeholder(mPlaceholderId) .error(mPlaceholderId).fallback(mPlaceholderId).transform(mTransformation) .into(this); else mgr.load(uri).asBitmap().diskCacheStrategy(getStrategy()).transform(mTransformation) .into(this); } else { if (mPlaceholderId != 0) mgr.load(uri).asBitmap().diskCacheStrategy(getStrategy()).placeholder(mPlaceholderId) .into(this); else mgr.load(uri).asBitmap().diskCacheStrategy(getStrategy()).into(this); } } } catch (IllegalArgumentException err) { Log.e(TAG, "Error setImageURI", err); } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (mRatio == 0) super.onMeasure(widthMeasureSpec, heightMeasureSpec); else { int width = MeasureSpec.getSize(widthMeasureSpec); int height = (int) (width / mRatio); setMeasuredDimension(width, height); } } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); if (!mSet && (mUri != null || mPlaceholderId != 0)) setImageURI(mUri); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); mSet = false; try { Glide.clear(this); } catch (IllegalArgumentException err) { Log.e(TAG, "Error onDetachedFromWindow", err); } setImageDrawable(null); } static class CornerTransformation implements Transformation<Bitmap> { BitmapPool mBitmapPool; boolean mCircle; float mRadius; RectF mRect; public CornerTransformation(Context context, boolean circle, float radius) { mBitmapPool = Glide.get(context).getBitmapPool(); mCircle = circle; mRadius = radius; } @Override public Resource<Bitmap> transform(Resource<Bitmap> resource, int outWidth, int outHeight) { Bitmap bitmap = resource.get(); if (mCircle) bitmap = circle(bitmap); else bitmap = round(bitmap); return BitmapResource.obtain(bitmap, mBitmapPool); } Bitmap circle(Bitmap original) { int size = Math.min(original.getWidth(), original.getHeight()); Bitmap bitmap = mBitmapPool.get(size, size, original.getConfig()); if (bitmap == null) bitmap = Bitmap.createBitmap(size, size, original.getConfig()); Canvas canvas = new Canvas(bitmap); Paint paint = new Paint(); BitmapShader shader = new BitmapShader(original, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP); int width = (original.getWidth() - size) / 2; int height = (original.getHeight() - size) / 2; if (width != 0 || height != 0) { Matrix matrix = new Matrix(); matrix.setTranslate(-width, -height); shader.setLocalMatrix(matrix); } paint.setShader(shader); paint.setAntiAlias(true); float r = size / 2f; canvas.drawCircle(r, r, r, paint); return bitmap; } Bitmap round(Bitmap original) { int width = original.getWidth(); int height = original.getHeight(); Bitmap bitmap = mBitmapPool.get(width, height, original.getConfig()); if (bitmap == null) bitmap = Bitmap.createBitmap(width, height, original.getConfig()); if (mRect == null) mRect = new RectF(0, 0, width, height); else mRect.set(0, 0, width, height); Canvas canvas = new Canvas(bitmap); BitmapShader shader = new BitmapShader(original, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP); Paint paint = new Paint(); paint.setShader(shader); paint.setAntiAlias(true); canvas.drawRoundRect(mRect, mRadius, mRadius, paint); return bitmap; } @Override public String getId() { return "CornerTransformation(" + mCircle + ", " + mRadius + ")"; } } public interface GlideDrawableListener { void onDrawable(Drawable drawable); } }