package info.guardianproject.pixelknot.views; import android.annotation.TargetApi; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.BitmapShader; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.RectF; import android.graphics.Shader; import android.graphics.drawable.Drawable; import android.os.Build; import android.util.AttributeSet; import android.util.Log; import android.view.View; import com.squareup.picasso.Picasso; import com.squareup.picasso.Target; import info.guardianproject.pixelknot.R; public class RoundedImageView extends View implements Target { private Paint mPaint; private RectF mViewRect; private float mRounding = 0; private float mLightFilter = 0; private Shader mShader; private Bitmap mBitmap; public RoundedImageView(Context context) { super(context); init(context, null); } public RoundedImageView(Context context, AttributeSet attrs) { super(context, attrs); init(context, attrs); } public RoundedImageView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context, attrs); } @TargetApi(Build.VERSION_CODES.LOLLIPOP) public RoundedImageView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); init(context, attrs); } private void init(Context context, AttributeSet attrs) { mPaint = null; if (attrs != null) { TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RoundedImageView); if (a != null) { mRounding = a.getFloat(R.styleable.RoundedImageView_rounding, 0); mLightFilter = a.getFraction(R.styleable.RoundedImageView_lightFilter, 1, 1, 0); a.recycle(); } } // Make sure this works on old devices, see https://developer.android.com/guide/topics/graphics/hardware-accel.html if (Build.VERSION.SDK_INT < 17) setLayerType(LAYER_TYPE_SOFTWARE, null); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); update(); } private float getRounding() { return mRounding; } public void setRounding(float rounding) { mRounding = rounding; update(); postInvalidate(); } public float getLightFilter() { return mLightFilter; } public void setLightFilter(float value) { mLightFilter = value; updateLightFilter(); postInvalidate(); } private void update() { mViewRect = new RectF(0.0f, 0.0f, getWidth(), getHeight()); updateShader(); } private void updateShader() { if (mBitmap != null && mShader != null) { Matrix matrix = new Matrix(); float dx = 0; float dy = 0; float scale; if (mBitmap.getWidth() * getHeight() > getWidth() * mBitmap.getHeight()) { scale = (float)getHeight() / (float) mBitmap.getHeight(); dx = (getWidth() - mBitmap.getWidth() * scale) * 0.5f; } else { scale = (float)getWidth() / (float) mBitmap.getWidth(); dy = (getHeight() - mBitmap.getHeight() * scale) * 0.5f; } matrix.setScale(scale, scale); matrix.postTranslate((int) (dx + 0.5f), (int) (dy + 0.5f)); mShader.setLocalMatrix(matrix); } } private void updateLightFilter() { if (mPaint != null) { if (mLightFilter == 0) { mPaint.setColorFilter(null); } else { int color = Color.argb((int)(255f * mLightFilter), 255, 255, 255); mPaint.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.LIGHTEN)); } } } public void setImageBitmap(Bitmap bitmap) { mBitmap = bitmap; if (bitmap == null || bitmap.isRecycled()) { if (mPaint != null) { mPaint.setShader(null); mShader = null; mPaint = null; } } else { mShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setShader(mShader); updateLightFilter(); } updateShader(); postInvalidate(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (mPaint != null && mViewRect != null) canvas.drawRoundRect(mViewRect, getRounding() * ((float)getWidth() / 2f), getRounding() * ((float)getHeight() / 2f), mPaint); } @Override public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom loadedFrom) { setImageBitmap(bitmap); } @Override public void onBitmapFailed(Drawable drawable) { Log.d("LOG", "Failed"); } @Override public void onPrepareLoad(Drawable drawable) { } }