前段时间写了如何获取相册和拍照之后的照片并且进行显示和上传,这一次是如何进行圆形图像制作,经常看我写的笔记的人会知道,我很懒。那么我就懒的自定义了,目前需求就用原生的就好了,大神的轮子,我会在后面进行推荐。这篇笔记是依赖于:[Android调用相册、相机(兼容6.0、7.0、8.0)
](https://www.jianshu.com/p/41b093d213fb) 文章撰写的,所以不会基本操作的,请先去看看那个。

先上效果哈:

一、布局设置

由于是圆形头像,所以,我们引用一个举世闻名的项目哈:CircleImageView

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><Buttonandroid:id="@+id/btn_get_pic_form_photo_album"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentStart="true"android:layout_margin="10dp"android:text="调用相册" /><Buttonandroid:id="@+id/btn_get_Permission"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerHorizontal="true"android:layout_margin="10dp"android:text="动态权限申请" /><Buttonandroid:id="@+id/btn_get_pic_from_camera"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentEnd="true"android:layout_margin="10dp"android:text="调用相机" /><de.hdodenhof.circleimageview.CircleImageViewandroid:id="@+id/iv_test"android:layout_width="96dp"android:layout_height="96dp"android:layout_centerInParent="true"android:src="@drawable/ic_launcher_background"app:civ_border_color="#999999"app:civ_border_width="2dp" />
</RelativeLayout>

布局没有太大变化,就是把之前的ImageView修改为CircleImageView控件

二、.java 文件

这里增加了两个方法

方法一
  private void photoClip(Uri uri) {// 调用系统中自带的图片剪裁Intent intent = new Intent("com.android.camera.action.CROP");intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);intent.setDataAndType(uri, "image/*");// 下面这个crop=true是设置在开启的Intent中设置显示的VIEW可裁剪intent.putExtra("crop", "true");// aspectX aspectY 是宽高的比例intent.putExtra("aspectX", 1);intent.putExtra("aspectY", 1);// outputX outputY 是裁剪图片宽高intent.putExtra("outputX", 150);intent.putExtra("outputY", 150);intent.putExtra("return-data", true);startActivityForResult(intent, 3);}

该方法,传入我们拿到的照片的 uri 进行激活 Android 系统的裁剪界面。我是在 onActivityResult 内进行调用该方法。

方法二
  public String saveImage(String name, Bitmap bmp) {File appDir = new File(Environment.getExternalStorageDirectory().getPath());if (!appDir.exists()) {appDir.mkdir();}String fileName = name + ".jpg";File file = new File(appDir, fileName);try {FileOutputStream fos = new FileOutputStream(file);bmp.compress(Bitmap.CompressFormat.PNG, 100, fos);fos.flush();fos.close();return file.getAbsolutePath();} catch (IOException e) {e.printStackTrace();}return null;}

该方法 传入获取照片的 bitmap 和裁剪之后的照片名称,生成文件的保存路径,韩小呆将其保存在了本地的根目录了。

完整代码

package com.example.hxd.pictest;import android.Manifest;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.SystemClock;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.v4.content.FileProvider;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;import com.bumptech.glide.Glide;import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.Objects;
import java.util.logging.Logger;import de.hdodenhof.circleimageview.CircleImageView;
import pub.devrel.easypermissions.EasyPermissions;public class MainActivity extends AppCompatActivity implements View.OnClickListener, EasyPermissions.PermissionCallbacks {private CircleImageView ivTest;private File cameraSavePath;//拍照照片路径private Uri uri;private String[] permissions = {Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE};private String photoName = System.currentTimeMillis() + ".jpg";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button btnGetPicFromCamera = findViewById(R.id.btn_get_pic_from_camera);Button btnGetPicFromPhotoAlbum = findViewById(R.id.btn_get_pic_form_photo_album);Button btnGetPermission = findViewById(R.id.btn_get_Permission);ivTest = findViewById(R.id.iv_test);btnGetPicFromCamera.setOnClickListener(this);btnGetPicFromPhotoAlbum.setOnClickListener(this);btnGetPermission.setOnClickListener(this);cameraSavePath = new File(Environment.getExternalStorageDirectory().getPath() + "/" + photoName);}@Overridepublic void onClick(View v) {int id = v.getId();switch (id) {case R.id.btn_get_pic_from_camera:goCamera();break;case R.id.btn_get_pic_form_photo_album:goPhotoAlbum();break;case R.id.btn_get_Permission:getPermission();break;}}//获取权限private void getPermission() {if (EasyPermissions.hasPermissions(this, permissions)) {//已经打开权限Toast.makeText(this, "已经申请相关权限", Toast.LENGTH_SHORT).show();} else {//没有打开相关权限、申请权限EasyPermissions.requestPermissions(this, "需要获取您的相册、照相使用权限", 1, permissions);}}private void photoClip(Uri uri) {// 调用系统中自带的图片剪裁Intent intent = new Intent("com.android.camera.action.CROP");intent.setDataAndType(uri, "image/*");// 下面这个crop=true是设置在开启的Intent中设置显示的VIEW可裁剪intent.putExtra("crop", "true");// aspectX aspectY 是宽高的比例intent.putExtra("aspectX", 1);intent.putExtra("aspectY", 1);// outputX outputY 是裁剪图片宽高intent.putExtra("outputX", 150);intent.putExtra("outputY", 150);intent.putExtra("return-data", true);startActivityForResult(intent, 3);}//激活相册操作private void goPhotoAlbum() {Intent intent = new Intent();intent.setAction(Intent.ACTION_PICK);intent.setType("image/*");startActivityForResult(intent, 2);}//激活相机操作private void goCamera() {Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {uri = FileProvider.getUriForFile(MainActivity.this, "com.example.hxd.pictest.fileprovider", cameraSavePath);intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);} else {uri = Uri.fromFile(cameraSavePath);}intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);MainActivity.this.startActivityForResult(intent, 1);}@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);//框架要求必须这么写EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);}//成功打开权限@Overridepublic void onPermissionsGranted(int requestCode, @NonNull List<String> perms) {Toast.makeText(this, "相关权限获取成功", Toast.LENGTH_SHORT).show();}//用户未同意权限@Overridepublic void onPermissionsDenied(int requestCode, @NonNull List<String> perms) {Toast.makeText(this, "请同意相关权限,否则功能无法使用", Toast.LENGTH_SHORT).show();}@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {String photoPath;if (requestCode == 1 && resultCode == RESULT_OK) {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {photoPath = String.valueOf(cameraSavePath);photoClip(Uri.fromFile(cameraSavePath));} else {photoPath = uri.getEncodedPath();photoClip(uri);}Log.d("拍照返回图片路径:", photoPath);Glide.with(MainActivity.this).load(photoPath).into(ivTest);} else if (requestCode == 2 && resultCode == RESULT_OK) {photoPath = getPhotoFromPhotoAlbum.getRealPathFromUri(this, data.getData());Log.d("相册返回图片路径:", photoPath);photoClip(data.getData());Glide.with(MainActivity.this).load(photoPath).into(ivTest);} else if (requestCode == 3 && resultCode == RESULT_OK) {Bundle bundle = data.getExtras();if (bundle != null) {//在这里获得了剪裁后的Bitmap对象,可以用于上传Bitmap image = bundle.getParcelable("data");//设置到ImageView上ivTest.setImageBitmap(image);//也可以进行一些保存、压缩等操作后上传String path = saveImage("头像", image);Log.d("裁剪路径:", path);}}super.onActivityResult(requestCode, resultCode, data);}public String saveImage(String name, Bitmap bmp) {File appDir = new File(Environment.getExternalStorageDirectory().getPath());if (!appDir.exists()) {appDir.mkdir();}String fileName = name + ".jpg";File file = new File(appDir, fileName);try {FileOutputStream fos = new FileOutputStream(file);bmp.compress(Bitmap.CompressFormat.PNG, 100, fos);fos.flush();fos.close();return file.getAbsolutePath();} catch (IOException e) {e.printStackTrace();}return null;}
}

当代码写成了这样,我以为就可以完事了,但是后来拿出来我的小米4和小米8se 测试的时候,我就懵逼了,出现了如下结果:

描述一下:
1、相册选择照片之后,只要进行裁剪就会出现“保存时发生错误,保存失败”;
2、就是拍照之后进行裁剪无效果。

三、解决bug

1、将 photoClip() 方法内添加如下代码,其他代码不进行变动

uritempFile = Uri.parse("file://" + "/" + Environment.getExternalStorageDirectory().getPath() + "/" + System.currentTimeMillis() + ".jpg");intent.putExtra(MediaStore.EXTRA_OUTPUT, uritempFile);intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());intent.putExtra("noFaceDetection", true); 

这里的 uritempFile 是个 Uri 。

2、将裁剪的返回成功的返回方法内添加如下代码:

  Picasso.with(EditMyInfoActivity.this).load(uritempFile).into(ivHead);File file = null;try {file = new File(new URI(uritempFile.toString()));} catch (URISyntaxException e) {e.printStackTrace();}//照片路径String path = Objects.requireNonNull(file).getPath();

然后,就可以完美的运行了。

三、推荐一篇自定义裁剪的博文

Android 高仿微信头像截取 打造不一样的自定义控件----作者: 家喻户晓的 张鸿洋

四、推荐几款裁剪框架

1、uCrop---薄荷,哔哩哔哩 在使用

2、android-crop---网易新闻,芒果TV 在使用

3、PhotoCrop---快手 使用

4、CropBitmap--->出自一位牛x的群友

Android 系统自带图片裁剪功能(适配7.0、8.0、对了还有小米手机)相关推荐

  1. android裁剪图片功能,Android通过ClipDrawable实现图片裁剪功能

    前言 最近需要实现一个显示下载进度的功能,下载进度的实现很简单,用ProgressBar就可以,但我想尝试通过图片裁剪来实现,学习一下ClipDrawable这个类的使用. ClipDrawable简 ...

  2. 手机调用系统的拍照和裁剪功能,假设界面有输入框EditText,在一些手机会出现点击EditText会弹出输入法,却不能输入的情况。...

    1. 拍照裁剪后 点击EditText会弹出输入法,却不能输入.可是点击点一EdtiText就能够输入了,所以我就写了一个看不见的EdtiText,切换焦点,这样就攻克了这个奇怪的这问题,应该是and ...

  3. Android 图片裁剪功能实现详解(类似QQ自定义头像裁剪)

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://mzh3344258.blog.51cto.com/1823534/808837 ...

  4. Android系统源码目录及功能介绍

    Android的移植按如下流程:     1.android linux 内核的普通驱动移植,让内核可以在目标平台上运行起来.     2.正确挂载文件系统,确保内核启动参数和 android 源代码 ...

  5. 仿快图系统自带图片浏览器应用源码项目

    仿快图系统自带图片浏览器应用源码,最近在做一个微博i动态模块,需要查看他人相册照片或者微博内容图片等.看到QQ空间那个效果不错,尝试了不少方法来实现,均不是怎么理想.最初是想通过自定义GroupVie ...

  6. 利用 Android 系统原生 API 实现分享功能

    对于 App 的分享功能,基本上是一个刚需,本文主要介绍运用系统原生分享功能时候需要注意的一些问题.对于某些特定平台的一些高级分享特性,比如微信或者微博之类的分享来源标注,需要在其开放平台注册应用再接 ...

  7. 微信小程序图片裁剪功能的实现

    文章目录 图片上传与处理 图片尺寸适配 图片显示与裁剪框 裁剪框的拖动与缩放 增加canvas并裁剪图片 保存图片到相册 总结 在之前的博文中,已经介绍了如何使用在前端开发中,实现较方便自由的图片裁剪 ...

  8. 可以删除的android系统自带程序—详细列表【转】

    android系统自带的很多程序平时根本用不到或很少用到,但是它们有的却在你开机之后默默地在后台运行着,既占内存又消耗电量,这时我们就需要把他们一一杀掉!但是很多人不明白这些软件都是些什么,哪些能删哪 ...

  9. Android系统将内置滤镜功能

    from: http://cblog.cc/2015/09/03/Android-Camera-%E5%AE%9E%E6%97%B6%E6%BB%A4%E9%95%9C/ 一.Android系统将内置 ...

最新文章

  1. MLIR中间表示与编译
  2. SWAGAN:基于样式的小波驱动生成模型
  3. 北京大学崔斌教授组招收图机器学习、AutoML等方向科研实习生
  4. SAP PM入门系列21 - IE07 Equipment List (Multilevel)
  5. 小猿圈Python之实现京东秒杀功能代码
  6. Bundle数据传输
  7. NLP(新闻文本分类)——数据读取与数据分析
  8. android layout wrap_content,android-如果高度为WRAP_CONTENT,则不显示VideoVi...
  9. 电脑打字学习_新手如何学会电脑打字 走上盲打之路
  10. 《数学之美》—隐含马尔可夫模型
  11. mybatis编写一个查询数据库表的程序
  12. 小团队Git协作流程
  13. 计算机字体安装按钮灰色,win10系统无法安装字体安装按钮灰色的的解决方法
  14. ASO优化:ios关键词覆盖和增量技巧
  15. [系统] Deepin系统常见问题解决(持续更新)
  16. 什么是App分发?有哪些分发平台可以选择?
  17. 在arm架构的mac上安装sql server(m1芯片 or m2芯片)
  18. php采集今日头条出现问题,PHP采集今日头条内容页时,解析页面上的JS转为json
  19. FineReport之localhost拒绝了我们的连接请求
  20. python文件读取写入中文乱码问题

热门文章

  1. 汉字拼音的一个解决方法(初具使用价值)
  2. 【对讲机的那点事】对讲机电池、充电器使用说明须知
  3. 点积、内积、外积、叉积、张量积——概念区分
  4. VS2017操做sql server数据库
  5. iPhone 14/Pro卫星紧急求救上线;非法采集用户位置,谷歌赔偿3.9亿美元;Node.js 19.1.0发布|极客头条
  6. 方舟linux服务器更新,方舟怎么更新服务器版本 | 手游网游页游攻略大全
  7. 多人在线编辑文档 开发_腾讯文档,支持多人实时在线协同编辑
  8. 双鱼林java_双鱼林Java代码生成器
  9. 基于二哈实现多人人脸学习和识别
  10. 怎么修改我的世界服务器封面,《我的世界:初识服务器》