调用系统相册,完成更换头像的操作

一直以来都说要写博客,前面好几篇都是写了标题,就没写内容,看了鸿洋大神和吴小龙同学的博客,决定自己也开始写属于自己的博客,并且坚持下来.
  先要把自己以前留下的坑给弥补上,今天先完成更换头像的操作,根据项目中实际的需求,步骤一步步完成.
  在我实际的项目开发中,点击更换头像按钮,会进入到一个选择图片的界面,这个界面会预先给24张头像供用户选择.当用户点击随意一张时,返回原来的界面,并更换头像,同时会在24张头像上方显示一个最近使用图片这么一项,最近使用图片最多可以有8张,
这是显示的效果图
这是实现的效果图,下面是使用gridView做的,上面是使用线性布局动态添加一个个View上去,实现的效果.在这里要说一下,GridView添加头布局使用的是GridViewWithHeaderAndFooter这么一个控件,github的地址,使用方法很合listview添加头布局一样,直接add就行,需要注意的是,也需要放在setAdapter前面进行.
  点击右上角的按钮,会让选择是拍照还是从系统图库选择照片,这里先介绍调用系统的相机进行拍照,下面是实现的代码:

     /**
     * 开启相机
     */
    private void startCarema() {
        // 激活相机
        Intent intentCarema = new Intent("android.media.action.IMAGE_CAPTURE");
        // 判断存储卡是否可以用,(判断存储卡是否可用的方法没有提供),可用进行存储
        if (hasSdcard()) {
            tempFile = new File(Environment.getExternalStorageDirectory(), System.currentTimeMillis() + "");
            // 从文件中创建uri
            Uri uri = Uri.fromFile(tempFile);
            intentCarema.putExtra(MediaStore.EXTRA_OUTPUT, uri);
        }
        // 开启一个带有返回值的Activity,请求码为PHOTO_REQUEST_CAREMA
        startActivityForResult(intentCarema, REQUESTCODE_CAREMA);
    }
    
	/**
     * 判断sdcard是否被挂载
     * @return 判断是否有sd卡
     */
    public static boolean hasSdcard() {
        if (Environment.getExternalStorageState().equals(
                Environment.MEDIA_MOUNTED)) {
            return true;
        } else {
            return false;
        }
    }

这样就会调用系统的相机进行拍照,然后返回一个uri,根据uri获取到图片保存在本地的文件地址,得到这个文件地址就可以去操作自己想要的逻辑

case REQUESTCODE_CAREMA: //这里判断是否是从相机界面返回      
     if (hasSdcard()) {
        Uri uri = Uri.fromFile(tempFile);
        //这里得到文件在本地的地址
        String filePath = getRealFilePath(this, uri);
     } else {
        Toast.makeText(this, "未找到存储卡,无法存储照片!", Toast.LENGTH_SHORT).show();
       }             
       break;

这是根据uri获取本地文件地址的方法:

	/**
     * 根据uri获取图片的真实路径(本地存储的路径)
     * @param context
     * @param uri
     * @return
     */
    public static String getRealFilePath(final Context context, final Uri uri) {
        if (null == uri) return null;
        final String scheme = uri.getScheme();
        String data = null;
        if (scheme == null)
            data = uri.getPath();
        else if (ContentResolver.SCHEME_FILE.equals(scheme)) {
            data = uri.getPath();
        } else if (ContentResolver.SCHEME_CONTENT.equals(scheme)) {
            Cursor cursor = context.getContentResolver().query(uri, new String[]{MediaStore.Images.ImageColumns.DATA}, null, null, null);
            if (null != cursor) {
                if (cursor.moveToFirst()) {
                    int index = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
                    if (index > -1) {
                        data = cursor.getString(index);
                    }
                }
                cursor.close();
            }
        }
        return data;
    }

上面是打开系统的相机,返回所拍的照片,返回的是uri,需要转换成本地的文件地址,然后再进行后续的操作,因为国产的手机rom不同,有的照片可能会进行过特殊处理,例如三星的会对照片进行旋转90度,所以在显示图片的时候,需要判断照片是否旋转了.

/**
     * 读取照片exif信息中的旋转角度
     *
     * @param path 照片路径
     * @return int 照片的旋转家督
     */
    public static int readPictureDegree(String path) {
        int degree = 0;
        try {
            ExifInterface exifInterface = new ExifInterface(path);
            int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
            switch (orientation) {
                case ExifInterface.ORIENTATION_ROTATE_90:
                    degree = 90;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_180:
                    degree = 180;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_270:
                    degree = 270;
                    break;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return degree;
    }

如果旋转了就需要旋转回正确的角度.

/**
  * degree就是上面那个方法计算出来旋转的角度
  */
	public static Bitmap toTurn(Bitmap img, int degree) {
        Log.d("ClipPhotoActivity", "degree:" + degree);
        Matrix matrix = new Matrix();
        matrix.postRotate(+degree); /*翻转90度*/
        int width = img.getWidth();
        int height = img.getHeight();
        img = Bitmap.createBitmap(img, 0, 0, width, height, matrix, true);
        return img;
    }

当前项目只是遇到这样的问题,如果后续遇到问题,再添加(加载图片的时候注意OOM异常).
  下面是调用系统的图库选取图片,很简单就是几行代码:

	 /**
     * 进入系统图库
     */
    private void startSystemGallery() {
        //进入系统图库
        Intent intent = new Intent(Intent.ACTION_PICK);
        intent.setType("image/*");
        startActivityForResult(intent, REQUESTCODE_LOCATIONPHOTO);
    }

在得到的返回值里进行处理:

			case REQUESTCODE_LOCATIONPHOTO:    // 从相册返回的数据
                if (data != null) {
                    // 得到图片的全路径
                    Uri uri = data.getData();
                    String filePath = getRealFilePath(this, uri);
                }
                break;

不管是从相机获取到图片还是从图库获取到图片,最后都获取到图片在本地存储的地址,如果各个界面之间需要将图片作为参数携带跳转的话,就使用图片的地址传递,如果之间传递图片的话,会超过intent所能携带的最大值.
  当然很少有情况是需要显示图库或者相机的照片,一般都是需要拿来裁剪做头像才使用这样的功能,这样就牵扯到使用裁剪的功能,裁剪可以使用系统的裁剪或者使用第三方的裁剪.
  使用系统的裁剪功能:

	private void cropImageUri(Uri uri, int outputX, int outputY, int requestCode) {
        Intent intent = new Intent("com.android.camera.action.CROP");
        intent.setDataAndType(uri, "image/*");
        //是否裁剪  
        intent.putExtra("crop", "true");
        //设置xy的裁剪比例  
        intent.putExtra("aspectX", 2);
        intent.putExtra("aspectY", 1);
        //设置输出的宽高  
        intent.putExtra("outputX", outputX);
        intent.putExtra("outputY", outputY);
        //是否缩放  
        intent.putExtra("scale", false);
        //输入图片的Uri,指定以后,可以在这个uri获得图片  
        intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
        //是否返回图片数据,可以不用,直接用uri就可以了  
        intent.putExtra("return-data", false);
        //设置输入图片格式  
        intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
        //是否关闭面部识别  
        intent.putExtra("noFaceDetection", true); // no face detection  
        //启动  
        startActivityForResult(intent, requestCode);
    }

我这个项目使用的是鸿洋的控件博客地址,也可以使用更为强大的裁剪控件uCrop的github地址,都是可以的,根据自己项目中的需求来完成.
  第一篇大致博客完成了,感觉写的不是很好,我相信会慢慢的好起来的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值