拍照或者从相册中挑选图片设置头像是很常见的功能。同样是网上搜索了资料,知道了可以调用系统的功能实现,然后就试着开始写了。先是布局文件,就是一个ImageView和一个TextView。
<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里有没有存过名字,有的话就从缓存图片中读取出来设置到界面。