拍照或者從相冊中挑選圖片設置頭像是很常見的功能。同樣是網上搜索了資料,知道了可以調用系統的功能實現,然後就試着開始寫了。先是佈局文件,就是一個ImageView和一個TextView。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ImageView
android:layout_width="200dp"
android:layout_height="200dp"
android:id="@+id/imageView"
android:background="@mipmap/ic_launcher"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="151dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="點擊修改頭像"
android:textSize="25sp"
android:id="@+id/textView"
android:layout_marginTop="108dp"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true" />
</RelativeLayout>
MainActivity.java
package com.sy.myphoto;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.text.TextUtils;
import android.view.View;
import android.widget.ImageView;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import java.io.ByteArrayOutputStream;
public class MainActivity extends Activity {
private ImageView iv;
private View view;
private RadioGroup group;
private RadioButton rb_camera;
private RadioButton rb_photo;
private String SDCardPath = Environment.getExternalStorageDirectory().getAbsolutePath();//sd卡路徑
private static final int PHOTO_REQUEST_TAKEPHOTO = 1;// 拍照
private static final int PHOTO_REQUEST_GALLERY = 2;// 從相冊中選擇
private static final int PHOTO_REQUEST_CUT = 3;// 結果
private AlertDialog.Builder builder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();//初始化控件
initEvent();//初始化事件
setImage();//如果有設置過頭像,set上之前的頭像
}
/**
* 從SharedPreferences裏讀取圖片名稱,從緩存中讀取圖片,設置圖片,如果沒有保存過就什麼也不做
*/
private void setImage() {
SharedPreferences sp = getSharedPreferences("imageName", MODE_PRIVATE);
String imageName = sp.getString("name", "");
if (TextUtils.isEmpty(imageName)) {
} else {
byte[] p = FileUtils.readBytes(SDCardPath + "/imageCache", imageName);
if(p!=null){
Bitmap bitmap = BitmapFactory.decodeByteArray(p, 0, p.length);
//設置到界面
Drawable drawable = new BitmapDrawable(bitmap);
iv.setBackgroundDrawable(drawable);
}
}
}
private void initEvent() {
iv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//設置一個帶items的dialog
final String[] items = new String[]{"拍照", "相冊"};
new AlertDialog.Builder(MainActivity.this).setTitle("選擇").setItems(items, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
switch (which) {
case 0:
// 調用系統的拍照功能
Intent intent1 = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent1, PHOTO_REQUEST_TAKEPHOTO);
break;
case 1:
//調用系統圖庫
Intent intent2 = new Intent(Intent.ACTION_PICK, null);
intent2.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
startActivityForResult(intent2, PHOTO_REQUEST_GALLERY);
break;
}
}
}).show();
}
});
}
private void initView() {
iv = (ImageView) findViewById(R.id.imageView);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case PHOTO_REQUEST_TAKEPHOTO:// 當選擇拍照時調用
if (data != null)
startPhotoZoom(data.getData(), 150);
break;
case PHOTO_REQUEST_GALLERY:// 當選擇從本地獲取圖片時
// 做非空判斷,當我們覺得不滿意想重新剪裁的時候便不會報異常
if (data != null)
startPhotoZoom(data.getData(), 150);
break;
case PHOTO_REQUEST_CUT:// 返回的結果
if (data != null)
saveAndsetPic(data);
break;
}
super.onActivityResult(requestCode, resultCode, data);
}
private void startPhotoZoom(Uri uri, int size) {
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", size);
intent.putExtra("outputY", size);
intent.putExtra("return-data", true);
startActivityForResult(intent, PHOTO_REQUEST_CUT);
}
private void saveAndsetPic(Intent picdata) {
Bundle bundle = picdata.getExtras();
if (bundle != null) {
Bitmap photo = bundle.getParcelable("data");
//保存到SD卡
String imageName = MD5Utils.md5(System.currentTimeMillis() + "");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
photo.compress(Bitmap.CompressFormat.PNG, 100, baos);
byte[] p = baos.toByteArray();
FileUtils.writeBytes(SDCardPath + "/imageCache", imageName, p);
//將圖片名字保存帶本地
SharedPreferences sp = getSharedPreferences("imageName", MODE_PRIVATE);
sp.edit().putString("name", imageName).commit();
//設置到界面
Drawable drawable = new BitmapDrawable(photo);
iv.setBackgroundDrawable(drawable);
}
}
}
主要就是調用系統相冊相機和裁剪的uri,然後通過 startActivityForResult,onActivityResult方法完成的。關於startActivityForResult 之前我有學過。在onActivityResult方法里根據requestCode的不同判斷進行裁剪還是設置界面。在裁剪方法startPhotoZoom裏,設置intent的附加參數的解釋如下:
在saveAndsetPic方法裏,除了設置界面,我把裁剪好的圖片保存到本地SD卡上,然後爲了方便以時間戳md5加密作爲圖片名字存到了SharedPreferences裏。下次打開時先檢查SharedPreferences裏有沒有存過名字,有的話就從緩存圖片中讀取出來設置到界面。