摘自: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);
}
}
好了。到這裏,從選擇照片還是拍照,到上傳文件更新頭像的步驟就全部搞定了。還有什麼不懂的話。就下載源碼進行研究把。