Android更改头像功能

一、UI显示

今天我来总结一下应用中我们常用的更改头像的功能。先上图看一下效果。
这里写图片描述
其实我们在更改头像的时候,我们分为两个部分
1、使用手机的拍照功能(可以使用系统的照相机,也可以是自定义的照相机)
2、使用手机中原有的照片进行使用
这里我进行一起总结。

二、代码的分析

1、使用照相机进行拍照上传头像

    try {
         Intent _intentTakePhoto = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
         if (FileManager.hasSdCard()){
             _intentTakePhoto.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(getExternalCacheDir(), mPictureName)));
            }
        startActivityForResult(_intentTakePhoto,Constants.ActivityCode.REQUEST_CODE_CAMERA);
            }catch (Exception _e){
                ExceptionHandler.onException(_e);
            }
/**
     * judge has card
     * @return
     */
    public static boolean hasSdCard(){
        try {
            String _state = Environment.getExternalStorageState();
            if (_state.equals(Environment.MEDIA_MOUNTED))
                return true;
        }catch (Exception _e){
            ExceptionHandler.onException(_e);
            return false;
        }
        return false;
    }

讲解:
1、我们先使用MediaStore.ACTION_IMAGE_CAPTURE的Intent来调出相机界面
2、我们拍完照片需要把照片保存到手机的存储卡中,这里我们使用hasSdCard()方法来进行判断是否又SD卡
3、当有SD卡的时候,我们将拍完的照片存储到SD卡中

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == RESULT_CANCELED){
            Toast.makeText(ActivityMyInfo.this, R.string.view_random_code_dialog_cancel, Toast.LENGTH_SHORT).show();
            return;
        }
        switch (requestCode){
            case Constants.ActivityCode.REQUEST_CODE_CAMERA:
                if (FileManager.hasSdCard()){
                    if(null == mPictureName)
                        return;
                    File _cameraFile = new File(getExternalCacheDir(), mPictureName);
                    cropRawPhoto(Uri.fromFile(_cameraFile));
                }else {
                    Toast.makeText(ActivityMyInfo.this, R.string.activity_my_info_toast_no_sdcard, Toast.LENGTH_SHORT).show();
                }
                break;
            case Constants.ActivityCode.REQUEST_CODE_CROP_PICTURE:
                Bundle _headBundle = data.getExtras();
                Bitmap _headBitmap = null,_bitmapRound = null,_bitmapComp = null;
                if (null != _headBundle){
                    _headBitmap = _headBundle.getParcelable("data");
                }else {
                    Uri _fileUri = data.getData();
                    if (null != _fileUri){
                        try {
                            _headBitmap = MediaStore.Images.Media.getBitmap(getContentResolver(),_fileUri);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }else{
                        Toast.makeText(ActivityMyInfo.this, R.string.activity_my_info_toast_dont_get_head, Toast.LENGTH_SHORT).show();
                        return;
                    }
                }
                _bitmapComp = ImageUtil.compBitmap(_headBitmap);
                mPicturePath = String.valueOf(FileManager.saveBitmapToSD(this,_bitmapComp,mPictureName));
                isNeedUploadHeadImage = true;
                mImageViewHeadIcon.setImageBitmap(_bitmapComp);
                break;
        }
            super.onActivityResult(requestCode, resultCode, data);
    }
/**
     * crop picture
     * @param uri
     */
    public void cropRawPhoto(Uri uri) {
        try {
            Intent _intent = new Intent("com.android.camera.action.CROP");
            _intent.setDataAndType(uri, "image/*");
            _intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(getExternalCacheDir(), mPictureName)));
            // 设置裁剪
            _intent.putExtra("crop", "true");
            // aspectX , aspectY :宽高的比例
            _intent.putExtra("aspectX", 1);
            _intent.putExtra("aspectY", 1);
            // outputX , outputY : 裁剪图片宽高
            _intent.putExtra("outputX", 250);
            _intent.putExtra("outputY", 250);
            _intent.putExtra("return-data", true);
            startActivityForResult(_intent, Constants.ActivityCode.REQUEST_CODE_CROP_PICTURE);
        }catch (Exception _e){
            ExceptionHandler.onException(_e);
        }
    }

讲解:
1、使用了startActivityForResult()之后,我们在onActivityResult()的函数中接收拍照后的结果
2、在取消拍照后,我使用了一个Toast来提示取消了拍照
3、如果拍照后返回成功,这里使用了cropRawPhoto()来进行对拍完的照片进行剪切
4、剪切成功之后,我们在最后一个case中进行处理剪切后的数据
5、这里要注意一点:剪切之后这里的Bundle中数据可能为空,原因因为自己暂时还没有研究,欢迎在坐的大神留言告诉我一下。我们这里就分开进行处理
6、获取到了这里的图片数据Bitmap,还需要对获取到的Bitmap进行处理,原因是图片太大会出现OOM的问题。我在文末就直接上压缩图片的代码了,大家可以研究一下。
7、最后使用fresco进行图片的显示
8、如果上传到服务器的话,最后我们还可以在上传服务器成功之后,删除图片文件,不然图片文件就一直在内存卡中了

2、使用选择图片进行上传

try {
            Intent _intentSelectPhoto = new Intent(Intent.ACTION_PICK);
            _intentSelectPhoto.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,"image/*");
            startActivityForResult(_intentSelectPhoto,Constants.ActivityCode.REQUEST_CODE_GALLERY);
        }catch (Exception _e){
            ExceptionHandler.onException(_e);
        }

讲解:
1、使用Intent.ACTION_PICK的Intent来打开相册,进行选择照片

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == RESULT_CANCELED){
            Toast.makeText(ActivityMyInfo.this, R.string.view_random_code_dialog_cancel, Toast.LENGTH_SHORT).show();
            return;
        }
        switch (requestCode){
            case Constants.ActivityCode.REQUEST_CODE_GALLERY:
                cropRawPhoto(data.getData());
                break;
            case Constants.ActivityCode.REQUEST_CODE_CROP_PICTURE:
                Bundle _headBundle = data.getExtras();
                Bitmap _headBitmap = null,_bitmapRound = null,_bitmapComp = null;
                if (null != _headBundle){
                    _headBitmap = _headBundle.getParcelable("data");
                }else {
                    Uri _fileUri = data.getData();
                    if (null != _fileUri){
                        try {
                            _headBitmap = MediaStore.Images.Media.getBitmap(getContentResolver(),_fileUri);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }else{
                        Toast.makeText(ActivityMyInfo.this, R.string.activity_my_info_toast_dont_get_head, Toast.LENGTH_SHORT).show();
                        return;
                    }
                }
                _bitmapComp = ImageUtil.compBitmap(_headBitmap);
                mPicturePath = String.valueOf(FileManager.saveBitmapToSD(this,_bitmapComp,mPictureName));
                isNeedUploadHeadImage = true;
                mImageViewHeadIcon.setImageBitmap(_bitmapComp);
                break;
        }
            super.onActivityResult(requestCode, resultCode, data);
    }

讲解:
1、这里比拍照选择会比较简单一点,不过也可以使用剪切图片来进行上传
2、其余的都和拍照后剪切是一样的

三、代码展示

最后全部代码贴出来,因为没有注释,如果大家有什么问题,欢迎找我。
1、take picture

/**
     * take picture
     */
    public void takePicture(){
        try {
            Intent _intentTakePhoto = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            if (FileManager.hasSdCard()){
                _intentTakePhoto.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(getExternalCacheDir(), mPictureName)));
            }
            startActivityForResult(_intentTakePhoto,Constants.ActivityCode.REQUEST_CODE_CAMERA);
        }catch (Exception _e){
            ExceptionHandler.onException(_e);
        }
    }

2、pick picture

/**
     * pick picture
     */
    public void pickPicture(){
        try {
            Intent _intentSelectPhoto = new Intent(Intent.ACTION_PICK);
            _intentSelectPhoto.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,"image/*");
            startActivityForResult(_intentSelectPhoto,Constants.ActivityCode.REQUEST_CODE_GALLERY);
        }catch (Exception _e){
            ExceptionHandler.onException(_e);
        }
    }

3、onActivityResult()函数中的处理

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == RESULT_CANCELED){
            Toast.makeText(ActivityMyInfo.this, R.string.view_random_code_dialog_cancel, Toast.LENGTH_SHORT).show();
            return;
        }
        switch (requestCode){
            case Constants.ActivityCode.REQUEST_CODE_CAMERA:
                if (FileManager.hasSdCard()){
                    if(null == mPictureName)
                        return;
                    File _cameraFile = new File(getExternalCacheDir(), mPictureName);
                    cropRawPhoto(Uri.fromFile(_cameraFile));
                }else {
                    Toast.makeText(ActivityMyInfo.this, R.string.activity_my_info_toast_no_sdcard, Toast.LENGTH_SHORT).show();
                }
                break;
            case Constants.ActivityCode.REQUEST_CODE_GALLERY:
                cropRawPhoto(data.getData());
                break;
            case Constants.ActivityCode.REQUEST_CODE_CROP_PICTURE:
                Bundle _headBundle = data.getExtras();
                Bitmap _headBitmap = null,_bitmapRound = null,_bitmapComp = null;
                if (null != _headBundle){
                    _headBitmap = _headBundle.getParcelable("data");
                }else {
                    Uri _fileUri = data.getData();
                    if (null != _fileUri){
                        try {
                            _headBitmap = MediaStore.Images.Media.getBitmap(getContentResolver(),_fileUri);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }else{
                        Toast.makeText(ActivityMyInfo.this, R.string.activity_my_info_toast_dont_get_head, Toast.LENGTH_SHORT).show();
                        return;
                    }
                }
                _bitmapComp = ImageUtil.compBitmap(_headBitmap);
                mPicturePath = String.valueOf(FileManager.saveBitmapToSD(this,_bitmapComp,mPictureName));
                isNeedUploadHeadImage = true;
                mImageViewHeadIcon.setImageBitmap(_bitmapComp);
                break;
        }
            super.onActivityResult(requestCode, resultCode, data);
    }

4、剪切图片

/**
     * crop picture
     * @param uri
     */
    public void cropRawPhoto(Uri uri) {
        try {
            Intent _intent = new Intent("com.android.camera.action.CROP");
            _intent.setDataAndType(uri, "image/*");
            _intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(getExternalCacheDir(), mPictureName)));
            // 设置裁剪
            _intent.putExtra("crop", "true");
            // aspectX , aspectY :宽高的比例
            _intent.putExtra("aspectX", 1);
            _intent.putExtra("aspectY", 1);
            // outputX , outputY : 裁剪图片宽高
            _intent.putExtra("outputX", 250);
            _intent.putExtra("outputY", 250);
            _intent.putExtra("return-data", true);
            startActivityForResult(_intent, Constants.ActivityCode.REQUEST_CODE_CROP_PICTURE);
        }catch (Exception _e){
            ExceptionHandler.onException(_e);
        }
    }

5、对图片进行处理,压缩图片,圆图像等

/**
     *compression imageview
     * @param _imageBitmap
     * @return
     */
    public static Bitmap compBitmap(Bitmap _imageBitmap) {
        try {
            if (null == _imageBitmap)
                return null;
            ByteArrayOutputStream _baos = new ByteArrayOutputStream();
            _imageBitmap.compress(Bitmap.CompressFormat.JPEG, 100, _baos);
            if( _baos.toByteArray().length / 1024>1024) {//判断如果图片大于1M,进行压缩避免在生成图片(BitmapFactory.decodeStream)时溢出
                _baos.reset();//重置baos即清空baos
                _imageBitmap.compress(Bitmap.CompressFormat.JPEG, 50, _baos);//这里压缩50%,把压缩后的数据存放到baos中
            }
            ByteArrayInputStream isBm = new ByteArrayInputStream(_baos.toByteArray());
            BitmapFactory.Options newOpts = new BitmapFactory.Options();
            //开始读入图片,此时把options.inJustDecodeBounds 设回true了
            newOpts.inJustDecodeBounds = true;
            newOpts.inPreferredConfig = Bitmap.Config.RGB_565;
            Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, newOpts);
            int w = newOpts.outWidth;
            int h = newOpts.outHeight;
            //现在主流手机比较多是800*480分辨率,所以高和宽我们设置为
            float hh = 800f;//这里设置高度为800f
            float ww = 480f;//这里设置宽度为480f
            //缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可
            int be = 1;//be=1表示不缩放
            if (w > h && w > ww) {//如果宽度大的话根据宽度固定大小缩放
                be = (int) (newOpts.outWidth / ww);
            } else if (w < h && h > hh) {//如果高度高的话根据宽度固定大小缩放
                be = (int) (newOpts.outHeight / hh);
            }
            if (be <= 0)
                be = 1;
            newOpts.inSampleSize = be;//设置缩放比例
            //重新读入图片,注意此时已经把options.inJustDecodeBounds 设回false了
            newOpts.inJustDecodeBounds = false;
            isBm = new ByteArrayInputStream(_baos.toByteArray());
            bitmap = BitmapFactory.decodeStream(isBm, null, newOpts);
            return compressImage(bitmap);//压缩好比例大小后再进行质量压缩
        }catch (Exception _e){
            ExceptionHandler.onException(_e);
            return null;
        }


      public static Bitmap compressImage(Bitmap _image) {
        try {
            if (null == _image)
                return null;
            ByteArrayOutputStream _baos = new ByteArrayOutputStream();
            _image.compress(Bitmap.CompressFormat.JPEG, 100, _baos);//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
            int options = 100;
            while ( _baos.toByteArray().length / 1024>100) {//循环判断如果压缩后图片是否大于100kb,大于继续压缩
                _baos.reset();//重置baos即清空baos
                _image.compress(Bitmap.CompressFormat.JPEG, options, _baos);//这里压缩options%,把压缩后的数据存放到baos中
                options -= 10;//每次都减少10
            }
            ByteArrayInputStream isBm = new ByteArrayInputStream(_baos.toByteArray());//把压缩后的数据baos存放到ByteArrayInputStream中
            Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);//把ByteArrayInputStream数据生成图片
            return makeRoundCorner(bitmap);
        }catch (Exception _e){
            ExceptionHandler.onException(_e);
            return null;
        }
    }


    /**
     * 转换图片成圆形
     * @param bitmap 传入Bitmap对象
     * @return
     */
    public static Bitmap makeRoundCorner(Bitmap bitmap)
    {
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();
        int left = 0, top = 0, right = width, bottom = height;
        float roundPx = height/2;
        if (width > height) {
            left = (width - height)/2;
            top = 0;
            right = left + height;
            bottom = height;
        } else if (height > width) {
            left = 0;
            top = (height - width)/2;
            right = width;
            bottom = top + width;
            roundPx = width/2;
        }
        Bitmap output = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(output);
        int color = 0xff424242;
        Paint paint = new Paint();
        Rect rect = new Rect(left, top, right, bottom);
        RectF rectF = new RectF(rect);

        paint.setAntiAlias(true);
        canvas.drawARGB(0, 0, 0, 0);
        paint.setColor(color);
        canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(bitmap, rect, rect, paint);
        return output;
    }
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值