摘自:bmob即时通讯个人资料编辑,源码猛击这里
很多人想知道即时聊天的拍照做图像和相册选择做图像的功能怎么实现,这里。我通过拆分bmob即时聊天的案例,介绍大家怎么实现这种功能。
首先我们点击头像弹出上图的窗口,我们用到了PopupWindow,把代码封装成一个方法,代码如下:
/**
* 弹出选择窗口
* @param view 要弹出来的view
*/
private void showPopupWindow(View view) {
avatorPop = new PopupWindow(view, mScreenWidth, 600);
avatorPop.setTouchInterceptor(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
avatorPop.dismiss();
return true;
}
return false;
}
});
avatorPop.setWidth(WindowManager.LayoutParams.MATCH_PARENT);
avatorPop.setHeight(WindowManager.LayoutParams.WRAP_CONTENT);
avatorPop.setTouchable(true);
avatorPop.setFocusable(true);
avatorPop.setOutsideTouchable(true);
avatorPop.setBackgroundDrawable(new BitmapDrawable());
// 动画效果 从底部弹起
avatorPop.setAnimationStyle(R.style.Animations_GrowFromBottom);
avatorPop.showAtLocation(layout_all, Gravity.BOTTOM, 0, 0);
}
那么,拍照和相册,现在我们是点击其中一项做相应的动作。也相应封装成一个方法:
RelativeLayout layout_choose;
RelativeLayout layout_photo;
PopupWindow avatorPop;
public String filePath = "";
private void showAvatarPop() {
//弹出窗口的布局文件,转化成view
View view = LayoutInflater.from(this).inflate(R.layout.pop_showavator,
null);
//实例化选择相册按钮
layout_choose = (RelativeLayout) view.findViewById(R.id.layout_choose);
//实例化选择拍照按钮
layout_photo = (RelativeLayout) view.findViewById(R.id.layout_photo);
layout_photo.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
ShowLog("点击拍照");
//点击时的背景的改变
layout_choose.setBackgroundColor(getResources().getColor(
R.color.base_color_text_white));
layout_photo.setBackgroundDrawable(getResources().getDrawable(
R.drawable.pop_bg_press));
File dir = new File(Environment.getExternalStorageDirectory()+"/avatar/");
if (!dir.exists()) {
dir.mkdirs();
}
// 原图
File file = new File(dir, new SimpleDateFormat("yyMMddHHmmss")
.format(new Date()));
// 获取相片的保存路径
filePath = file.getAbsolutePath();
//将图片转化成uri
Uri imageUri = Uri.fromFile(file);
//跳转到系统的相机拍照
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
// public static final int REQUESTCODE_UPLOADAVATAR_CAMERA = 1;//拍照修改头像
startActivityForResult(intent,
BmobConstants.REQUESTCODE_UPLOADAVATAR_CAMERA);
}
});
layout_choose.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
ShowLog("点击相册");
//点击相册时的背景改变
layout_photo.setBackgroundColor(getResources().getColor(
R.color.base_color_text_white));
layout_choose.setBackgroundDrawable(getResources().getDrawable(
R.drawable.pop_bg_press));
//跳转到相册
Intent intent = new Intent(Intent.ACTION_PICK, null);
intent.setDataAndType(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
// public static final int REQUESTCODE_UPLOADAVATAR_LOCATION = 2;//本地相册修改头像
startActivityForResult(intent,
BmobConstants.REQUESTCODE_UPLOADAVATAR_LOCATION);
}
});
//调用showPopupWindow方法
showPopupWindow(view);
}
我们不管是拍照还是选择相册,我们都是通过调用系统的程序来实现的,拍照之后或者选择相册之后,会返回数据回来,所以我要用startActivityForResult将返回的数据得到。
Bitmap newBitmap;
boolean isFromCamera = false;// 区分拍照旋转
int degree = 0;
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
// 拍照修改头像
case BmobConstants.REQUESTCODE_UPLOADAVATAR_CAMERA:
if (resultCode == RESULT_OK) {
if (!Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
ShowToast("SD不可用");
return;
}
isFromCamera = true;
File file = new File(filePath);
//degree = PhotoUtil.readPictureDegree(file.getAbsolutePath());
//Log.i("life", "拍照后的角度:" + degree);
//进行裁剪
startImageAction(Uri.fromFile(file), 200, 200,
BmobConstants.REQUESTCODE_UPLOADAVATAR_CROP, true);
}
break;
// 本地修改头像
case BmobConstants.REQUESTCODE_UPLOADAVATAR_LOCATION:
if (avatorPop != null) {
avatorPop.dismiss();
}
Uri uri = null;
if (data == null) {
return;
}
if (resultCode == RESULT_OK) {
if (!Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
ShowToast("SD不可用");
return;
}
isFromCamera = false;
uri = data.getData();
startImageAction(uri, 200, 200,
BmobConstants.REQUESTCODE_UPLOADAVATAR_CROP, true);
} else {
ShowToast("照片获取失败");
}
break;
// 裁剪头像返回
case BmobConstants.REQUESTCODE_UPLOADAVATAR_CROP:
// TODO sent to crop
if (avatorPop != null) {
avatorPop.dismiss();
}
if (data == null) {
// Toast.makeText(this, "取消选择", Toast.LENGTH_SHORT).show();
return;
} else {
saveCropAvator(data);
}
// 初始化文件路径
filePath = "";
// 上传头像
uploadAvatar();
break;
default:
break;
}
}
从代码中可以看出,拍照成功或者选择相片后,进行照片的裁剪startImageAction。裁剪的动作也封装成一个方法
/**
* @Title: 进行照片的裁剪
* @return void
* @throws
*/
private void startImageAction(Uri uri, int outputX, int outputY,
int requestCode, boolean isCrop) {
Intent intent = null;
if (isCrop) {
intent = new Intent("com.android.camera.action.CROP");
} else {
intent = new Intent(Intent.ACTION_GET_CONTENT, null);
}
intent.setDataAndType(uri, "image/*");
intent.putExtra("crop", "true");
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
intent.putExtra("outputX", outputX);
intent.putExtra("outputY", outputY);
intent.putExtra("scale", true);
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
intent.putExtra("return-data", true);
intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
intent.putExtra("noFaceDetection", true); // no face detection
startActivityForResult(intent, requestCode);
}
裁剪之后,我们requestCode的requestCode是照片裁剪的public static final int REQUESTCODE_UPLOADAVATAR_CROP = 3;裁剪成功对应的是BmobConstants.REQUESTCODE_UPLOADAVATAR_CROP的处理,那么在case BmobConstants.REQUESTCODE_UPLOADAVATAR_CROP中,我们可以看到saveCropAvator和uploadAvatar两个方法,这两个方法呢分别是保存头像和上传头像到服务器的方法,代码如下:
/**
* 保存裁剪的头像
*
* @param data
*/
private void saveCropAvator(Intent data) {
Bundle extras = data.getExtras();
if (extras != null) {
//得到返回来的数据,是bitmap类型的数据
Bitmap bitmap = extras.getParcelable("data");
Log.i("life", "avatar - bitmap = " + bitmap);
if (bitmap != null) {
bitmap = PhotoUtil.toRoundCorner(bitmap, 10);
if (isFromCamera && degree != 0) {
//将图片转化成圆角图片
bitmap = PhotoUtil.rotaingImageView(degree, bitmap);
}
iv_set_avator.setImageBitmap(bitmap);
// 保存图片
String filename = new SimpleDateFormat("yyMMddHHmmss")
.format(new Date())+".png";
path = BmobConstants.MyAvatarDir + filename;
PhotoUtil.saveBitmap(BmobConstants.MyAvatarDir, filename,
bitmap, true);
// 上传头像
if (bitmap != null && bitmap.isRecycled()) {
bitmap.recycle();
}
}
}
}
/**
* 将图片变为圆角
*
* @param bitmap
* 原Bitmap图片
* @param pixels
* 图片圆角的弧度(单位:像素(px))
* @return 带有圆角的图片(Bitmap 类型)
*/
public static Bitmap toRoundCorner(Bitmap bitmap, int pixels) {
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
bitmap.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int color = 0xff424242;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
final RectF rectF = new RectF(rect);
final float roundPx = pixels;
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return output;
}
保存完剪裁的头像之后,把头像上传到服务器。
//bmob服务器上传文件操作
private void uploadAvatar() {
final BmobFile bmobFile = new BmobFile(new File(path));
bmobFile.upload(this, new UploadFileListener() {
@Override
public void onSuccess() {
// TODO Auto-generated method stub
//得到文件的路径
String url = bmobFile.getFileUrl(SetMyInfoActivity.this);
// 更新BmobUser对象
updateUserAvatar(url);
}
@Override
public void onProgress(Integer arg0) {
// TODO Auto-generated method stub
}
@Override
public void onFailure(int arg0, String msg) {
// TODO Auto-generated method stub
ShowToast("头像上传失败:" + msg);
}
});
}
//将上传的图片文件地址值(路径)赋值给该用户
private void updateUserAvatar(final String url) {
User u =new User();
u.setAvatar(url);
updateUserData(u,new UpdateListener() {
@Override
public void onSuccess() {
// TODO Auto-generated method stub
ShowToast("头像更新成功!");
// 更新头像
refreshAvatar(url);
}
@Override
public void onFailure(int code, String msg) {
// TODO Auto-generated method stub
ShowToast("头像更新失败:" + msg);
}
});
}
上传之后,就是更新当前头像了
/**
* 更新头像 refreshAvatar
*
* @return void
* @throws
*/
private void refreshAvatar(String avatar) {
if (avatar != null && !avatar.equals("")) {
//iv_set_avator是显示头像的imageview
ImageLoader.getInstance().displayImage(avatar, iv_set_avator,
ImageLoadOptions.getOptions());
} else {
iv_set_avator.setImageResource(R.drawable.default_head);
}
}
好了。到这里,从选择照片还是拍照,到上传文件更新头像的步骤就全部搞定了。还有什么不懂的话。就下载源码进行研究把。