Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Victorcassone2/feature/crop support #7

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cropimageview-samples/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ buildscript {
}

dependencies {
classpath 'com.jakewharton.hugo:hugo-plugin:1.2.0'
classpath 'com.jakewharton.hugo:hugo-plugin:1.2.1'
}
}

Expand Down
15 changes: 15 additions & 0 deletions cropimageview/src/main/java/com/cesards/cropimageview/Corner.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.cesards.cropimageview;

import android.support.annotation.IntDef;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.SOURCE)
@IntDef({
RoundedCornerDrawable.CORNER_TOP_LEFT,
RoundedCornerDrawable.CORNER_TOP_RIGHT,
RoundedCornerDrawable.CORNER_BOTTOM_LEFT,
RoundedCornerDrawable.CORNER_BOTTOM_RIGHT
})
public @interface Corner { }
220 changes: 201 additions & 19 deletions cropimageview/src/main/java/com/cesards/cropimageview/CropImageView.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,27 @@
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.os.Build;
import android.util.AttributeSet;
import android.widget.ImageView;

import java.util.HashMap;
import java.util.Map;

import static com.cesards.cropimageview.RoundedCornerDrawable.*;

/**
* @author cesards
*/
public class CropImageView extends ImageView {

private CropType cropType = CropType.NONE;
private final int[] cornerRadius = new int[4];
private boolean specificCornerRadiusSet = true;

public CropImageView(Context context) {
super(context);
Expand All @@ -47,8 +55,8 @@ public CropImageView(Context context, AttributeSet attrs, int defStyle) {
this.parseAttributes(attrs);
}

@TargetApi(Build.VERSION_CODES.LOLLIPOP) public CropImageView(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes) {
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public CropImageView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
this.parseAttributes(attrs);
}
Expand Down Expand Up @@ -82,6 +90,138 @@ public CropType getCropType() {
return this.cropType;
}

/**
* @return the largest corner radius.
*/
public float getCornerRadius() {
return getMaxCornerRadius();
}

/**
* @return the largest corner radius.
*/
public int getMaxCornerRadius() {
int maxRadius = DEFAULT_RADIUS;
for (int i = cornerRadius.length - 1; i >= 0; i--) {
maxRadius = Math.max(cornerRadius[i], maxRadius);
}

return maxRadius;
}

/**
* Get the corner radius of a specified corner.
*
* @param corner the corner.
* @return the radius.
*/
public int getCornerRadius(@Corner int corner) {
return cornerRadius[corner];
}

/**
* Set the corner radii of all corners in px.
*
* @param radius the radius to set.
*/
public void setCornerRadius(int radius) {
setCornerRadius(radius, radius, radius, radius);
}

/**
* Set the corner radius of a specific corner from a dimension resource id.
*
* @param corner the corner to set.
* @param resId the dimension resource id of the corner radius.
*/
public void setCornerRadiusDimen(@Corner int corner, @DimenRes int resId) {
setCornerRadius(corner, getResources().getDimensionPixelSize(resId));
}

/**
* Set all the corner radii from a dimension resource id.
*
* @param resId dimension resource id of radii.
*/
public void setCornerRadiusDimen(@DimenRes int resId) {
final int radius = getResources().getDimensionPixelOffset(resId);
setCornerRadius(radius, radius, radius, radius);
}

/**
* Set the corner radius of a specific corner in px.
*
* @param corner the corner to set.
* @param radius the corner radius to set in px.
*/
public void setCornerRadius(@Corner int corner, int radius) {
if (radius < DEFAULT_RADIUS) throw new IllegalArgumentException("Non negative radius supported");

if (cornerRadius[corner] == radius) return;

cornerRadius[corner] = radius;

setDrawableCorners(getDrawable());
invalidate();
}

/**
* Set the corner radii of each corner individually. Currently only one unique nonzero value is
* supported.
*
* @param topLeft radius of the top left corner in px.
* @param topRight radius of the top right corner in px.
* @param bottomRight radius of the bottom right corner in px.
* @param bottomLeft radius of the bottom left corner in px.
*/
public void setCornerRadius(int topLeft, int topRight, int bottomLeft, int bottomRight) {
if (topLeft < DEFAULT_RADIUS || topRight < DEFAULT_RADIUS || bottomLeft < DEFAULT_RADIUS || bottomRight < DEFAULT_RADIUS) throw new IllegalArgumentException("Non negative radius supported");

if (cornerRadius[CORNER_TOP_LEFT] == topLeft && cornerRadius[CORNER_TOP_RIGHT] == topRight && cornerRadius[CORNER_BOTTOM_RIGHT] == bottomRight && cornerRadius[CORNER_BOTTOM_LEFT] == bottomLeft) return;

cornerRadius[CORNER_TOP_LEFT] = topLeft;
cornerRadius[CORNER_TOP_RIGHT] = topRight;
cornerRadius[CORNER_BOTTOM_LEFT] = bottomLeft;
cornerRadius[CORNER_BOTTOM_RIGHT] = bottomRight;

setDrawableCorners(getDrawable());
invalidate();
}

@Override
public void setImageDrawable(Drawable drawable) {
final Drawable roundedDrawable = RoundedCornerDrawable.fromDrawable(drawable);
setDrawableCorners(roundedDrawable);

super.setImageDrawable(roundedDrawable);
}

@Override
public void setImageBitmap(Bitmap bm) {
final Drawable roundedDrawable = RoundedCornerDrawable.fromBitmap(bm);
setDrawableCorners(roundedDrawable);

super.setImageDrawable(roundedDrawable);
}

// TODO: Not sure if this is necessary
@Override
protected void drawableStateChanged() {
super.drawableStateChanged();

invalidate();
}

@Override
protected boolean setFrame(int l, int t, int r, int b) {
final boolean changed = super.setFrame(l, t, r, b);
if (!isInEditMode()) {
computeImageMatrix();
}

return changed;
}

private void parseAttributes(AttributeSet attrs) {
TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.CropImageView);

Expand All @@ -90,28 +230,66 @@ private void parseAttributes(AttributeSet attrs) {
setScaleType(ScaleType.MATRIX);
this.cropType = CropType.get(crop);
}

final int cornerRadiusOverride = a.getDimensionPixelSize(R.styleable.CropImageView_cornerRadius, DEFAULT_RADIUS);

cornerRadius[CORNER_TOP_LEFT] = a.getDimensionPixelSize(R.styleable.CropImageView_cornerRadiusTopLeft, DEFAULT_RADIUS);
cornerRadius[CORNER_TOP_RIGHT] = a.getDimensionPixelSize(R.styleable.CropImageView_cornerRadiusTopRight, DEFAULT_RADIUS);
cornerRadius[CORNER_BOTTOM_LEFT] = a.getDimensionPixelSize(R.styleable.CropImageView_cornerRadiusBottomLeft, DEFAULT_RADIUS);
cornerRadius[CORNER_BOTTOM_RIGHT] = a.getDimensionPixelSize(R.styleable.CropImageView_cornerRadiusBottomRight, DEFAULT_RADIUS);

for (int i = 0; i < cornerRadius.length && specificCornerRadiusSet; i++) {
specificCornerRadiusSet = cornerRadius[i] > DEFAULT_RADIUS;
}

if (cornerRadiusOverride > DEFAULT_RADIUS && !specificCornerRadiusSet) {
cornerRadius[CORNER_TOP_LEFT] = cornerRadiusOverride;
cornerRadius[CORNER_TOP_RIGHT] = cornerRadiusOverride;
cornerRadius[CORNER_BOTTOM_RIGHT] = cornerRadiusOverride;
cornerRadius[CORNER_BOTTOM_LEFT] = cornerRadiusOverride;

specificCornerRadiusSet = true;
}

a.recycle();
}

@Override
protected boolean setFrame(int l, int t, int r, int b) {
final boolean changed = super.setFrame(l, t, r, b);
if (!isInEditMode()) {
this.computeImageMatrix();
private void setDrawableCorners(Drawable drawable) {
if (drawable == null) return;

if (drawable instanceof RoundedCornerDrawable && specificCornerRadiusSet) {
((RoundedCornerDrawable) drawable).setCornerRadius(cornerRadius[CORNER_TOP_LEFT], cornerRadius[CORNER_TOP_RIGHT], cornerRadius[CORNER_BOTTOM_LEFT], cornerRadius[CORNER_BOTTOM_RIGHT]);
} else if (drawable instanceof LayerDrawable) {
// Loop through layers to and set drawable attrs
LayerDrawable ld = ((LayerDrawable) drawable);
for (int i = 0, layers = ld.getNumberOfLayers(); i < layers; i++) {
setDrawableCorners(ld.getDrawable(i));
}
}
return changed;
}






private void computeImageMatrix() {
final int viewWidth = getWidth() - getPaddingLeft() - getPaddingRight();
final int viewHeight = getHeight() - getPaddingTop() - getPaddingBottom();

if (cropType != CropType.NONE && viewHeight > 0 && viewWidth > 0) {
final Matrix matrix = getImageMatrix();


int drawableWidth = getDrawable().getIntrinsicWidth();
int drawableHeight = getDrawable().getIntrinsicHeight();
Matrix matrix = getImageMatrix();

int drawableWidth;
int drawableHeight;
if (specificCornerRadiusSet && getDrawable() instanceof RoundedCornerDrawable) {
drawableWidth = ((RoundedCornerDrawable) getDrawable()).getBitmapWidth();
drawableHeight = ((RoundedCornerDrawable) getDrawable()).getBitmapHeight();
} else {
drawableWidth = getDrawable().getIntrinsicWidth();
drawableHeight = getDrawable().getIntrinsicHeight();
}

final float scaleY = (float) viewHeight / (float) drawableHeight;
final float scaleX = (float) viewWidth / (float) drawableWidth;
Expand All @@ -122,16 +300,21 @@ private void computeImageMatrix() {

final float postDrawableWidth = drawableWidth * scale;
final float xTranslation = getXTranslation(cropType, viewWidth, postDrawableWidth, verticalImageMode);
final float postDrawabeHeigth = drawableHeight * scale;
final float yTranslation = getYTranslation(cropType, viewHeight, postDrawabeHeigth, verticalImageMode);
final float postDrawableHeight = drawableHeight * scale;
final float yTranslation = getYTranslation(cropType, viewHeight, postDrawableHeight, verticalImageMode);

matrix.postTranslate(xTranslation, yTranslation);
setImageMatrix(matrix);

if (specificCornerRadiusSet && getDrawable() instanceof RoundedCornerDrawable) {
((RoundedCornerDrawable) getDrawable()).setMatrix(matrix);
setImageMatrix(null);
} else {
setImageMatrix(matrix);
}
}
}

private float getYTranslation(CropType cropType, int viewHeight, float postDrawabeHeigth,
boolean verticalImageMode) {
private float getYTranslation(CropType cropType, int viewHeight, float postDrawabeHeigth, boolean verticalImageMode) {
if (verticalImageMode) {
switch (cropType) {
case CENTER_BOTTOM:
Expand All @@ -149,8 +332,7 @@ private float getYTranslation(CropType cropType, int viewHeight, float postDrawa
return 0;
}

private float getXTranslation(CropType cropType, int viewWidth, float postDrawableWidth,
boolean verticalImageMode) {
private float getXTranslation(CropType cropType, int viewWidth, float postDrawableWidth, boolean verticalImageMode) {
if (!verticalImageMode) {
switch (cropType) {
case RIGHT_TOP:
Expand Down
Loading