Android 头像选择功能实战

一、图片选择

1.1 目标

  1. 实现如图所示功能:能够出现相册和相机选项
  2. 能够对选择的图片进行裁剪

1.2 功能实现

1.2.1 Intent工具类封装

封装图片选择和图片裁剪的工具类

    /**
     * 选择图片(从相册或相机)
     * @param uri 相机存储uri
     * @return
     */
    public static Intent getPhotoSelectIntent(Uri uri){
        Intent take = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        take.addCategory(Intent.CATEGORY_DEFAULT);
        take.putExtra(MediaStore.EXTRA_OUTPUT, uri);
        Intent pics = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
        Intent chose= Intent.createChooser(pics,"选择图片");
        chose.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Parcelable[]{take});
        return chose;
    }

    /**
     * 图片裁剪
     * @param inputUri 需要裁剪的图片
     * @param outputUri 裁剪后存储位置
     * @param width 裁剪宽度
     * @param height 裁剪高度
     * @return
     */
    public static Intent getImageCropIntent(Uri inputUri, Uri outputUri, int width, int height) {
        Intent intent = new Intent("com.android.camera.action.CROP");
        intent.setDataAndType(inputUri, "image/*");
        // 下面这个crop=true是设置在开启的Intent中设置显示的VIEW可裁剪
        intent.putExtra("crop", "true");
        intent.putExtra("scale", true); // 去黑边
        intent.putExtra("scaleUpIfNeeded", true); // 去黑边
        // aspectX aspectY 裁剪框宽高比例
        intent.putExtra("aspectX", width); // 输出是X方向的比例
        intent.putExtra("aspectY", height);
        // outputX outputY 输出图片宽高,切忌不要再改动下列数字,会卡死
        intent.putExtra("outputX", width); // 输出X方向的像素
        intent.putExtra("outputY", height);
        intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
        intent.putExtra("noFaceDetection", true);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, outputUri);
        intent.putExtra("return-data", false); // 设置为不返回数据
        return intent;
    }
复制代码

1.2.2 添加点击图片选择事件

b.ivAvatar.setOnClickListener {
            mTakePhotoFile = File(getPicPath() + File.separator + System.currentTimeMillis() + ".jpeg")
            val uri = Uri.fromFile(mTakePhotoFile)
            startActivityForResult(IntentUtils.getPhotoSelectIntent( uri), TAKE_PHOTO_REQ)
        }
复制代码

1.2.3 处理图片选择和裁剪反馈

图片裁剪所需的Uri类似:content:// 的形式,因此需要封装一个获取content Uri的工具类

public static Uri getContentUri(Context context, File file) {
        String filePath = file.getAbsolutePath();
        Cursor cursor = context.getContentResolver().query(
                MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                new String[] { MediaStore.Images.Media._ID },
                MediaStore.Images.Media.DATA + "=? ",
                new String[] { filePath }, null);
        if (cursor != null && cursor.moveToFirst()) {
            int id = cursor.getInt(cursor
                    .getColumnIndex(MediaStore.MediaColumns._ID));
            Uri baseUri = Uri.parse("content://media/external/images/media");
            return Uri.withAppendedPath(baseUri, "" + id);
        } else {
            if (file.exists()) {
                ContentValues values = new ContentValues();
                values.put(MediaStore.Images.Media.DATA, filePath);
                return context.getContentResolver().insert(
                        MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
            } else {
                return null;
            }
        }
    }
复制代码

处理反馈结果

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if(resultCode != -1) {
            return
        }
        when (requestCode) {
            TAKE_PHOTO_REQ -> {
                // 处理图片选择结果
                mCutPhotoFile = File(getPicPath() + File.separator + "avatar_" + System.currentTimeMillis() + "jpeg")
                val cutUri = Uri.fromFile(mCutPhotoFile)
                if (data != null){
                    startActivityForResult(IntentUtils.getImageCropIntent(data.data, cutUri, 200, 200), CUT_PHOTO_REQ)
                } else {
                    val uri = UriUtils.getContentUri(applicationContext, mTakePhotoFile)
                    startActivityForResult(IntentUtils.getImageCropIntent(uri, cutUri, 200, 200), CUT_PHOTO_REQ)
                }
            }
            CUT_PHOTO_REQ -> {
                // 处理图片裁剪结果
            }
        }
    }
复制代码

1.2.4 Android 7.0适配

1. res/xml/provider_paths.xml 路径自行更换

<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path path="Android/data/com/example/sunmoon/images" name="sdcard_files" />
    <external-files-path   path="Android/data/com/example/sunmoon/images" name="camera_has_sdcard"/>
    <files-path path="Android/data/com/example/sunmoon/other"     name="camera_no_sdcard"/>
    <external-path path="Android/data/com/example/sunmoon" name="files_root" />
    <external-path path="." name="external_storage_root" />
</paths>
复制代码

2. manifests配置 包名自行更换

...
<application>
        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="com.example.sunmoon.provider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/provider_paths"/>
        </provider>
   ...
</application>
...
复制代码
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值