学习安卓-第三周-拍照裁剪与perssionx的使用

  1. 拍照裁剪问题
    (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()
                }
            }
        //网络请求
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值