Android 以任意比例裁剪图片代码分享

公司的一个小伙伴写的,可以按照任意比例裁剪图片。我觉得挺好用的。简单在这里记录一下,以后肯定还会用到。

public class SeniorCropImageView extends ImageView implements ScaleGestureDetector.OnScaleGestureListener,
View.OnLayoutChangeListener {
/* For drawing color field start */
private static final int LINE_COLOR = Color.WHITE;
private static final int OUTER_MASK_COLOR = Color.argb(191, 0, 0, 0);
private static final int LINE_WIDTH_IN_DP = 1;
private final float[] mMatrixValues = new float[9];
protected Matrix mSupportMatrix;
protected ScaleGestureDetector mScaleGestureDetector;
/* For drawing color field end */
protected Paint mPaint;
/*
* 宽比高
*/
protected float mRatio = 1.0f;
protected RectF mCropRect;
//RectFPadding是适应产品需求,给裁剪框mCropRect设置一下padding -- chenglin 2016年04月18日
protected float RectFPadding = 0;
protected int mLastX;
protected int mLastY;
protected OPERATION mOperation;
private onBitmapLoadListener iBitmapLoading = null;
private boolean mEnableDrawCropWidget = true;
/*
For scale and drag
*/
private Matrix mBaseMatrix;
private Matrix mDrawMatrix;
private AccelerateDecelerateInterpolator sInterpolator = new AccelerateDecelerateInterpolator();
private Path mPath;
private int mLineWidth;
private float mScaleMax = 3.0f;
private RectF mBoundaryRect;
private int mRotation = 0;
private int mImageWidth;
private int mImageHeight;
private int mDisplayW;
private int mDisplayH;
public SeniorCropImageView(Context context) {
this(context, null);
}
public SeniorCropImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public SeniorCropImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
if (attrs != null) {
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Life_CropImage);
mRatio = a.getFloat(R.styleable.Life_CropImage_life_Crop_ratio, 1.0f);
a.recycle();
}
init();
}
public static void decodeImageForCropping(final String path, final IDecodeCallback callback) {
new Thread(new Runnable() {
@Override
public void run() {
int rotation = 0;
// 读取一下exif中的rotation
try {
ExifInterface exif = new ExifInterface(path);
final int rotate = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED);
switch (rotate) {
case ExifInterface.ORIENTATION_ROTATE_90:
rotation = 90;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
rotation = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_270:
rotation = 270;
break;
}
} catch (IOException e) {
e.printStackTrace();
}
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, options);
final int textureLimit = getMaxTextureSize();
int scale = 1;
while (options.outWidth / scale >= textureLimit) {
scale *= 2;
}
while (options.outHeight / scale >= textureLimit) {
scale *= 2;
}
options.inSampleSize = scale;
options.inJustDecodeBounds = false;
Bitmap bitmap = null;
try {
bitmap = BitmapFactory.decodeFile(path, options);
} catch (OutOfMemoryError e) {
e.printStackTrace();
}
final Bitmap bimapDecoded = bitmap;
if (bimapDecoded == null) {
return;
}
if (callback != null) {
callback.onDecoded(rotation, bimapDecoded);
}
}
}).start();
}
private static int getMaxTextureSize() {
EGL10 egl = (EGL10) EGLContext.getEGL();
EGLDisplay display = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
// Initialise
int[] version = new int[2];
egl.eglInitialize(display, version);
// Query total number of configurations
int[] totalConfigurations = new int[1];
egl.eglGetConfigs(display, null, 0, totalConfigurations);
// Query actual list configurations
EGLConfig[] configurationsList = new EGLConfig[totalConfigurations[0]];
egl.eglGetConfigs(display, configurationsList, totalConfigurations[0], totalConfigurations);
int[] textureSize = new int[1];
int maximumTextureSize = 0;
// Iterate through all the configurations to located the maximum texture size
for (int i = 0; i < totalConfigurations[0]; i++) {
// Only need to check for width since opengl textures are always squared
egl.eglGetConfigAttrib(display, configurationsList[i], EGL10.EGL_MAX_PBUFFER_WIDTH, textureSize);
// Keep track of the maximum texture size
if (maximumTextureSize < textureSize[0]) {
maximumTextureSize = textureSize[0];
}
}
// Release
egl.eglTerminate(display);
return maximumTextureSize;
}
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
mDisplayW = right - left;
mDisplayH = bottom - top;
if (getDrawable() != null && ((BitmapDrawable) getDrawable()).getBitmap() != null) {
calculateProperties(((BitmapDrawable) getDrawable()).getBitmap());
}
}
private void init() {
mScaleGestureDetector = new ScaleGestureDetector(getContext(), this);
mBaseMatrix = new Matrix();
mDrawMatrix = new Matrix();
mSupportMatrix = new Matrix();
mLineWidth = (int) dipToPixels(LINE_WIDTH_IN_DP);
mPaint = new Paint();
// 表示第一个实线段长dashOnWidth,第一个虚线段长dashOffWidth
mPath = new Path();
mCropRect = new RectF();
mBoundaryRect = new RectF();
setScaleType(ScaleType.MATRIX);
setClickable(true);
}
private float dipToPixels(float dip) {
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip,
getResources().getDisplayMetrics());
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
addOnLayoutChangeListener(this);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
removeOnLayoutChangeListener(this);
}
/**
* 设置图片的裁剪比例,比如3:4就是0.75
*
* @param ratio
*/
public void setCropRatio(final float ratio) {
if (mRatio == ratio) {
return;
}
mRatio = ratio;
//重新选择比例后,恢复旋转角度
//setImageRotation(0);
if (getDrawable() == null) {
return;
}
calculateProperties(((BitmapDrawable) getDrawable()).getBitmap());
postInvalidate();
}
public void setImageRotation(int rotation) {
if (mRotation == rotation) {
return;
}
mRotation = rotation;
if (getDrawable() == null) {
return;
}
calculateProperties(((BitmapDrawable) getDrawable()).getBitmap());
postInvalidate();
}
public void setCropRectPadding(float padding) {
RectFPadding = padding;
}
public void setImagePath(final String path) {
if (TextUtils.isEmpty(path)) {
return;
}
if (iBitmapLoading != null) {
iBitmapLoading.onLoadPrepare();
}
decodeImageForCropping(path, new IDecodeCallback() {
@Override
public void onDecoded(final int rotation, final Bitmap bitmap) {
post(new Runnable() {
@Override
public void run() {
mRotation = rotation;
setImageBitmap(bitmap);
if (iBitmapLoading != null) {
iBitmapLoading.onLoadFinish();
}
}
});
}
});
}
@Override
public void setImageBitmap(Bitmap bm) {
calculateProperties(bm);
super.setImageBitmap(bm);
}
public void setBitmapLoadingListener(onBitmapLoadListener iBitmapLoad) {
iBitmapLoading = iBitmapLoad;
}
protected void calculateProperties(Bitmap bm) {
mSupportMatrix.reset();
mBaseMatrix.reset();
int widthSize = mDisplayW;
int heightSize = mDisplayH;
generateCropRect(widthSize, heightSize);
mImageWidth = bm.getWidth();
mImageHeight = bm.getHeight();
final boolean rotated = isImageRotated();
final int bitmapWidth = rotated ? mImageHeight : mImageWidth;
final int bitmapHeight = rotated ? mImageWidth : mImageHeight;
mBoundaryRect.set(0, 0, bitmapWidth, bitmapHeight);
final float widthScale = mCropRect.width() / bitmapWidth;
final float heightScale = mCropRect.height() / bitmapHeight;
final float scale = Math.max(widthScale, heightScale);
final float scaledHeight = scale * bitmapHeight;
final float scaledWidth = scale * bitmapWidth;
// 移动到中心点
final int translateX = (int) (mCropRect.left + mCropRect.width() / 2 - scaledWidth / 2);
final int translateY = (int) (mCropRect.top + mCropRect.height() / 2 - scaledHeight / 2);
mBaseMatrix.setScale(scale, scale);
mBaseMatrix.postTranslate(translateX, translateY);
mBaseMatrix.mapRect(mBoundaryRect);
setImageMatrix(getDrawMatrix());
}
private boolean isImageRotated() {
return ((mRotation % 360) == 90) || ((mRotation % 360) == 270);
}
private void generateCropRect(int boundaryWidth, int boundaryHeight) {
//RectFPadding是适应产品需求,给裁剪框mCropRect设置一下padding -- chenglin 2016年04月18日
boundaryWidth = boundaryWidth - (int)(RectFPadding * 2);
boundaryHeight = boundaryHeight - (int)(RectFPadding * 2);
int left;
int top;
int right;
int bottom;
boolean vertical;
// 宽/高 大于比例的话,说明裁剪框是“竖直”的
vertical = (float) boundaryWidth / boundaryHeight > mRatio;
final int rectH = (int) (boundaryWidth / mRatio);
final int rectW = (int) (boundaryHeight * mRatio);
if (vertical) {
left = (boundaryWidth - rectW) / 2;
top = 0;
right = (boundaryWidth + rectW) / 2;
bottom = boundaryHeight;
} else {
left = 0;
top = (boundaryHeight - rectH) / 2;
right = boundaryWidth;
bottom = (boundaryHeight + rectH) / 2;
}
//RectFPadding是适应产品需求,给裁剪框mCropRect设置一下padding -- chenglin 2016年04月18日
mCropRect.set(left + RectFPadding, top + RectFPadding, right + RectFPadding, bottom + RectFPadding);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (!mEnableDrawCropWidget) {
return;
}
if (getDrawable() == null) {
return;
}
mPaint.reset();
mPaint.setAntiAlias(true);
mPaint.setColor(LINE_COLOR);
mPaint.setStrokeWidth(mLineWidth);
mPaint.setStyle(Paint.Style.STROKE);
mPath.reset();
// 上
mPath.moveTo(mCropRect.left, mCropRect.top);
mPath.lineTo(mCropRect.right, mCropRect.top);
// 左
mPath.moveTo(mCropRect.left, mCropRect.top);
mPath.lineTo(mCropRect.left, mCropRect.bottom);
// 右
mPath.moveTo(mCropRect.right, mCropRect.top);
mPath.lineTo(mCropRect.right, mCropRect.bottom);
// 下
mPath.moveTo(mCropRect.right, mCropRect.bottom);
mPath.lineTo(mCropRect.left, mCropRect.bottom);
canvas.drawPath(mPath, mPaint);
// 绘制外部阴影部分
mPaint.reset();
mPaint.setAntiAlias(true);
mPaint.setColor(Color.parseColor("#B3333333"));
mPaint.setStyle(Paint.Style.FILL);
//下面的四个矩形是装饰性的,就是裁剪框四周的四个阴影
final int lineOffset = mLineWidth;
if (mCropRect.top > 0) {
canvas.drawRect(0, 0, getMeasuredWidth(), mCropRect.top - lineOffset, mPaint);
}
if (mCropRect.left > 0) {
canvas.drawRect(mCropRect.top - lineOffset - RectFPadding, RectFPadding - lineOffset, mCropRect.left - lineOffset, mCropRect.bottom + lineOffset, mPaint);
}
if (mCropRect.right < getMeasuredWidth()) {
canvas.drawRect(mCropRect.right + lineOffset, mCropRect.top - lineOffset, getMeasuredWidth(), mCropRect.bottom + lineOffset, mPaint);
}
if (mCropRect.bottom < getMeasuredHeight()) {
canvas.drawRect(0, mCropRect.bottom + lineOffset, getMeasuredWidth(), getMeasuredHeight(), mPaint);
}
}
public boolean onTouchEvent(MotionEvent ev) {
if (ev.getPointerCount() > 1) {
mOperation = OPERATION.SCALE;
return mScaleGestureDetector.onTouchEvent(ev);
}
final int action = ev.getActionMasked();
final int x = (int) ev.getX();
final int y = (int) ev.getY();
switch (action) {
case MotionEvent.ACTION_DOWN:
mOperation = OPERATION.DRAG;
mLastX = x;
mLastY = y;
break;
case MotionEvent.ACTION_MOVE:
if (mOperation == OPERATION.DRAG) {
int deltaX = x - mLastX;
int deltaY = y - mLastY;
RectF boundary = getDrawBoundary(getDrawMatrix());
if (boundary.left + deltaX > mCropRect.left) {
deltaX = (int) (mCropRect.left - boundary.left);
} else if (boundary.right + deltaX < mCropRect.right) {
deltaX = (int) (mCropRect.right - boundary.right);
}
if (boundary.top + deltaY > mCropRect.top) {
deltaY = (int) (mCropRect.top - boundary.top);
} else if (boundary.bottom + deltaY < mCropRect.bottom) {
deltaY = (int) (mCropRect.bottom - boundary.bottom);
}
mSupportMatrix.postTranslate(deltaX, deltaY);
setImageMatrix(getDrawMatrix());
mLastX = x;
mLastY = y;
}
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_POINTER_UP:
case MotionEvent.ACTION_UP:
mLastX = 0;
mLastY = 0;
mOperation = null;
break;
}
return super.onTouchEvent(ev);
}
public Bitmap getOriginBitmap() {
BitmapDrawable drawable = (BitmapDrawable) getDrawable();
return drawable == null ? null : drawable.getBitmap();
}
/**
* 保存图片为bitmap
*/
public Bitmap saveCrop() throws OutOfMemoryError {
if (getDrawable() == null) {
return null;
}
Bitmap origin = getOriginBitmap();
Matrix drawMatrix = getDrawMatrix();
// 反转一下矩阵
Matrix inverse = new Matrix();
drawMatrix.invert(inverse);
// 把裁剪框对应到原图上去
RectF cropMapped = new RectF();
inverse.mapRect(cropMapped, mCropRect);
clampCropRect(cropMapped, origin.getWidth(), origin.getHeight());
// 如果产生了旋转,需要一个旋转矩阵
Matrix rotationM = new Matrix();
if (mRotation % 360 != 0) {
rotationM.postRotate(mRotation, origin.getWidth() / 2, origin.getHeight() / 2);
}
Bitmap cropped = Bitmap.createBitmap(
origin, (int) cropMapped.left, (int) cropMapped.top, (int) cropMapped.width(), (int) cropMapped.height(), rotationM, true
);
return cropped;
}
private void clampCropRect(RectF cropRect, int borderW, int borderH) {
if (cropRect.left < 0) {
cropRect.left = 0;
}
if (cropRect.top < 0) {
cropRect.top = 0;
}
if (cropRect.right > borderW) {
cropRect.right = borderW;
}
if (cropRect.bottom > borderH) {
cropRect.bottom = borderH;
}
}
@Override
public boolean onScale(ScaleGestureDetector detector) {
float scale = detector.getScaleFactor();
if (scale == 1.0f) {
return true;
}
final float currentScale = getScale(mSupportMatrix);
final float centerX = detector.getFocusX();
final float centerY = detector.getFocusY();
if ((currentScale <= 1.0f && scale < 1.0f)
|| (currentScale >= mScaleMax && scale > 1.0f)) {
return true;
}
if (currentScale * scale < 1.0f) {
scale = 1.0f / currentScale;
} else if (currentScale * scale > mScaleMax) {
scale = mScaleMax / currentScale;
}
mSupportMatrix.postScale(scale, scale, centerX, centerY);
RectF boundary = getDrawBoundary(getDrawMatrix());
float translateX = 0;
if (boundary.left > mCropRect.left) {
translateX = mCropRect.left - boundary.left;
} else if (boundary.right < mCropRect.right) {
translateX = mCropRect.right - boundary.right;
}
Log.d("scale", "x==>" + translateX);
float translateY = 0;
if (boundary.top > mCropRect.top) {
translateY = mCropRect.top - boundary.top;
} else if (boundary.bottom < mCropRect.bottom) {
translateY = mCropRect.bottom - boundary.bottom;
}
mSupportMatrix.postTranslate(translateX, translateY);
setImageMatrix(getDrawMatrix());
return true;
}
protected Matrix getDrawMatrix() {
mDrawMatrix.reset();
if (mRotation % 360 != 0) {
final boolean rotated = isImageRotated();
final int width = rotated ? mImageHeight : mImageWidth;
final int height = rotated ? mImageWidth : mImageHeight;
mDrawMatrix.postRotate(mRotation, mImageWidth / 2, mImageHeight / 2);
if (rotated) {
final int translateX = (width - mImageWidth) / 2;
final int translateY = (height - mImageHeight) / 2;
mDrawMatrix.postTranslate(translateX, translateY);
}
}
mDrawMatrix.postConcat(mBaseMatrix);
mDrawMatrix.postConcat(mSupportMatrix);
return mDrawMatrix;
}
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
return true;
}
@Override
public void onScaleEnd(ScaleGestureDetector detector) {
final float currentScale = getScale(mSupportMatrix);
if (currentScale < 1.0f) {
Log.e("onScaleEnd", "currentScale==>" + currentScale);
RectF boundary = getDrawBoundary(getDrawMatrix());
post(new AnimatedZoomRunnable(currentScale, 1.0f, boundary.centerX(), boundary.centerY()));
}
}
protected RectF getDrawBoundary(Matrix matrix) {
Drawable drawable = getDrawable();
if (drawable == null) {
return mBoundaryRect;
}
final int bitmapWidth = drawable.getIntrinsicWidth();
final int bitmapHeight = drawable.getIntrinsicHeight();
mBoundaryRect.set(0, 0, bitmapWidth, bitmapHeight);
matrix.mapRect(mBoundaryRect);
return mBoundaryRect;
}
public float getScale(Matrix matrix) {
return (float) Math.sqrt((float) Math.pow(getValue(matrix, Matrix.MSCALE_X), 2) + (float) Math.pow(getValue(matrix, Matrix.MSKEW_Y), 2));
}
/**
* Helper method that 'unpacks' a Matrix and returns the required value
*
* @param matrix - Matrix to unpack
* @param whichValue - Which value from Matrix.M* to return
* @return float - returned value
*/
private float getValue(Matrix matrix, int whichValue) {
matrix.getValues(mMatrixValues);
return mMatrixValues[whichValue];
}
public void enableDrawCropWidget(boolean enable) {
mEnableDrawCropWidget = enable;
}
protected enum OPERATION {
DRAG, SCALE
}
public enum Type {
CENTER_CROP, CENTER_INSIDE
}
public interface IDecodeCallback {
void onDecoded(final int rotation, final Bitmap bitmap);
}
//setImagePath这个方法耗时,需要显示进度条,这个是监听
public interface onBitmapLoadListener {
void onLoadPrepare();
void onLoadFinish();
}
private class AnimatedZoomRunnable implements Runnable {
private final float mFocalX, mFocalY;
private final long mStartTime;
private final float mZoomStart, mZoomEnd;
public AnimatedZoomRunnable(final float currentZoom, final float targetZoom,
final float focalX, final float focalY) {
mFocalX = focalX;
mFocalY = focalY;
mStartTime = System.currentTimeMillis();
mZoomStart = currentZoom;
mZoomEnd = targetZoom;
}
@Override
public void run() {
float t = interpolate();
float scale = mZoomStart + t * (mZoomEnd - mZoomStart);
float deltaScale = scale / getScale(mSupportMatrix);
mSupportMatrix.postScale(deltaScale, deltaScale, mFocalX, mFocalY);
setImageMatrix(getDrawMatrix());
// We haven't hit our target scale yet, so post ourselves again
if (t < 1f) {
postOnAnimation(this);
}
}
private float interpolate() {
float t = 1f * (System.currentTimeMillis() - mStartTime) / 200;
t = Math.min(1f, t);
t = sInterpolator.getInterpolation(t);
return t;
}
}
}
<declare-styleable name="Life_CropImage">
<attr name="life_Crop_ratio" format="float" />
<attr name="life_Crop_scale_type" format="enum">
<enum name="life_center_crop" value="0" />
<enum name="life_center_inside" value="1" />
</attr>
</declare-styleable>

1、让这个裁剪框显示图片:

mSeniorImageView.setImagePath(path);

2、保存裁剪后的图片:

Bitmap imageViewBitmap = null;
try {
imageViewBitmap = mSeniorImageView.saveCrop();
} catch (OutOfMemoryError e) {
imageViewBitmap = mSeniorImageView.getOriginBitmap();
PinkToast.makeText(mActivity, R.string.life_image_crop_topbar_crop_error, Toast.LENGTH_LONG).show();
}

3、设置裁剪比例:

mSeniorImageView.setCropRatio(3f / 4f);

4、设置裁剪框的padding:

mSeniorImageView.setCropRectPadding(0f);

5、setImagePath这个方法比较耗时,需要显示进度条,这个是监听:

mSeniorImageView.setBitmapLoadingListener(new SeniorCropImageView.onBitmapLoadListener() {
@Override
public void onLoadPrepare() {
mActivity.showProgress();
}
@Override
public void onLoadFinish() {
mActivity.hideProgress();
}
});

以上所述是小编给大家带来的Android 以任意比例裁剪图片代码分享,希望对大家有所帮助

(0)

相关推荐

  • Android实现相机拍摄、选择、图片裁剪功能

    最近的一些学习心得: 功能实现:点击圆形头像之后可以实现相册上传或者开启相机,然后把得到的图片经过剪裁,把剪裁过的图片设置为头像的背景图 步骤:第一步:自定义一个类,继承ImageView,重写draw方法,实现外观为圆形 第二步:在xml文件中引用该控件 第三步:实现圆形头像的点击事件,点击后显示对话框界面,询问你是打开相册还是相机(自动省略显示对话框的代码) 第四步:根据用户选择情况,打开相册或者相机 第五步:将拍摄的图片或者相册选中的图片进行剪裁,将结果保存在指定内存区域 第六步:更新头像

  • Android实现拍照、选择图片并裁剪图片功能

    一. 实现拍照.选择图片并裁剪图片效果 按照之前博客的风格,首先看下实现效果. 二. uCrop项目应用 想起之前看到的Yalantis/uCrop效果比较绚,但是研究源码之后发现在定制界面方面还是有一点的限制,于是在它的基础上做了修改Android-Crop,把定制界面独立出来,让用户去自由设置.下图为使用Android-Crop实现的模仿微信选择图片并裁剪Demo. 三. 实现思路 比较简单的选择设备图片裁剪,并将裁剪后的图片保存到指定路径: 调用系统拍照,将拍照图片保存在SD卡,然后裁剪图

  • android系统拍照结合android-crop裁剪图片

    在一个应用中更换用户的头像,一般有拍照和从图库中选择照片两种方法,现在网上也有很多开源的,但是很多都太复杂.而 Android-crop 这个库比较小,代码不复杂,比较适合,但是它没有拍照这个功能,需要我们自己整合进去. 调用系统相机拍照 1.返回略缩图的拍照 // 调用系统的拍照 private void dispatchTakePictureIntent() { Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAP

  • 解决Android从相册中获取图片出错图片却无法裁剪问题的方法

    在学习获取相册中图片进行裁剪的时候遇到了比较大的问题,在纠结了近半天才真的解决,下面分享一下学习经验. 问题: 选择了相册中的图片之后要进入图片裁剪的时候出错,(华为)手机提示"此图片无法获取",经百度后,明白是版本不同导致的URI的问题的问题,原文如下: 4.3或以下,选了图片之后,根据Uri来做处理,很多帖子都有了,我就不详细说了.主要是4.4,如果使用上面pick的原生方法来选图,返回的uri还是正常的,但如果用ACTION_GET_CONTENT的方法,返回的uri跟4.3是完

  • Android编程实现调用系统图库与裁剪图片功能

    本文实例讲述了Android编程实现调用系统图库与裁剪图片功能.分享给大家供大家参考,具体如下: 在Android开发中,调用系统图库和裁剪照片是很常见的需求.相对于自己实现这种功能,直接调用系统具有诸多优点,如不用考虑屏幕适配,不用担心性能问题,等等.因此,对于一般的需求,建议直接调用系统的功能,简便高效! 首先上效果图:    一.只调用系统图库(不裁剪),返回用户选择的图片.(只支持单选,如需多选则需要自己实现,可参考Android编程实现仿QQ照片选择器(按相册分类显示,多选添加)源码.

  • Android拍照或从图库选择图片并裁剪

    今天看<第一行代码>上面关于拍照和从相册选取图片那一部分,发现始终出不来效果,所以搜索其他资料学习一下相关知识,写一个简单的Demo. 一. 拍照选择图片 1.使用隐式Intent启动相机 //构建隐式Intent Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); //调用系统相机 startActivityForResult(intent, 1); 2.处理相机拍照返回的结果 //用户点击了取消 if(data == n

  • Android开发从相机或相册获取图片裁剪

    废话不多说了,直接给大家贴代码了. package com.only.android.app; import java.io.File; import android.app.Activity; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.Intent; import android.graphics.Bitmap; import android.gr

  • Android实现从本地图库/相机拍照后裁剪图片并设置头像

    玩qq或者是微信的盆友都知道,这些聊天工具里都要设置头像,一般情况下大家的解决办法是从本地图库选择图片或是从相机拍照,然后根据自己的喜爱截取图片.上述过程已经实现好了,最后一步我加上了把截取好的图片在保存到本地的操作,来保存头像.为了大家需要,下面我们小编把完整的代码贴出来供大家参考. 先给大家展示效果图: 代码部分: 布局代码(其实就是两个按钮和一个ImageView来显示头像) <LinearLayout xmlns:android="http://schemas.android.co

  • Android图片裁剪功能实现代码

    在Android应用中,图片裁剪也是一个经常用到的功能.Android系统中可以用隐式意图调用系统应用进行裁剪,但是这样做在不同的手机可能表现出不同的效果,甚至在某些奇葩手机上还会出其他更奇怪的问题,所以调用系统功能进行图片裁剪在很多时候对我们来说并不是一个好的选择.这时候就需要我们自己去实现这种裁剪功能了. 功能分析 要完成图片裁剪的功能,我们需要先知道图片裁剪的功能有哪些.图片裁剪之前,我们需要有一个框指示我们需要裁剪的样式合大小.图片显示出来后大小和位置可能并不是我们所期望的,所以我们还需

  • Android裁剪图片为圆形图片的实现原理与代码

    以前在eoe论坛中找过裁剪图片为圆形图片的方法,但是效果都不是很理想,这几天因为公司业务的要求,需要对头像进行裁剪以圆形的方式显示,这个方法是根据传入的图片的高度(height)和宽度(width)决定的,如果是 width <= height时,则会裁剪高度,裁剪的区域是宽度不变高度从顶部到宽度width的长度:如果 width > height,则会裁剪宽度,裁剪的区域是高度不变,宽度是取的图片宽度的中心区域,不过不同的业务需求,对裁剪图片要求不一样,可以根据业务的需求来调整裁剪的区域.

  • Android调用系统拍照裁剪图片模糊的解决方法

    在Android中,调用系统相机拍照时,将会接收到返回的图像数据,但是这些图片并不是全尺寸的图像,而是系统给的缩略图,当对拍照的图片进行裁切后显示时,得到的却是模糊的图片.下面针对这个问题提出解决的方法. 首先,我们知道调用系统的裁切是通过Intent intent = new Intent("com.android.camera.action.CROP"); 但是intent到底能够携带哪些数据呢,都有什么含义呢,我们可以看到如下: 上面包含了所有可选的操作,其中有一些非常重要的参数

  • Android实现拍照、选择相册图片并裁剪功能

    通过拍照或相册中获取图片,并进行裁剪操作,然后把图片显示到ImageView上.  当然也可以上传到服务器(项目中绝大部分情况是上传到服务器),参考网上资料及结合项目实际情况,  测试了多款手机暂时没有发现严重问题.代码有注释,直接贴代码: public class UploadPicActivity extends Activity implements View.OnClickListener { private Button take_photo_btn; private Button s

随机推荐