美文网首页
Android实现图片拍照、选择、剪裁效果

Android实现图片拍照、选择、剪裁效果

作者: 木小伍 | 来源:发表于2017-11-24 17:03 被阅读0次

    特别感谢博客

    直接上图片
    图1 图2 图3 图4
    使用到的第三方依赖,也是裁剪的重要依赖

    github地址:点我跳转

        // 图像剪切
        compile('com.kevin:crop:1.0.2') {
            // 如果已经引入 support:appcompat-v7 可以加上这句话
            exclude group: 'com.android.support', module: 'appcompat-v7'
        }
    
    具体实现

    1.图1选项的布局代码(采用的popupWindow实现)

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        android:orientation="vertical">
    
        <LinearLayout
            android:id="@+id/pop_layout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:background="#9999"
            android:gravity="center_horizontal"
            android:orientation="vertical">
    
            <Button
                android:id="@+id/picture_selector_take_photo_btn"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginLeft="10dip"
                android:layout_marginRight="10dip"
                android:layout_marginTop="10dp"
                android:background="@drawable/shape_corner5_white"
                android:padding="10dp"
                android:text="拍照"
                android:textColor="@color/font_black"
                android:textSize="14sp"
                android:textStyle="bold" />
    
            <Button
                android:id="@+id/picture_selector_pick_picture_btn"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginLeft="10dip"
                android:layout_marginRight="10dip"
                android:layout_marginTop="5dp"
                android:background="@drawable/shape_corner5_white"
                android:padding="10dp"
                android:text="从相册选择"
                android:textColor="@color/font_black"
                android:textSize="14sp"
                android:textStyle="bold" />
    
            <Button
                android:id="@+id/picture_selector_cancel_btn"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginBottom="15dip"
                android:layout_marginLeft="10dip"
                android:layout_marginRight="10dip"
                android:layout_marginTop="20dp"
                android:background="@drawable/shape_corner5_white"
                android:padding="10dp"
                android:text="取消"
                android:textColor="#373447"
                android:textSize="14sp"
                android:textStyle="bold" />
        </LinearLayout>
    
    </RelativeLayout>
    

    2.popupWindow的添加主要代码

        var popupWindow: PopupWindow? = null
        /**
         * 把一个View控件添加到PopupWindow上并且显示
    
         * @param activity
         */
        fun showPopupWindow(activity: Activity) {
            popupWindow = PopupWindow(mMenuView, // 添加到popupWindow
                    ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
            popupWindow!!.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
            popupWindow!!.showAtLocation(activity.window.decorView, Gravity.CENTER or Gravity.BOTTOM, 0, 0)
            popupWindow!!.setAnimationStyle(android.R.style.Animation_InputMethod)   // 设置窗口显示的动画效果
            popupWindow!!.setFocusable(false)                                        // 点击其他地方隐藏键盘 popupWindow
            popupWindow!!.update()
        }
    

    3.拍照实现主要代码,采取系统自带

       /**
         * 拍照
         */
        @RequiresApi(Build.VERSION_CODES.M)
        fun takePhoto() {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN // Permission was added in API Level 16
                    && ActivityCompat.checkSelfPermission(mActivity, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                requestPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE,
                        "拍照时需要存储权限",
                        REQUEST_STORAGE_WRITE_ACCESS_PERMISSION)
            } else {
                popupWindow!!.dismiss()
                val takeIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
                //下面这句指定调用相机拍照后的照片存储的路径
                takeIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(File(mTempPhotoPath)))
                startActivityForResult(takeIntent, CAMERA_REQUEST_CODE)
            }
        }
    

    4.图片选择采用系统自带

      /**
        * 从系统相册选择
        */
      @RequiresApi(Build.VERSION_CODES.M)
        private fun pickFromGallery() {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN // Permission was added in API Level 16
                    && ActivityCompat.checkSelfPermission(mActivity, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                requestPermission(Manifest.permission.READ_EXTERNAL_STORAGE,
                        "选择图片时需要读取权限",
                        REQUEST_STORAGE_READ_ACCESS_PERMISSION)
            } else {
                popupWindow!!.dismiss()
                val pickIntent = Intent(Intent.ACTION_PICK, null)
                // 如果限制上传到服务器的图片类型时可以直接写如:"image/jpeg 、 image/png等的类型"
                pickIntent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*")
                startActivityForResult(pickIntent, GALLERY_REQUEST_CODE)
            }
        }
    

    5.权限申请
    必须注意的是--需要在配置清单文件中添加权限声明

     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    
     /**
         * 请求权限
    
         * 如果权限被拒绝过,则提示用户需要权限
         */
        @RequiresApi(Build.VERSION_CODES.M)//编译的api版本过低,所造成的
        protected fun requestPermission(permission: String, rationale: String, requestCode: Int) {
            if (shouldShowRequestPermissionRationale(permission)) {
    
                TooltipUtils.showDialog(mActivity, "权限需求", rationale, DialogInterface.OnClickListener
                { dialog, which -> requestPermissions(arrayOf(permission), requestCode) }, null, "确定", "取消")
            } else {
                requestPermissions(arrayOf(permission), requestCode)
            }
        }
    

    6.图片选择完成之后,跳转裁剪界面(图4)
    a.布局代码简单粗暴

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
    
        <com.vcredit.cp.view.TitleBar
            android:id="@+id/title_bar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:titleMiddle="编辑" />
    
        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_below="@+id/toolbar"
            android:background="#000">
    
            <com.kevin.crop.view.UCropView
                android:id="@+id/weixin_act_ucrop"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:visibility="invisible" />
    
        </FrameLayout>
    </LinearLayout>
    

    b.初始化操作

       mGestureCropImageView = mUCropView.getCropImageView();
            mOverlayView = mUCropView.getOverlayView();
    
            mGestureCropImageView.setTransformImageListener(mImageListener);
    
            initCropView();
    

    如果需要对裁剪框进行自定义操作,可在initCropView方法中进行操作

     /**
         * 初始化裁剪View
         */
        private void initCropView() {
            // 设置允许缩放
            mGestureCropImageView.setScaleEnabled(true);
            // 设置禁止旋转
            mGestureCropImageView.setRotateEnabled(false);
    
            // 设置外部阴影颜色
            mOverlayView.setDimmedColor(Color.parseColor("#AA000000"));
            // 设置周围阴影是否为椭圆(如果false则为矩形)
            mOverlayView.setOvalDimmedLayer(false);
            // 设置显示裁剪边框
            mOverlayView.setShowCropFrame(true);
            // 设置不显示裁剪网格
            mOverlayView.setShowCropGrid(false);
    
            final Intent intent = getIntent();
            setImageData(intent);
        }
        private void setImageData(Intent intent) {
            Uri inputUri = intent.getParcelableExtra(UCrop.EXTRA_INPUT_URI);
            mOutputUri = intent.getParcelableExtra(UCrop.EXTRA_OUTPUT_URI);
    
            if (inputUri != null && mOutputUri != null) {
                try {
                    mGestureCropImageView.setImageUri(inputUri);
                } catch (Exception e) {
                    setResultException(e);
                    finish();
                }
            } else {
                setResultException(new NullPointerException("Both input and output Uri must be specified"));
                finish();
            }
    
            // 设置裁剪宽高比
            if (intent.getBooleanExtra(UCrop.EXTRA_ASPECT_RATIO_SET, false)) {
                float aspectRatioX = intent.getFloatExtra(UCrop.EXTRA_ASPECT_RATIO_X, 0);
                float aspectRatioY = intent.getFloatExtra(UCrop.EXTRA_ASPECT_RATIO_Y, 0);
    
                if (aspectRatioX > 0 && aspectRatioY > 0) {
                    mGestureCropImageView.setTargetAspectRatio(aspectRatioX / aspectRatioY);
                } else {
                    mGestureCropImageView.setTargetAspectRatio(CropImageView.SOURCE_IMAGE_ASPECT_RATIO);
                }
            }
    
            // 设置裁剪的最大宽高
            if (intent.getBooleanExtra(UCrop.EXTRA_MAX_SIZE_SET, false)) {
                int maxSizeX = intent.getIntExtra(UCrop.EXTRA_MAX_SIZE_X, 0);
                int maxSizeY = intent.getIntExtra(UCrop.EXTRA_MAX_SIZE_Y, 0);
    
                if (maxSizeX > 0 && maxSizeY > 0) {
                    mGestureCropImageView.setMaxResultImageSizeX(maxSizeX);
                    mGestureCropImageView.setMaxResultImageSizeY(maxSizeY);
                } else {
                    Log.w(TAG, "EXTRA_MAX_SIZE_X and EXTRA_MAX_SIZE_Y must be greater than 0");
                }
            }
        }
    

    不作详细介绍,上面有github地址,如有兴趣可直接撸源码。
    7.在onActivityResult方法中对裁剪后的图片进行其他操作(比如上传)

      override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
            if (resultCode == Activity.RESULT_OK) {
                when (requestCode) {
                    CAMERA_REQUEST_CODE   // 调用相机拍照
                    -> {
                        val temp = File(mTempPhotoPath)
                        TooltipUtils.showToastL(mActivity, mTempPhotoPath)
                        startCropActivity(Uri.fromFile(temp))
                    }
                    GALLERY_REQUEST_CODE  // 直接从相册获取
                    -> {
                        startCropActivity(data!!.data)
                    }
                    REQUEST_CROP -> {   // 裁剪图片结果
                        handleCropResult(data!!)
                    }
                    RESULT_ERROR    // 裁剪图片错误
                    -> {
                        handleCropError(data!!)
                    }
                }
            }
            super.onActivityResult(requestCode, resultCode, data)
        }
    
     /**
         * 处理剪切失败的返回值
    
         * @param result
         */
        private fun handleCropError(result: Intent) {
            deleteTempPhotoFile()
            val cropError = UCrop.getError(result)
            if (cropError != null) {
                Toast.makeText(mActivity, cropError.message, Toast.LENGTH_LONG).show()
            } else {
                Toast.makeText(mActivity, "无法剪切选择图片", Toast.LENGTH_SHORT).show()
            }
        }
    
    
        /**
         * 处理剪切成功的返回值
    
         * @param result
         */
        private fun handleCropResult(result: Intent) {
            deleteTempPhotoFile()
            val resultUri = UCrop.getOutput(result)
            if (null != resultUri) {
                var bitmap: Bitmap? = null
                try {
                    bitmap = MediaStore.Images.Media.getBitmap(mActivity.contentResolver, resultUri)
                } catch (e: FileNotFoundException) {
                    e.printStackTrace()
                } catch (e: IOException) {
                    e.printStackTrace()
                }
                onPictureSelected(resultUri, bitmap!!)  //该方法主要执行的是图片的上传请求。
            } else {
                Toast.makeText(mActivity, "无法剪切选择图片", Toast.LENGTH_SHORT).show()
            }
        }
    

    以上就是具体实现参见demo(纯java语言实现,没有掺杂kotlin),单独的demo地址

    相关文章

      网友评论

          本文标题:Android实现图片拍照、选择、剪裁效果

          本文链接:https://www.haomeiwen.com/subject/bcyxbxtx.html