PS:第四部的时候,一定要压缩之后们通过流的方式保存到本地,不要在调用BitmapFactory.decodeStream方法,否则又会回到200K
import java.io.File; import android.app.Activity; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.provider.MediaStore; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class MainActivity extends Activity { private File file; // 要保存的文件sss private Button btnCamera; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout. activity_main); btnCamera = (Button) findViewById(R.id. btn_camera); btnCamera.setOnClickListener( new OnClickListener() { @Override public void onClick(View v) { file = new File(FileUtils.getImgStorageDirectory() + "/aa.jpg"); Intent intent = new Intent(); intent.setAction( "android.media.action.IMAGE_CAPTURE"); Uri uri = Uri. fromFile(file); intent.putExtra(MediaStore. EXTRA_OUTPUT, uri); startActivityForResult(intent, 100); } }); } @Override protected void onActivityResult( int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == 100 && file.exists() && file.length() > 0) { // 这里吧文件的路径传入到下一个界面,就是裁剪的界面 Intent intent = new Intent(MainActivity. this, CropActivity.class); intent.putExtra( "path", file.getPath()); startActivity(intent); } } } 第二个界面:裁剪的界面: import android.app.Activity; import android.content.Intent; import android.graphics.Bitmap; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import com.example.ima.view.ClipImageLayout; public class CropActivity extends Activity implements OnClickListener { private Button btn; private ClipImageLayout mClipImageLayout; private String path; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout. activity_crop); path = getIntent().getStringExtra( "path"); btn = (Button) findViewById(R.id. crop_button); btn.setOnClickListener(CropActivity. this); mClipImageLayout = (ClipImageLayout) findViewById(R.id.clipImageLayout ); // 有的系统返回的图片是旋转了,有的没有旋转,所以处理 int degreee = ImageUtil. readPictureDegree(path); Bitmap bitmap = ImageUtil. getSmallBitmap(path); if (bitmap != null) { if (degreee == 0) { mClipImageLayout.setImageBitmap(bitmap); } else { mClipImageLayout.setImageBitmap(ImageUtil. rotaingBitmap(degreee, bitmap)); } } } @Override public void onClick(View v) { //得到裁剪的图片 Bitmap bitmap = mClipImageLayout.clip(); String imageName = String.valueOf(System.currentTimeMillis()); //这里把裁剪过后的图片进行质量压缩,并且保存到本地 ImageUtil. compressAndSave(bitmap, imageName); Intent intent = new Intent(CropActivity. this, ShowActivity.class); intent.putExtra( "imageName", imageName); startActivity(intent); } } 这个类的布局文件: <LinearLayout xmlns:android= "http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width= "fill_parent" android:layout_height= "fill_parent" android:background="#000000" android:orientation="vertical" > <Button android:id= "@+id/crop_button" android:layout_width= "match_parent" android:layout_height= "wrap_content" android:layout_gravity= "center" android:layout_margin= "16dp" android:text="CROP" /> <com.example.ima.view.ClipImageLayout android:id= "@+id/clipImageLayout" android:layout_width= "match_parent" android:layout_height= "match_parent" /> </LinearLayout> 主要的三个View文件: import android.content.Context; import android.graphics.Bitmap; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.util.TypedValue; import android.widget.RelativeLayout; /** * @ClassName: ClipImageLayout * @Description: * @date 2015 -5 -10 下午10:22:24 */ public class ClipImageLayout extends RelativeLayout { private ClipZoomImageView mZoomImageView; private ClipImageBorderView mClipImageView; private int mHorizontalPadding = 0; // 这里测试,直接写死了大小,真正使用过程中,可以提取为自定义属性 public ClipImageLayout(Context context, AttributeSet attrs) { super(context, attrs); mZoomImageView = new ClipZoomImageView(context); mClipImageView = new ClipImageBorderView(context); android.view.ViewGroup.LayoutParams lp = new LayoutParams( android.view.ViewGroup.LayoutParams. MATCH_PARENT, android.view.ViewGroup.LayoutParams. MATCH_PARENT); this.addView( mZoomImageView, lp); this.addView( mClipImageView, lp); // 计算padding的px mHorizontalPadding = ( int) TypedValue. applyDimension( TypedValue. COMPLEX_UNIT_DIP, mHorizontalPadding, getResources() .getDisplayMetrics()); mZoomImageView.setHorizontalPadding( mHorizontalPadding); mClipImageView.setHorizontalPadding( mHorizontalPadding); } public void setImageDrawable(Drawable drawable) { mZoomImageView.setImageDrawable(drawable); } public void setImageBitmap(Bitmap bitmap) { mZoomImageView.setImageBitmap(bitmap); } /** *对外公布设置边距的方法,单位为 dp * * @param mHorizontalPadding */ public void setHorizontalPadding( int mHorizontalPadding) { this. mHorizontalPadding = mHorizontalPadding; } /** * 裁切图片 * * @return */ public Bitmap clip() { return mZoomImageView.clip(); } } import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Paint.Style; import android.util.AttributeSet; import android.util.TypedValue; import android.view.View; public class ClipImageBorderView extends View { /** * 水平方向与View的边距 */ private int mHorizontalPadding; /** * 垂直方向与View的边距 */ private int mVerticalPadding; /** * 绘制的矩形的宽度 */ private int mWidth; /** * 边框的颜色,默认为白色 */ private int mBorderColor = Color.parseColor("#FFFFFF" ); /** * 边框的宽度单位 dp */ private int mBorderWidth = 1; private Paint mPaint; public ClipImageBorderView(Context context) { this(context, null); } public ClipImageBorderView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ClipImageBorderView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); mBorderWidth = ( int) TypedValue. applyDimension( TypedValue. COMPLEX_UNIT_DIP, mBorderWidth, getResources() .getDisplayMetrics()); mPaint = new Paint(); mPaint.setAntiAlias( true); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 计算矩形区域的宽度 mWidth = getWidth() - 2 * mHorizontalPadding; // 计算距离屏幕垂直边界 的边据 mVerticalPadding = (getHeight() - mWidth) / 2; mPaint.setColor(Color. parseColor("#aa000000")); mPaint.setStyle(Style. FILL); // 绘制左边1 canvas.drawRect(0, 0, mHorizontalPadding, getHeight(), mPaint); // 绘制右边2 canvas.drawRect(getWidth() - mHorizontalPadding, 0, getWidth(), getHeight(), mPaint); // 绘制上边3 canvas.drawRect( mHorizontalPadding, 0, getWidth() - mHorizontalPadding, mVerticalPadding, mPaint); // 绘制下边4 canvas.drawRect( mHorizontalPadding, getHeight() - mVerticalPadding, getWidth() - mHorizontalPadding, getHeight(), mPaint); // 绘制外边框 mPaint.setColor( mBorderColor); mPaint.setStrokeWidth( mBorderWidth); mPaint.setStyle(Style. STROKE); canvas.drawRect( mHorizontalPadding, mVerticalPadding, getWidth() - mHorizontalPadding, getHeight() - mVerticalPadding, mPaint ); } public void setHorizontalPadding( int mHorizontalPadding) { this. mHorizontalPadding = mHorizontalPadding; } } import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.RectF; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.view.GestureDetector; import android.view.GestureDetector.SimpleOnGestureListener; import android.view.MotionEvent; import android.view.ScaleGestureDetector; import android.view.ScaleGestureDetector.OnScaleGestureListener; import android.view.View; import android.view.View.OnTouchListener; import android.view.ViewTreeObserver; import android.widget.ImageView; /** * 缩放图片的View * */ public class ClipZoomImageView extends ImageView implements OnScaleGestureListener, OnTouchListener, ViewTreeObserver.OnGlobalLayoutListener { public static float SCALE_MAX = 4.0f; private static float SCALE_MID = 2.0f; /** * 初始化时的缩放比例,如果图片宽或高大于屏幕,此值将小于0 */ private float initScale = 1.0f; private boolean once = true; /** * 用于存放矩阵的9个值 */ private final float[] matrixValues = new float[9]; /** * 缩放的手势检测 */ private ScaleGestureDetector mScaleGestureDetector = null; private final Matrix mScaleMatrix = new Matrix(); /** * 用于双击检测 */ private GestureDetector mGestureDetector; private boolean isAutoScale; private int mTouchSlop; private float mLastX; private float mLastY; private boolean isCanDrag; private int lastPointerCount; /** * 水平方向与View的边距 */ private int mHorizontalPadding; public ClipZoomImageView(Context context) { this(context, null); } public ClipZoomImageView(Context context, AttributeSet attrs) { super(context, attrs); setScaleType(ScaleType. MATRIX); mGestureDetector = new GestureDetector(context, new SimpleOnGestureListener() { @Override public boolean onDoubleTap(MotionEvent e) { if ( isAutoScale == true) return true; float x = e.getX(); float y = e.getY(); if (getScale() < SCALE_MID) { ClipZoomImageView. this.postDelayed( new AutoScaleRunnable(SCALE_MID, x, y), 16); isAutoScale = true; } else { ClipZoomImageView. this.postDelayed( new AutoScaleRunnable(initScale, x, y), 16); isAutoScale = true; } return true; } }); mScaleGestureDetector = new ScaleGestureDetector(context, this); this. setOnTouchListener(this); } /** * 自动缩放的任务 * */ private class AutoScaleRunnable implements Runnable { static final float BIGGER = 1.07f; static final float SMALLER = 0.93f; private float mTargetScale; private float tmpScale; /** * 缩放的中心 */ private float x; private float y; /** * 传入目标缩放值,根据目标值与当前值,判断应该放大还是缩小 * * @param targetScale */ public AutoScaleRunnable( float targetScale, float x, float y) { this. mTargetScale = targetScale; this. x = x; this. y = y; if (getScale() < mTargetScale) { tmpScale = BIGGER; } else { tmpScale = SMALLER; } } @Override public void run() { // 进行缩放 mScaleMatrix.postScale( tmpScale, tmpScale, x, y); checkBorder(); setImageMatrix( mScaleMatrix); final float currentScale = getScale(); // 如果值在合法范围内,继续缩放 if ((( tmpScale > 1f) && (currentScale < mTargetScale)) || (( tmpScale < 1f) && ( mTargetScale < currentScale))) { ClipZoomImageView. this.postDelayed( this, 16); } else // 设置为目标的缩放比例 { final float deltaScale = mTargetScale / currentScale; mScaleMatrix.postScale(deltaScale, deltaScale, x, y); checkBorder(); setImageMatrix( mScaleMatrix); isAutoScale = false; } } } @Override public boolean onScale(ScaleGestureDetector detector) { float scale = getScale(); float scaleFactor = detector.getScaleFactor(); if (getDrawable() == null) return true; /** * 缩放的范围控制 */ if ((scale < SCALE_MAX && scaleFactor > 1.0f) || (scale > initScale && scaleFactor < 1.0f)) { /** * 最大值最小值判断 */ if (scaleFactor * scale < initScale) { scaleFactor = initScale / scale; } if (scaleFactor * scale > SCALE_MAX) { scaleFactor = SCALE_MAX / scale; } /** * 设置缩放比例 */ mScaleMatrix.postScale(scaleFactor, scaleFactor, detector.getFocusX(), detector.getFocusY()); checkBorder(); setImageMatrix( mScaleMatrix); } return true; } /** * 根据当前图片的Matrix获得图片的范围 * * @return */ private RectF getMatrixRectF() { Matrix matrix = mScaleMatrix; RectF rect = new RectF(); Drawable d = getDrawable(); if ( null != d) { rect.set(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight()); matrix.mapRect(rect); } return rect; } @Override public boolean onScaleBegin(ScaleGestureDetector detector) { return true; } @Override public void onScaleEnd(ScaleGestureDetector detector) { } @Override public boolean onTouch(View v, MotionEvent event) { if ( mGestureDetector.onTouchEvent(event)) return true; mScaleGestureDetector.onTouchEvent(event); float x = 0, y = 0; // 拿到触摸点的个数 final int pointerCount = event.getPointerCount(); // 得到多个触摸点的x与y均值 for ( int i = 0; i < pointerCount; i++) { x += event.getX(i); y += event.getY(i); } x = x / pointerCount; y = y / pointerCount; /** * 每当触摸点发生变化时,重置mLasX , mLastY */ if (pointerCount != lastPointerCount) { isCanDrag = false; mLastX = x; mLastY = y; } lastPointerCount = pointerCount; switch (event.getAction()) { case MotionEvent. ACTION_MOVE: float dx = x - mLastX; float dy = y - mLastY; if (! isCanDrag) { isCanDrag = isCanDrag(dx, dy); } if ( isCanDrag) { if (getDrawable() != null) { RectF rectF = getMatrixRectF(); // 如果宽度小于屏幕宽度,则禁止左右移动 if (rectF.width() <= getWidth() - mHorizontalPadding * 2) { dx = 0; } // 如果高度小雨屏幕高度,则禁止上下移动 if (rectF.height() <= getHeight() - getHVerticalPadding() * 2) { dy = 0; } mScaleMatrix.postTranslate(dx, dy); checkBorder(); setImageMatrix( mScaleMatrix); } } mLastX = x; mLastY = y; break; case MotionEvent. ACTION_UP: case MotionEvent. ACTION_CANCEL: lastPointerCount = 0; break; } return true; } /** * 获得当前的缩放比例 * * @return */ public final float getScale() { mScaleMatrix.getValues( matrixValues); return matrixValues[Matrix. MSCALE_X]; } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); getViewTreeObserver().addOnGlobalLayoutListener( this); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); getViewTreeObserver(). removeGlobalOnLayoutListener( this); } /** * 垂直方向与View的边距 */ // private int getHVerticalPadding(); @Override public void onGlobalLayout() { if ( once) { Drawable d = getDrawable(); if (d == null) return; int width = getWidth(); int height = getHeight(); // 拿到图片的宽和高 int drawableW = d.getIntrinsicWidth(); int drawableH = d.getIntrinsicHeight(); float scale = 1.0f; int frameSize = getWidth() - mHorizontalPadding * 2; // 大图 if (drawableW > frameSize && drawableH < frameSize) { scale = 1.0f * frameSize / drawableH; } else if (drawableH > frameSize && drawableW < frameSize) { scale = 1.0f * frameSize / drawableW; } else if (drawableW > frameSize && drawableH > frameSize) { float scaleW = frameSize * 1.0f / drawableW; float scaleH = frameSize * 1.0f / drawableH; scale = Math. max(scaleW, scaleH); } // 太小的图片放大处里 if (drawableW < frameSize && drawableH > frameSize) { scale = 1.0f * frameSize / drawableW; } else if (drawableH < frameSize && drawableW > frameSize) { scale = 1.0f * frameSize / drawableH; } else if (drawableW < frameSize && drawableH < frameSize) { float scaleW = 1.0f * frameSize / drawableW; float scaleH = 1.0f * frameSize / drawableH; scale = Math. max(scaleW, scaleH); } initScale = scale; SCALE_MID = initScale * 2; SCALE_MAX = initScale * 4; mScaleMatrix.postTranslate((width - drawableW) / 2, (height - drawableH) / 2); mScaleMatrix.postScale(scale, scale, getWidth() / 2, getHeight() / 2); // 图片移动至屏幕中心 setImageMatrix( mScaleMatrix); once = false; } } /** * 剪切图片,返回剪切后的bitmap对象 * * @return */ public Bitmap clip() { Bitmap bitmap = Bitmap. createBitmap(getWidth(), getHeight(), Bitmap.Config. ARGB_8888); Canvas canvas = new Canvas(bitmap); draw(canvas); return Bitmap. createBitmap(bitmap, mHorizontalPadding, getHVerticalPadding(), getWidth() - 2 * mHorizontalPadding, getWidth() - 2 * mHorizontalPadding); } /** * 边界检测 */ private void checkBorder() { RectF rect = getMatrixRectF(); float deltaX = 0; float deltaY = 0; int width = getWidth(); int height = getHeight(); // 如果宽或高大于屏幕,则控制范围 ; 这里的0.001是因为精度丢失会产生问题,但是误差一般很小,所以我们直接加了一个0.01 if (rect.width() + 0.01 >= width - 2 * mHorizontalPadding) { if (rect. left > mHorizontalPadding) { deltaX = -rect. left + mHorizontalPadding; } if (rect. right < width - mHorizontalPadding) { deltaX = width - mHorizontalPadding - rect.right; } } if (rect.height() + 0.01 >= height - 2 * getHVerticalPadding()) { if (rect. top > getHVerticalPadding()) { deltaY = -rect. top + getHVerticalPadding(); } if (rect. bottom < height - getHVerticalPadding()) { deltaY = height - getHVerticalPadding() - rect.bottom; } } mScaleMatrix.postTranslate(deltaX, deltaY); } /** * 是否是拖动行�? * * @param dx * @param dy * @return */ private boolean isCanDrag( float dx, float dy) { return Math. sqrt((dx * dx) + (dy * dy)) >= mTouchSlop; } public void setHorizontalPadding( int mHorizontalPadding) { this. mHorizontalPadding = mHorizontalPadding; } private int getHVerticalPadding() { return (getHeight() - (getWidth() - 2 * mHorizontalPadding)) / 2; } }