Android App开发常用功能之用户头像选择

来源:互联网 发布:怎么看数据库版本 编辑:程序博客网 时间:2024/05/23 17:15

前言

现在的APP基本都有个人资料的填写,基本的都有头像的选择,支持拍照和从本地相册选择,剪切圆形头像的功能,现在用个小demo实现以下。

下面看一下效果图


上代码:

主界面代码

package com.example.androidpersonal_icon;import android.os.Bundle;import android.os.Environment;import android.provider.MediaStore;import android.util.Log;import android.view.Gravity;import android.view.View;import android.view.View.OnClickListener;import android.widget.ImageView;import java.io.File;import android.app.Activity;import android.content.Intent;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.net.Uri;public class MainActivity extends Activity {protected static final int CHOOSE_PICTURE = 0;protected static final int TAKE_PICTURE = 1;private static final int CROP_SMALL_PICTURE = 2;protected static Uri tempUri;private ImageView iv_personal_icon;private SelectPicPopupWindow menuWindow;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 新建一个用来存储照片的文件夹File destDir = new File(Environment.getExternalStorageDirectory() + "/AndroidPersonal_icon");if (!destDir.exists()) {destDir.mkdirs();}iv_personal_icon = (ImageView) findViewById(R.id.iv_personal_icon);iv_personal_icon.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {// 实例化SelectPicPopupWindowmenuWindow = new SelectPicPopupWindow(MainActivity.this, itemsOnClick);// 显示窗口menuWindow.showAtLocation(MainActivity.this.findViewById(R.id.main),Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, 0); // 设置layout在PopupWindow中显示的位置}});// 读取上一次剪切的照片if (destDir.exists() && destDir.isDirectory()) {if (destDir.list().length > 0) {Log.d("111111111112", destDir.toString() + "/image_icon.png");Bitmap bitmap = BitmapFactory.decodeFile(destDir.toString() + "/image_icon.png");iv_personal_icon.setImageBitmap(bitmap);} else {iv_personal_icon.setBackgroundResource(R.drawable.default_personal_image);}}}// 为弹出窗口实现监听类private OnClickListener itemsOnClick = new OnClickListener() {public void onClick(View v) {menuWindow.dismiss();switch (v.getId()) {case R.id.Layout_take_photo:Intent openCameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);tempUri = Uri.fromFile(new File(Environment.getExternalStorageDirectory() + "/AndroidPersonal_icon", "image.jpg"));Log.d("11111111", tempUri.toString());// 指定照片保存路径(SD卡),image.jpg为一个临时文件,每次拍照后这个图片都会被替换openCameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, tempUri);startActivityForResult(openCameraIntent, TAKE_PICTURE);break;case R.id.Layout_pick_photo:Intent openAlbumIntent = new Intent(Intent.ACTION_GET_CONTENT);openAlbumIntent.setType("image/*");startActivityForResult(openAlbumIntent, CHOOSE_PICTURE);break;default:break;}}};@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);if (resultCode == RESULT_OK) { // 如果返回码是可以用的switch (requestCode) {case TAKE_PICTURE:startPhotoZoom(tempUri); // 开始对图片进行裁剪处理break;case CHOOSE_PICTURE:startPhotoZoom(data.getData()); // 开始对图片进行裁剪处理break;case CROP_SMALL_PICTURE:if (data != null) {setImageToView(data); // 让刚才选择裁剪得到的图片显示在界面上}break;}}}/** * 裁剪图片方法实现 *  * @param uri */protected void startPhotoZoom(Uri uri) {if (uri == null) {Log.i("tag", "The uri is not exist.");}tempUri = uri;Intent intent = new Intent("com.android.camera.action.CROP");intent.setDataAndType(uri, "image/*");// 设置裁剪intent.putExtra("crop", "true");// aspectX aspectY 是宽高的比例intent.putExtra("aspectX", 1);intent.putExtra("aspectY", 1);// outputX outputY 是裁剪图片宽高intent.putExtra("outputX", 150);intent.putExtra("outputY", 150);intent.putExtra("return-data", true);startActivityForResult(intent, CROP_SMALL_PICTURE);}/** * 保存裁剪之后的图片数据 *  * @param *  * @param picdata */protected void setImageToView(Intent data) {Bundle extras = data.getExtras();if (extras != null) {Bitmap photo = extras.getParcelable("data");photo = Utils.toRoundBitmap(photo, tempUri); // 这个时候的图片已经被处理成圆形的了iv_personal_icon.setImageBitmap(photo);uploadPic(photo);}}private void uploadPic(Bitmap bitmap) {// 上传至服务器// ... 可以在这里把Bitmap转换成file,然后得到file的url,做文件上传操作// 注意这里得到的图片已经是圆形图片了// bitmap是没有做个圆形处理的,但已经被裁剪了String imagePath = Utils.savePhoto(bitmap,Environment.getExternalStorageDirectory().getAbsolutePath() + "/AndroidPersonal_icon", "image_icon");Log.d("imagePath", imagePath + "");if (imagePath != null) {// 拿着imagePath上传了// ...}}}

圆形头像剪切代码:

package com.example.androidpersonal_icon;import java.io.File;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import android.graphics.Bitmap;import android.graphics.Bitmap.Config;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.PorterDuff.Mode;import android.graphics.PorterDuffXfermode;import android.graphics.Rect;import android.graphics.RectF;import android.net.Uri;import android.util.Log;public class Utils {/** * Save image to the SD card *  * @param photoBitmap * @param photoName * @param path */public static String savePhoto(Bitmap photoBitmap, String path,String photoName) {String localPath = null;if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) {File dir = new File(path);if (!dir.exists()) {dir.mkdirs();}File photoFile = new File(path, photoName + ".png");FileOutputStream fileOutputStream = null;try {fileOutputStream = new FileOutputStream(photoFile);if (photoBitmap != null) {if (photoBitmap.compress(Bitmap.CompressFormat.PNG, 100,fileOutputStream)) { // 转换完成localPath = photoFile.getPath();fileOutputStream.flush();}}} catch (FileNotFoundException e) {photoFile.delete();localPath = null;e.printStackTrace();} catch (IOException e) {photoFile.delete();localPath = null;e.printStackTrace();} finally {try {if (fileOutputStream != null) {fileOutputStream.close();fileOutputStream = null;}} catch (IOException e) {e.printStackTrace();}}}return localPath;}/** * 转换图片成圆形 *  * @param bitmap *            传入Bitmap对象 * @param tempUri * @return */public static Bitmap toRoundBitmap(Bitmap bitmap, Uri tempUri) {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;left = 0;top = 0;right = width;bottom = 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, 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); // 填充整个Canvaspaint.setColor(color);// 以下有两种方法画圆,drawRounRect和drawCircle// canvas.drawRoundRect(rectF, roundPx, roundPx, paint);//// 画圆角矩形,第一个参数为图形显示区域,第二个参数和第三个参数分别是水平圆角半径和垂直圆角半径。canvas.drawCircle(roundPx, roundPx, roundPx, paint);paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));// 设置两张图片相交时的模式,参考http://trylovecatch.iteye.com/blog/1189452canvas.drawBitmap(bitmap, src, dst, paint); // 以Mode.SRC_IN模式合并bitmap和已经draw了的Circlereturn output;}}

ok,大功告成,最后别忘了在清单文件中添加读写sd可权限,不然得不到imagePath

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />


文章参考地址:http://blog.csdn.net/ydxlt/article/details/48024017


demo下载地址:http://download.csdn.net/detail/qq_31546677/9906678

原创粉丝点击