-
拍照裁剪问题
(1)首先是imgpath,uri,File这几种格式的转换。
(2)调用系统相机拍照的startActivity问题。
由于之前我们都是在activity中开始startActivity,所以在当前activity
里进行onstartActivity是没有问题的,但是在frgment里调用,就存在不同(拿不到返回数据)。
activity,frgmentActivity,fgment都可以进行startActivity,和onactivity的接收,只是,fragmentActivity [getactivity().startActivity(intent)] 的数据只能在父activity里接收到,fgrment
l里的onactivityresult是接受不到的------所以,我的方法是在frgment里进行startactivity(不加getactivity),在frgment里进行onactivityresult(也不用加getactivity),就行。
(3)图片的裁剪和临时裁剪图片的删除
–图片裁剪
建议每次拍照和选择图片的时候,都创建一个imgpath(临时地址),通过这个imgpath,转换得到imguri,每次选择或者拍照都输出到imguri.裁剪也是在该uri上进行的。遇到的问题是,当时声明一个cropuri(该uri没有进行与imgpath或者file的绑定),导致一直出错。选择图片时,直接对data.getdata操作(没有更改源文件权限),导致报错,需要把data.getdata读到bitmap,在把bitmap写到我们的imgpath对应的file里。创建一个imgpath
imgPath= Environment.getExternalStorageDirectory()
.getAbsolutePath() + File.separator.toString() + System.currentTimeMillis()
.toString() + ".jpg"
if (dialog != null) {
imgFile = File(imgPath)
if (!imgFile.getParentFile().exists()) {
imgFile.getParentFile().mkdirs()
}
imgUri = if (Build.VERSION.SDK_INT < 24) {
// 从文件中创建uri
Uri.fromFile(imgFile)
} else {
//兼容android7.0 使用共享文件的形式
val contentValues = ContentValues(1)
contentValues.put(MediaStore.Images.Media.DATA, imgFile.getAbsolutePath())
activity!!.contentResolver.insert(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
contentValues
)
选择图片时,bitmap操作(在onActivityresult里),得到uri
if(data!=null) {
val file = File(imgPath)
val fos = file.outputStream()
var bitmap: Bitmap? = null
bitmap = BitmapFactory.decodeStream(
data.getData()?.let {
requireActivity().application.contentResolver.openInputStream(
it
)
}
)
if (bitmap == null) {
return
}
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos)
imgFile = File(imgPath)
if (!imgFile.parentFile.exists()) {
imgFile.parentFile.mkdirs()
}
imgUri = if (Build.VERSION.SDK_INT < 24) {
// 从文件中创建uri
Uri.fromFile(imgFile)
} else {
//兼容android7.0 使用共享文件的形式
val contentValues = ContentValues(1)
contentValues.put(MediaStore.Images.Media.DATA, imgFile.absolutePath)
requireActivity().application.contentResolver.insert(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
contentValues
)
}
--图片删除
只是简单的file.delete是不行的,会留下一个空的图片,得在数据库里也删除。
override fun onDestroyView() {
val file = File(viewModel.selfImagePathString.value)
if (file.isFile() && file.exists())
file.delete()
//filepath-->图片绝对路径
requireActivity().contentResolver.delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, MediaStore.Images.Media.DATA + "=?", arrayOf(viewModel.selfImagePathString.value))
super.onDestroyView()
}
2,图片的base64编码,有java的编码和安卓的编码,我们选择安卓的编码
//得到的直接可用编码,无需进行split等操作
val str = Base64.encodeToString(imgFile.readBytes(),Base64.NO_WRAP)
3,ui方面,能用ConstraintLayout,就用ConstraintLayout。以为方便,可以替换其他linerlayout等布局,在控制view大小方面,也时最方便的,不用通过weight这个分配空间。
而且,在view的重叠覆盖效果的实现,也是最方便的。
4,创建dialog
fun showDialog(): Dialog? {
if(requireContext()==null){
Log.d("daxiong", "showDialog: ")
}
val dialog = requireContext()?.let { Dialog(it, R.style.DialogTheme) }
//填充对话框的布局
val inflate: View = LayoutInflater.from(requireContext()).inflate(R.layout.portal_layout_pop_add_photo, null)
//初始化控件
val camera = inflate.findViewById(R.id.camera) as TextView
val pic = inflate.findViewById(R.id.pic) as TextView
val cancel = inflate.findViewById(R.id.cancel) as TextView
camera.setOnClickListener(object : View.OnClickListener {
override fun onClick(view: View?) {
//逻辑
dialog.dismiss()
}
}
})
pic.setOnClickListener(object : View.OnClickListener {
override fun onClick(view: View?) {
if (dialog != null) {
//逻辑
dialog.dismiss()
}
}
})
cancel.setOnClickListener(object : View.OnClickListener {
override fun onClick(view: View?) {
if (dialog != null) {
dialog.dismiss()
}
}
})
//将布局设置给Dialog
dialog?.setContentView(inflate)
val dialogWindow: Window
//获取当前Activity所在的窗体
if (dialog != null) {
if(dialog.window == null){
return null
}
}
dialogWindow = dialog?.window!!
//设置Dialog从窗体底部弹出
dialogWindow.setGravity(Gravity.BOTTOM)
val win: Window = dialog.getWindow()!!
win.getDecorView().setPadding(0, 0, 0, 0)
val lp: WindowManager.LayoutParams = win.getAttributes()
lp.width = WindowManager.LayoutParams.FILL_PARENT
lp.height = WindowManager.LayoutParams.WRAP_CONTENT
win.setAttributes(lp)
/*
控制dialog的大小,使用point,来控制弹窗的屏幕占比
val size:Point = Point()
requireActivity().windowManager.defaultDisplay.getRealSize(size)
val lp: WindowManager.LayoutParams = win.getAttributes()
lp.width = WindowManager.LayoutParams.FILL_PARENT
lp.height=(size.y*0.7).toInt()
win.setAttributes(lp)
*/
return dialog//显示对话框
}
下拉框控件使用详解
permisionx的使用
* 摄像头/存储/录音权限
*/
private val PERMISSIONS_REQUIRED = arrayOf(
Manifest.permission.CAMERA,
Manifest.permission.RECORD_AUDIO,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE
)
//检查权限
PermissionX.init(this).permissions(PERMISSIONS_REQUIRED.toList())
.onExplainRequestReason { scope, deniedList ->
val dialog = PermissionDialog(
requireContext(),
getString(),
getString(),
deniedList
)
scope.showRequestReasonDialog(dialog)
}
.onForwardToSettings { scope, deniedList ->
val dialog = PermissionDialog(
requireContext(),
getString(R.string.isecurephone_portal_permission_tips_msg),
getString(R.string.isecurephone_portal_set_button),
deniedList
)
scope.showForwardToSettingsDialog(dialog)
}.request { allGranted, _, _ ->
if (allGranted) {
} else {
findNavController().popBackStack()
}
}
//网络请求