封装的图片选择工具,通过调用系统API实现,代码量少,侵入性低

    xiaoxiao2022-07-02  124

    package com.konstant.tool.lite.util import android.app.Activity import android.content.Context import android.content.Intent import android.graphics.Bitmap import android.graphics.Color import android.net.Uri import android.os.Build import android.os.Bundle import android.os.Environment import android.provider.MediaStore import android.support.v4.content.FileProvider import android.view.View import android.view.WindowManager import com.konstant.tool.lite.module.setting.SettingManager import java.io.File /** * 时间:2019/5/22 10:49 * 创建:菜籽 * 描述:封装的图片选择器,包含从系统图库获取图片以及从相机获取图片 * 本选择器支持安卓4.0以上版本,同时针对安卓8.0的新特性做了适配工作 * 本质上是启动了一个完全透明的activity,在内部对startActivityForResult进行了封装处理 * * 接口如下: * 通过伴生接口,提供给外部的接口有三个: * 1、fun selectImg(context: Context, name: String, callback: (result: Boolean) -> Unit) * 2、fun takePhoto(context: Context, name: String, callback: (result: Boolean) -> Unit) * 3、fun clipPhoto(context: Context, name: String, callback: (result: Boolean) -> Unit) * 获取的图片一律存放在/storage/emulated/0/Android/包名/files/Pictures 下 * 当接口回调为true时,表示图片已处理完毕,调用者可根据传过来的文件名字获取图片 * 当接口回调false时,基本上用户手动取消了操作,调用者可根据此结果做响应处理 */ class ImageSelector : Activity() { companion object { private val CAMERA_REQUEST = 1 // 拍照 private val PHOTO_REQUEST = 2 // 相册 private val PHOTO_CLIP = 3 // 裁剪 private lateinit var mFileName: String lateinit var mCallback: ((result: Boolean) -> Unit) // 从相册选择图片,提供给外部的接口 fun selectImg(context: Context, name: String, callback: (result: Boolean) -> Unit) { mCallback = callback mFileName = name with(Intent(context, ImageSelector::class.java)) { putExtra("type", PHOTO_REQUEST) flags = Intent.FLAG_ACTIVITY_NEW_TASK context.startActivity(this) } } // 调用摄像机拍摄图片,提供给外部的接口 fun takePhoto(context: Context, name: String, callback: (result: Boolean) -> Unit) { mCallback = callback mFileName = name with(Intent(context, ImageSelector::class.java)) { putExtra("type", CAMERA_REQUEST) flags = Intent.FLAG_ACTIVITY_NEW_TASK context.startActivity(this) } } // 单独的调用系统裁剪图片的接口,这个接口一般很少单独使用,提供给外部的接口 fun clipPhoto(context: Context, name: String, callback: (result: Boolean) -> Unit) { mCallback = callback mFileName = name with(Intent(context, ImageSelector::class.java)) { putExtra("type", PHOTO_CLIP) flags = Intent.FLAG_ACTIVITY_NEW_TASK context.startActivity(this) } } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) invasionStatusBar(this) val type = intent.getIntExtra("type", 0) when (type) { CAMERA_REQUEST -> { val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE) val uri = FileUtil.getPictureUri(this, mFileName) intent.putExtra(MediaStore.EXTRA_OUTPUT, uri) startActivityForResult(intent, CAMERA_REQUEST) } PHOTO_REQUEST -> { with(Intent(Intent.ACTION_PICK)) { setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*") startActivityForResult(this, PHOTO_REQUEST) } } PHOTO_CLIP -> { val uri = FileUtil.getPictureUri(this, mFileName) clipPhoto(uri) } } } // 本activity调用系统的API获取数据后得到的结果,并对结果进行处理 override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { if (resultCode != RESULT_OK) { mCallback.invoke(false) finish() } when (requestCode) { CAMERA_REQUEST -> { val file = File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), mFileName) if (!file.exists()) { mCallback.invoke(false) return } val uri = FileUtil.getPictureUri(this, mFileName) clipPhoto(uri) } PHOTO_REQUEST -> { data?.let { clipPhoto(it.data) } } PHOTO_CLIP -> { mCallback.invoke(true) finish() } else -> { mCallback.invoke(false) finish() } } } // 调用系统中自带的图片剪裁 private fun clipPhoto(uri: Uri) { val cropPhoto = File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), mFileName) with(Intent("com.android.camera.action.CROP")) { setDataAndType(uri, "image/*") addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 下面这个crop=true是设置在开启的Intent中设置显示的VIEW可裁剪 putExtra("crop", "true") putExtra("scale", true) putExtra("aspectX", 1) putExtra("aspectY", 1) //输出的宽高 putExtra("outputX", 300) putExtra("outputY", 300) putExtra("return-data", false) putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(cropPhoto)) putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString()) putExtra("noFaceDetection", true) // no face detection startActivityForResult(this, PHOTO_CLIP) } } // 隐藏系统的状态栏 以及 任务栏 private fun invasionStatusBar(activity: Activity) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { val window = activity.window val decorView = window.decorView decorView.systemUiVisibility = (decorView.systemUiVisibility or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_STABLE) window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) window.statusBarColor = Color.TRANSPARENT } } }

    activity的主题配置:

    <!--透明主题--> <style name="TransparentTheme" parent="@android:style/Theme.Translucent.NoTitleBar"> <item name="android:windowActionBar">false</item> <item name="android:windowNoTitle">true</item> <item name="android:windowBackground">@color/color_transport</item> <item name="android:windowDisablePreview">true</item> </style>

    安卓8.0及以上,需要再清单文件中加入:

    <provider android:name="android.support.v4.content.FileProvider" android:authorities="${applicationId}.provider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider>

    这是文件path配置:

    <?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <external-path name="header_big.jpg" path="images/"/> <external-cache-path name="header_big.jpg" path="."/> <external-path name="header_big.jpg" path="."/> </paths>

     

     

     

    最新回复(0)