这里写自定义目录标题
- github地址 https://github.com/JI577/ChoosePicture
- 调用方式
- 基本配置
- 封装 BasePhotoActivity Kotlin
- 底部弹框 PopupWindow
- 动画样式 styles
- 裁剪方法
github地址 https://github.com/JI577/ChoosePicture
调用方式
class MainActivity : BasePhotoActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
tvPic.setOnClickListener {
if (checkPermission()) {
showDialog()
}
}
}
override fun showDialog() {
getPopView().showAtLocation(llAll, Gravity.BOTTOM, 0, 0)
}
override fun getHeadNet(file: File) {
Log.e("jrq", "File path----" + file.absolutePath)
tvContent.text = file!!.absolutePath
}
}
基本配置
权限
provider
file_path
封装 BasePhotoActivity Kotlin
open abstract class BasePhotoActivity : FragmentActivity() {
private val REQUESTCODE_PICK = 0x121
val RESULT_COD = 102
var picDialog: SelectPicPopupwindow? = null
private val mFile_Pic: File? = null
private val permissions = arrayOf(Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE)
private var dialog: AlertDialog? = null
private var mBitmap: Bitmap? = null
fun getPopView(): SelectPicPopupwindow {
if (null == picDialog) {
headPic()
}
return picDialog!!
}
fun checkPermission(): Boolean {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
for (permission in permissions) {
val i = ContextCompat.checkSelfPermission(this, permission)
if (i != PackageManager.PERMISSION_GRANTED) {
showDialogTipUserRequestPermission()
return false
}
}
}
return true
}
fun showDialogTipUserRequestPermission() {
AlertDialog.Builder(this)
.setTitle("存储权限不可用")
.setMessage("由于选取照片和拍照需要手机的部分权限,否则您将不能使用该应用的全部功能")
.setPositiveButton("立即开启") { dialog, which -> startRequestPermission() }
.setNegativeButton("取消") { dialog, which -> finish() }.setCancelable(false).show()
}
fun startRequestPermission() {
ActivityCompat.requestPermissions(this, permissions, 321)
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == 321) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
val b = shouldShowRequestPermissionRationale(permissions[0])
if (!b) {
showDialogTipUserGoToAppSettting()
} else
finish()
} else {
showDialog()
}
}
}
}
fun showDialogTipUserGoToAppSettting() {
dialog = AlertDialog.Builder(this)
.setTitle("存储权限不可用")
.setMessage("请在-应用设置-权限-中,允许本应用使用相机的相应权限来启用拍照等功能")
.setPositiveButton("立即开启") { dialog, which ->
goToAppSetting()
}
.setNegativeButton("取消") { dialog, which -> finish() }.setCancelable(false).show()
}
fun headPic() {
picDialog = SelectPicPopupwindow(this, View.OnClickListener { v ->
when (v.id) {
R.id.btn_take_photo -> getPicCamera()
R.id.btn_pick_photo -> selectPicture()
}
picDialog!!.dismiss()
}, SelectPicPopupwindow.PHOTO)
}
private var mPictureFile: String? = null
private var filePath: String? = null
private val OPEN_RESULT2 = 0x124
fun getPicCamera() {
val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
intent.addCategory(Intent.CATEGORY_DEFAULT)
mPictureFile = DateFormat.format("yyyyMMdd_hhmmss",
Calendar.getInstance(Locale.CHINA)).toString() + ".jpg"
filePath = getPhotoPath() + mPictureFile!!
val currentapiVersion = android.os.Build.VERSION.SDK_INT
Log.e("jrq", "currentapiVersion====>$currentapiVersion")
if (currentapiVersion < 24) {
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(File(filePath!!)))
startActivityForResult(intent, OPEN_RESULT2)
} else {
val contentValues = ContentValues(1)
contentValues.put(MediaStore.Images.Media.DATA, filePath)
val uri = contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri)
startActivityForResult(intent, OPEN_RESULT2)
}
}
fun getPhotoPath(): String {
return Environment.getExternalStorageDirectory().toString() + "/DCIM/"
}
fun goToAppSetting() {
val intent = Intent()
intent.action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
val uri = Uri.fromParts("package", packageName, null)
intent.data = uri
startActivityForResult(intent, 123)
}
fun selectPicture() {
val intent = Intent()
intent.action = Intent.ACTION_PICK
intent.type = "image/*"//从所有图片中进行选择
startActivityForResult(intent, REQUESTCODE_PICK)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == RESULT_COD) {
// if (data != null) {
// setPicParam(data)
// }
setPicParam()
}
if (requestCode == OPEN_RESULT2) {
if (resultCode == Activity.RESULT_OK) {
var uri: Uri? = null
if (Build.VERSION.SDK_INT >= 24) {
uri = FileProvider.getUriForFile(this, packageName + ".FileProvider", File(filePath))
} else {
uri = Uri.fromFile(File(filePath))
}
startPhotoZoom(uri)
}
}
if (resultCode == Activity.RESULT_OK)
when (requestCode) {
REQUESTCODE_PICK
-> startPhotoZoom(data!!.data)
}
}
var uritempFile :Uri?=null
private fun startPhotoZoom(uri: Uri) {
val intent = Intent("com.android.camera.action.CROP")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
}
intent.setDataAndType(uri, "image/*")
intent.putExtra("corp", "true")
//裁剪器高宽比
intent.putExtra("aspectY", 1)
intent.putExtra("aspectX", 1)
//设置裁剪框高宽
intent.putExtra("outputX", 300)
intent.putExtra("outputY", 300)
//返回数据
// intent.putExtra("return-data", true)
uritempFile = Uri.parse("file://" + "/" + Environment.getExternalStorageDirectory().getPath() + "/" + "small.jpg");
intent.putExtra(MediaStore.EXTRA_OUTPUT, uritempFile);
intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
startActivityForResult(intent, RESULT_COD)
}
private fun setPicParam(data: Intent) {
val bundle = data.extras
if (bundle != null) {
mBitmap = bundle.getParcelable<Bitmap>("data")
Log.e("jrq","---mBitmap-------"+mBitmap)
val file = compressImage(mBitmap!!)
if (file.exists()) {
getHeadNet(file)
}
}
}
private fun setPicParam() {
mBitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uritempFile));
Log.e("jrq","---mBitmap-------"+mBitmap)
val file = compressImage(mBitmap!!)
if (file.exists()) {
getHeadNet(file)
}
}
fun compressImage(bitmap: Bitmap): File {
val baos = ByteArrayOutputStream()
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos)//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
var options = 100
while (baos.toByteArray().size / 1024 > 500) { //循环判断如果压缩后图片是否大于500kb,大于继续压缩
baos.reset()//重置baos即清空baos
options -= 10//每次都减少10
bitmap.compress(Bitmap.CompressFormat.JPEG, options, baos)//这里压缩options%,把压缩后的数据存放到baos中
val length = baos.toByteArray().size.toLong()
}
val format = SimpleDateFormat("yyyyMMddHHmmss")
val date = Date(System.currentTimeMillis())
val filename = format.format(date)
val file = File(Environment.getExternalStorageDirectory(), "$filename.png")
try {
val fos = FileOutputStream(file)
try {
fos.write(baos.toByteArray())
fos.flush()
fos.close()
} catch (e: IOException) {
e.printStackTrace()
}
} catch (e: FileNotFoundException) {
Log.e("jrq", e.message)
e.printStackTrace()
}
recycleBitmap(bitmap)
return file
}
fun recycleBitmap(vararg bitmaps: Bitmap) {
if (bitmaps == null) {
return
}
for (bm in bitmaps) {
if (null != bm && !bm.isRecycled) {
bm.recycle()
}
}
}
abstract fun showDialog()
abstract fun getHeadNet(file: File)
}
底部弹框 PopupWindow
public class SelectPicPopupwindow extends PopupWindow {
private TextView btn_take_photo, btn_pick_photo, btn_cancel;
private View mMenuView;
public SelectPicPopupwindow(Context context, OnClickListener itemsOnClick, int option) {
super(context);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mMenuView = inflater.inflate(R.layout.photo_window_view, null);
btn_take_photo = (TextView) mMenuView.findViewById(R.id.btn_take_photo);
btn_pick_photo = (TextView) mMenuView.findViewById(R.id.btn_pick_photo);
btn_cancel = (TextView) mMenuView.findViewById(R.id.btn_cancel);
btn_cancel.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
dismiss();
}
});
btn_pick_photo.setOnClickListener(itemsOnClick);
btn_take_photo.setOnClickListener(itemsOnClick);
this.setContentView(mMenuView);
this.setWidth(LayoutParams.MATCH_PARENT);
this.setHeight(LayoutParams.WRAP_CONTENT);
this.setFocusable(true);
this.setAnimationStyle(R.style.popupAnimation);
ColorDrawable dw = new ColorDrawable(0xaa000000);
this.setBackgroundDrawable(dw);
}
}
动画样式 styles
<!--淡入淡出popupwindow -->
<style name="popupAnimation" parent="android:Animation">
<item name="android:windowEnterAnimation">@anim/alpha_in</item>
<item name="android:windowExitAnimation">@anim/alpha_out</item>
</style>
alpha_in
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha
android:fromAlpha="0.0"
android:toAlpha="0.5"
android:duration="0"
/>
<translate
android:duration="0"
android:fromYDelta="100%p"
android:toYDelta="0" />
</set>
<!--
fromAlpha:开始时透明度
toAlpha:结束时透明度
duration:动画持续时间
淡入
-->
alpha_out
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="0"
android:fromYDelta="0"
android:toYDelta="50%p" />
<alpha
android:duration="0"
android:fromAlpha="0.5"
android:toAlpha="0.0" />
</set>
<!--
fromAlpha:开始时透明度
toAlpha:结束时透明度
duration:动画持续时间
淡出
-->
裁剪方法
private fun startPhotoZoom(uri: Uri) {
val intent = Intent("com.android.camera.action.CROP")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
}
intent.putExtra("corp", "true")
intent.putExtra("aspectY", 1)
intent.putExtra("aspectX", 1)
intent.putExtra("outputX", 300)
intent.putExtra("outputY", 300)
intent.putExtra("return-data", true)
uritempFile = Uri.parse("file://" + "/" + Environment.getExternalStorageDirectory().getPath() + "/" + "small.jpg");
intent.putExtra(MediaStore.EXTRA_OUTPUT, uritempFile);
intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
startActivityForResult(intent, RESULT_COD)
}