一般的app如果有用户概念的,肯定会涉及到用户头像自定义的功能,用户需要的头像要么从本地图库里面获取后截取,要么直接拍照然后截取,请大家看一下demo
这里拍照用的模拟器,效果不好大家请不要介意
下面将针对这2种方法进行讲解。
步骤
1、点击头像弹出pop框,可以提供选择是拍照还是从图库选择
2、拍照和图库选择完图片之后,进行图片缩放,选择适合的图片准备截取
3、获取截取的图片
4、图片截取完之后,修改成圆形头像
5、保存头像以便上传
下面逐步讲解代码
1、拍照和图库选择图片
a)拍照
执行拍照前,应该先判断SD卡是否存在,如果存在,则直接跳转到拍照界面进行拍照
if (state.equals(Environment.MEDIA_MOUNTED)) {
Intent getImageByCamera = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
/***
* 需要说明一下,以下操作使用照相机拍照,拍照后的图片会存放在相册中的
* 这里使用的这种方式有一个好处就是获取的图片是拍照后的原图
* 如果不使用ContentValues存放照片路径的话,拍照后获取的图片为缩略图不清晰
*/
ContentValues values = new ContentValues();
photoUri=getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
getImageByCamera.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, photoUri); startActivityForResult(getImageByCamera, REQUEST_CODE_TAKE_PHOTO);
}
这里需要注意的地方是,必须用ContentValues存放照片路径,不然拍照后获取的图片为缩略图不清晰
b)从图库获取图片
// 选择照片的时候也一样,我们用Action为Intent.ACTION_GET_CONTENT,
// 有些人使用其他的Action但我发现在有些机子中会出问题,所以优先选择这个
Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(intent, REQUEST_CODE_USER_ALBUM);
2、选择完图片之后,进行图片缩放,选择适合的图片准备截取
上面选择完图片,我们用了startActivityForResult跳转回界面,在这里我们需要用onActivityResult来接收
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
/**
* 用户相册
*/
case REQUEST_CODE_USER_ALBUM:
doPhoto(data);
break;
/**
* 拍照
*/
case REQUEST_CODE_TAKE_PHOTO:
startPhotoZoom(photoUri);
break;
/**
* 裁剪处理
*/
case REQUEST_CODE_CUT_PHOTO:
cutPhoto(data);
break;
}
}
a)拍照后的图片进行适当的缩放
这里的参数uri就是上一个步骤中拍完照片使用ContentValues存放照片路径photoUri
public void startPhotoZoom(Uri uri) {
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setDataAndType(uri, "image/*");
// 下面这个crop=true是设置在开启的Intent中设置显示的VIEW可裁剪
intent.putExtra("crop", "true");
// aspectX aspectY 是宽高的比例
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
// outputX outputY 是裁剪图片宽高
intent.putExtra("outputX", 300);
intent.putExtra("outputY", 300);
intent.putExtra("return-data", true);
startActivityForResult(intent, REQUEST_CODE_CUT_PHOTO);
}
b)从图库选择的图片进行缩放
其实主要通过Uri mImageCaptureUri = data.getData();
获取到uri,再传入缩放方法startPhotoZoom中。
private void doPhoto(Intent data) {
if (data != null) {
// 这个方法是根据Uri获取Bitmap图片的静态方法
// 取得返回的Uri,基本上选择照片的时候返回的是以Uri形式,但是在拍照中有得机子呢Uri是空的,所以要特别注意
Uri mImageCaptureUri = data.getData();
// 返回的Uri不为空时,那么图片信息数据都会在Uri中获得。如果为空,那么我们就进行下面的方式获取
if (mImageCaptureUri != null) {
startPhotoZoom(mImageCaptureUri);
} else {
// android拍照获得图片URI为空的处理方法http://www.xuebuyuan.com/1929552.html
// 这样做取得是缩略图,以下链接是取得原始图片
// http://blog.csdn.net/beyond0525/article/details/8940840
Bundle extras = data.getExtras();
if (extras != null) {
// 这里是有些拍照后的图片是直接存放到Bundle中的所以我们可以从这里面获取Bitmap图片
// Bitmap imageBitmap =
// extras.getParcelable("data");
Bitmap imageBitmap = (Bitmap) extras.get("data");
mImageCaptureUri = Uri
.parse(MediaStore.Images.Media.insertImage(
getContentResolver(), imageBitmap,
null, null));
startPhotoZoom(mImageCaptureUri);
}
}
}
}
3、获取截取的图片
private void cutPhoto(Intent data) {
if(data!=null){
Bundle extras = data.getExtras();
if (extras != null) {
// 这里是有些拍照后的图片是直接存放到Bundle中的所以我们可以从这里面获取Bitmap图片
cutImageBitmap = (Bitmap) data.getExtras()
.get("data");
//下面将图片设置成圆形
//保存图片
}
}
}
4、设置成圆形头像
这个设置圆形头像可以参考之前的一篇博客
自定义view之圆形头像(2种实现方式)
这里采用PorterDuffXfermode 来实现
/**
* 转换图片成圆形
*
* @param bitmap
* 传入Bitmap对象
* @return
*/
public Bitmap toRoundBitmap(Bitmap bitmap) {
int width = bitmap.getWidth();
int height = bitmap.getHeight();
float roundPx;
float left, top, right, bottom, dst_left, dst_top, dst_right, dst_bottom;
if (width <= height) {
roundPx = width / 2;
top = 0;
bottom = width;
left = 0;
right = width;
height = width;
dst_left = 0;
dst_top = 0;
dst_right = width;
dst_bottom = width;
} else {
roundPx = height / 2;
float clip = (width - height) / 2;
left = clip;
right = width - clip;
top = 0;
bottom = height;
width = height;
dst_left = 0;
dst_top = 0;
dst_right = height;
dst_bottom = height;
}
Bitmap output = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int color = 0xff424242;
final Paint paint = new Paint();
final Rect src = new Rect((int) left, (int) top, (int) right,
(int) bottom);
final Rect dst = new Rect((int) dst_left, (int) dst_top,
(int) dst_right, (int) dst_bottom);
final RectF rectF = new RectF(dst);
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(bitmap, src, dst, paint);
return output;
}
5、保存图片
这里保存图片的主要原因是为了可以上传,因为上传图片必须要将file传入
/**
* 保存图片
*
* @param bitmap
* @param fileName
* @param baseFile
*/
public static void saveBitmap(Bitmap bitmap, String fileName, File baseFile) {
FileOutputStream bos = null;
File imgFile = new File(baseFile, "/" + fileName);
try {
bos = new FileOutputStream(imgFile);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, bos);
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
try {
bos.flush();
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
全部代码下载(因为是从项目里面抽出来的功能,没有项目,提供了java文件和xml,大家自己把代码贴进项目就行)