/*
* Copyright (C) 2012 www.amsoft.cn
*
* 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 com.ab.view.cropimage;
import java.util.ArrayList;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.MotionEvent;
// TODO: Auto-generated Javadoc
/**
* The Class CropImageView.
*/
public class CropImageView extends CropViewBase {
/** The m highlight views. */
public ArrayList<HighlightView> mHighlightViews = new ArrayList<HighlightView>();
/** The m motion highlight view. */
HighlightView mMotionHighlightView = null;
/** The m last y. */
float mLastX, mLastY;
/** The m motion edge. */
int mMotionEdge;
/** The m crop image. */
private CropImage mCropImage;
/**
* 描述:TODO.
*
* @version v1.0
* @param changed the changed
* @param left the left
* @param top the top
* @param right the right
* @param bottom the bottom
* @see com.ab.view.cropimage.CropViewBase#onLayout(boolean, int, int, int, int)
* @author: amsoft.cn
* @date:2013-6-17 上午9:04:49
*/
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (mBitmapDisplayed.getBitmap() != null) {
for (HighlightView hv : mHighlightViews) {
hv.mMatrix.set(getImageMatrix());
hv.invalidate();
if (hv.mIsFocused) {
centerBasedOnHighlightView(hv);
}
}
}
}
/**
* Instantiates a new crop image view.
*
* @param context the context
* @param attrs the attrs
*/
public CropImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
/**
* 描述:TODO.
*
* @version v1.0
* @param scale the scale
* @param centerX the center x
* @param centerY the center y
* @see com.ab.view.cropimage.CropViewBase#zoomTo(float, float, float)
* @author: amsoft.cn
* @date:2013-6-17 上午9:04:49
*/
@Override
protected void zoomTo(float scale, float centerX, float centerY) {
super.zoomTo(scale, centerX, centerY);
for (HighlightView hv : mHighlightViews) {
hv.mMatrix.set(getImageMatrix());
hv.invalidate();
}
}
/**
* 描述:TODO.
*
* @version v1.0
* @see com.ab.view.cropimage.CropViewBase#zoomIn()
* @author: amsoft.cn
* @date:2013-6-17 上午9:04:49
*/
@Override
protected void zoomIn() {
super.zoomIn();
for (HighlightView hv : mHighlightViews) {
hv.mMatrix.set(getImageMatrix());
hv.invalidate();
}
}
/**
* 描述:TODO.
*
* @version v1.0
* @see com.ab.view.cropimage.CropViewBase#zoomOut()
* @author: amsoft.cn
* @date:2013-6-17 上午9:04:49
*/
@Override
protected void zoomOut() {
super.zoomOut();
for (HighlightView hv : mHighlightViews) {
hv.mMatrix.set(getImageMatrix());
hv.invalidate();
}
}
/**
* 描述:TODO.
*
* @version v1.0
* @param deltaX the delta x
* @param deltaY the delta y
* @see com.ab.view.cropimage.CropViewBase#postTranslate(float, float)
* @author: amsoft.cn
* @date:2013-6-17 上午9:04:49
*/
@Override
protected void postTranslate(float deltaX, float deltaY) {
super.postTranslate(deltaX, deltaY);
for (int i = 0; i < mHighlightViews.size(); i++) {
HighlightView hv = mHighlightViews.get(i);
hv.mMatrix.postTranslate(deltaX, deltaY);
hv.invalidate();
}
}
// According to the event's position, change the focus to the first
// hitting cropping rectangle.
/**
* Recompute focus.
*
* @param event the event
*/
private void recomputeFocus(MotionEvent event) {
for (int i = 0; i < mHighlightViews.size(); i++) {
HighlightView hv = mHighlightViews.get(i);
hv.setFocus(false);
hv.invalidate();
}
for (int i = 0; i < mHighlightViews.size(); i++) {
HighlightView hv = mHighlightViews.get(i);
int edge = hv.getHit(event.getX(), event.getY());
if (edge != HighlightView.GROW_NONE) {
if (!hv.hasFocus()) {
hv.setFocus(true);
hv.invalidate();
}
break;
}
}
invalidate();
}
/**
* 描述:TODO.
*
* @version v1.0
* @param event the event
* @return true, if successful
* @see android.view.View#onTouchEvent(android.view.MotionEvent)
* @author: amsoft.cn
* @date:2013-6-17 上午9:04:49
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
CropImage cropImage = mCropImage;
if (cropImage.mSaving) {
return false;
}
switch (event.getAction()) {
// CR: inline case blocks.
case MotionEvent.ACTION_DOWN:
if (cropImage.mWaitingToPick) {
recomputeFocus(event);
} else {
for (int i = 0; i < mHighlightViews.size(); i++) {
HighlightView hv = mHighlightViews.get(i);
int edge = hv.getHit(event.getX(), event.getY());
if (edge != HighlightView.GROW_NONE) {
mMotionEdge = edge;
mMotionHighlightView = hv;
mLastX = event.getX();
mLastY = event.getY();
// CR: get rid of the extraneous parens below.
mMotionHighlightView.setMode((edge == HighlightView.MOVE) ? HighlightView.ModifyMode.Move
: HighlightView.ModifyMode.Grow);
break;
}
}
}
break;
// CR: vertical space before case blocks.
case MotionEvent.ACTION_UP:
if (cropImage.mWaitingToPick) {
for (int i = 0; i < mHighlightViews.size(); i++) {
HighlightView hv = mHighlightViews.get(i);
if (hv.hasFocus()) {
cropImage.mCrop = hv;
for (int j = 0; j < mHighlightViews.size(); j++) {
if (j == i) {
//if j != i do your shit; no need,for continue.
continue;
}
mHighlightViews.get(j).setHidden(true);
}
centerBasedOnHighlightView(hv);
mCropImage.mWaitingToPick = false;
return true;
}
}
} else if (mMotionHighlightView != null) {
centerBasedOnHighlightView(mMotionHighlightView);
mMotionHighlightView.setMode(HighlightView.ModifyMode.None);
}
mMotionHighlightView = null;
break;
case MotionEvent.ACTION_MOVE:
if (cropImage.mWaitingToPick) {
recomputeFocus(event);
} else if (mMotionHighlightView != null) {
mMotionHighlightView.handleMotion(mMotionEdge, event.getX() - mLastX, event.getY() - mLastY);
mLastX = event.getX();
mLastY = event.getY();
if (true) {
// This section of code is optional. It has some user
// benefit in that moving the crop rectangle against
// the edge of the screen causes scrolling but it means
// that the crop rectangle is no longer fixed under
// the user's finger.
ensureVisible(mMotionHighlightView);
}
}
break;
}
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
center(true, true);
break;
case MotionEvent.ACTION_MOVE:
// if we're not zoomed then there's no point in even allowing
// the user to move the image around. This call to center puts
// it back to the normalized location (with false meaning don't
// animate).
//if (getScale() == 1F) {
//center(true, true);
//}
center(true, true);
break;
}
return true;
}
// Pan the displayed image to make sure the cropping rectangle is visible.
/**
* Ensure visible.
*
* @param hv the hv
*/
private void ensureVisible(HighlightView hv) {
Rect r = hv.mDrawRect;
int panDeltaX1 = Math.max(0, getLeft() - r.left);
int panDeltaX2 = Math.min(0, getRight() - r.right);
int panDeltaY1 = Math.max(0, getTop() - r.top);
int panDeltaY2 = Math.min(0, getBottom() - r.bottom);
int panDeltaX = panDeltaX1 != 0 ? panDeltaX1 : panDeltaX2;
int panDeltaY = panDeltaY1 != 0 ? panDeltaY1 : panDeltaY2;
if (panDeltaX != 0 || panDeltaY != 0) {
panBy(panDeltaX, panDeltaY);
}
}
// If the cropping rectangle's size changed significantly, change the
// view's center and scale according to the cropping rectangle.
//hv.mDrawRect.width<0.54*thisWidth||width>0.66*thisWidth,need to zoom
/**
* Center based on highlight view.
*
* @param hv the hv
*/
private void centerBasedOnHighlightView(HighlightView hv) {
Rect drawRect = hv.mDrawRect;
float width = drawRect.width();
float height = drawRect.height();
float thisWidth = getWidth();
float thisHeight = getHeight();
float z1 = thisWidth / width * .6F;
float z2 = thisHeight / height * .6F;
float zoom = Math.min(z1, z2);
zoom = zoom * this.getScale();
zoom = Math.max(1F, zoom);//assure getScale()>1
if ((Math.abs(zoom - getScale()) / zoom) > 0.1) {
float[] coordinates = new float[] { hv.mCropRect.centerX(), hv.mCropRect.centerY() };
getImageMatrix().mapPoints(coordinates);
zoomTo(zoom, coordinates[0], coordinates[1], 300F); // CR: 300.0f.
}
ensureVisible(hv);
}
/**
* 描述:TODO.
*
* @version v1.0
* @param canvas the canvas
* @see android.widget.ImageView#onDraw(android.graphics.Canvas)
* @author: amsoft.cn
* @date:2013-6-17 上午9:04:49
*/
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (int i = 0; i < mHighlightViews.size(); i++) {
mHighlightViews.get(i).draw(canvas);
}
}
/**
* Adds the.
*
* @param hv the hv
*/
public void add(HighlightView hv) {
mHighlightViews.clear();
mHighlightViews.add(hv);
invalidate();
}
/**
* Sets the crop image.
*
* @param cropImage the new crop image
*/
public void setCropImage(CropImage cropImage){
mCropImage = cropImage;
}
/**
* Reset view.
*
* @param b the b
*/
public void resetView(Bitmap b){
setImageBitmap(b);
setImageBitmapResetBase(b, true);
setImageMatrix(getImageViewMatrix());
int width = mBitmapDisplayed.getWidth();
int height = mBitmapDisplayed.getHeight();
Rect imageRect = new Rect(0, 0, width, height);
int cropWidth = Math.min(width, height) * 4 / 5;
int cropHeight = cropWidth;
int x = (width - cropWidth) / 2;
int y = (height - cropHeight) / 2;
RectF cropRect = new RectF(x, y, x + cropWidth, y + cropHeight);
HighlightView hv = new HighlightView(this);
hv.setup(getImageViewMatrix(), imageRect, cropRect, false, true);
hv.setFocus(true);
add(hv);
centerBasedOnHighlightView(hv);
hv.setMode(HighlightView.ModifyMode.None);
center(true, true);
invalidate();
}
}