热门标签 | HotTags
当前位置:  开发笔记 > Android > 正文

Android拍照或从图库选择图片并裁剪

这篇文章主要介绍了Android拍照或从图库选择图片并裁剪的相关资料,具有一定的参考价值,需要的朋友可以参考下

今天看《第一行代码》上面关于拍照和从相册选取图片那一部分,发现始终出不来效果,所以搜索其他资料学习一下相关知识,写一个简单的Demo。 

一、 拍照选择图片

1、使用隐式Intent启动相机

//构建隐式Intent
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
//调用系统相机
startActivityForResult(intent, 1);

2、处理相机拍照返回的结果

//用户点击了取消
if(data == null){
  return;
}else{
  Bundle extras = data.getExtras();
  if (extras != null){
    //获得拍的照片
    Bitmap bm = extras.getParcelable("data");
  }
}

二、 从图库选择图片

1、构建内容选择隐式Intent

Intent intent = new Intent(Intent.ACTION_GET_CONTENT);

2、设置内容类型为图片

intent.setType("image/*");

3、启动图片选择

startActivityForResult(intent, 2);

4、处理图片选择结果

if (data == null){
  return;
}else{
  //用户从图库选择图片后会返回所选图片的Uri
  Uri uri;
  //获取到用户所选图片的Uri
  uri = data.getData();
}

三、 裁剪选择的图片

从相机拍照得到的是Bitmap类型,所以我们需要先将其转化为文件Uri以供裁剪。同时我们还要顺便将相机拍的照片保存到本地。

 /**
 * 将Bitmap写入SD卡中的一个文件中,并返回写入文件的Uri
 * @param bm
 * @param dirPath
 * @return
 */
private Uri saveBitmap(Bitmap bm, String dirPath) {
  //新建文件夹用于存放裁剪后的图片
  File tmpDir = new File(Environment.getExternalStorageDirectory() + "/" + dirPath);
  if (!tmpDir.exists()){
    tmpDir.mkdir();
  }

  //新建文件存储裁剪后的图片
  File img = new File(tmpDir.getAbsolutePath() + "/avator.png");
  try {
    //打开文件输出流
    FileOutputStream fos = new FileOutputStream(img);
    //将bitmap压缩后写入输出流(参数依次为图片格式、图片质量和输出流)
    bm.compress(Bitmap.CompressFormat.PNG, 85, fos);
    //刷新输出流
    fos.flush();
    //关闭输出流
    fos.close();
    //返回File类型的Uri
    return Uri.fromFile(img);
  } catch (FileNotFoundException e) {
    e.printStackTrace();
    return null;
  } catch (IOException e) {
    e.printStackTrace();
    return null;
  }
}

从图库选择的图片返回的是content类型的Uri,我们需要转化为文件类型的Uri才能进行裁剪。

 /**
* 将content类型的Uri转化为文件类型的Uri
* @param uri
* @return
*/
private Uri convertUri(Uri uri){
  InputStream is;
  try {
    //Uri ----> InputStream
    is = getContentResolver().openInputStream(uri);
    //InputStream ----> Bitmap
    Bitmap bm = BitmapFactory.decodeStream(is);
    //关闭流
    is.close();
    return saveBitmap(bm, "temp");
  } catch (FileNotFoundException e) {
    e.printStackTrace();
    return null;
  } catch (IOException e) {
    e.printStackTrace();
    return null;
  }

}

下面便是设置裁剪的参数,用隐式Intent方式启动裁剪程序

 /**
 * 通过Uri传递图像信息以供裁剪
 * @param uri
 */
private void startImageZoom(Uri uri){
  //构建隐式Intent来启动裁剪程序
  Intent intent = new Intent("com.android.camera.action.CROP");
  //设置数据uri和类型为图片类型
  intent.setDataAndType(uri, "image/*");
  //显示View为可裁剪的
  intent.putExtra("crop", true);
  //裁剪的宽高的比例为1:1
  intent.putExtra("aspectX", 1);
  intent.putExtra("aspectY", 1);
  //输出图片的宽高均为150
  intent.putExtra("outputX", 150);
  intent.putExtra("outputY", 150);
  //裁剪之后的数据是通过Intent返回
  intent.putExtra("return-data", true);
  startActivityForResult(intent, CROP_CODE);
}

下面是完整的布局文件和java文件

--------------------------------------------------------------------------------

activity_main.xml文件

<&#63;xml version="1.0" encoding="utf-8"&#63;>


  
  

MainActivity.java文件

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
  //用于展示选择的图片
  private ImageView mImageView;

  private static final int CAMERA_CODE = 1;
  private static final int GALLERY_CODE = 2;
  private static final int CROP_CODE = 3;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    initView();
  }

  private void initView() {
    mImageView = (ImageView) findViewById(R.id.show_image);
    Button chooseCamera = (Button) findViewById(R.id.choose_camera);
    chooseCamera.setOnClickListener(this);
    Button chooseGallery = (Button) findViewById(R.id.choose_gallery);
    chooseGallery.setOnClickListener(this);
  }

  @Override
  public void onClick(View view) {
    switch (view.getId()){
      case R.id.choose_camera:
        //拍照选择
        chooseFromCamera();
        break;
      case R.id.choose_gallery:
        //从相册选取
        chooseFromGallery();
        break;
      default:
        break;
    }
  }

  /**
   * 拍照选择图片
   */
  private void chooseFromCamera() {
    //构建隐式Intent
    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    //调用系统相机
    startActivityForResult(intent, CAMERA_CODE);
  }

  /**
   * 从相册选择图片
   */
  private void chooseFromGallery() {
    //构建一个内容选择的Intent
    Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
    //设置选择类型为图片类型
    intent.setType("image/*");
    //打开图片选择
    startActivityForResult(intent, GALLERY_CODE);
  }

  @Override
  protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode){
      case CAMERA_CODE:
        //用户点击了取消
        if(data == null){
          return;
        }else{
          Bundle extras = data.getExtras();
          if (extras != null){
            //获得拍的照片
            Bitmap bm = extras.getParcelable("data");
            //将Bitmap转化为uri
            Uri uri = saveBitmap(bm, "temp");
            //启动图像裁剪
            startImageZoom(uri);
          }
        }
        break;
      case GALLERY_CODE:
        if (data == null){
          return;
        }else{
          //用户从图库选择图片后会返回所选图片的Uri
          Uri uri;
          //获取到用户所选图片的Uri
          uri = data.getData();
          //返回的Uri为content类型的Uri,不能进行复制等操作,需要转换为文件Uri
          uri = convertUri(uri);
          startImageZoom(uri);
        }
        break;
      case CROP_CODE:
        if (data == null){
          return;
        }else{
          Bundle extras = data.getExtras();
          if (extras != null){
            //获取到裁剪后的图像
            Bitmap bm = extras.getParcelable("data");
            mImageView.setImageBitmap(bm);
          }
        }
        break;
      default:
        break;
    }
  }

  /**
   * 将content类型的Uri转化为文件类型的Uri
   * @param uri
   * @return
   */
  private Uri convertUri(Uri uri){
    InputStream is;
    try {
      //Uri ----> InputStream
      is = getContentResolver().openInputStream(uri);
      //InputStream ----> Bitmap
      Bitmap bm = BitmapFactory.decodeStream(is);
      //关闭流
      is.close();
      return saveBitmap(bm, "temp");
    } catch (FileNotFoundException e) {
      e.printStackTrace();
      return null;
    } catch (IOException e) {
      e.printStackTrace();
      return null;
    }
  }

  /**
   * 将Bitmap写入SD卡中的一个文件中,并返回写入文件的Uri
   * @param bm
   * @param dirPath
   * @return
   */
  private Uri saveBitmap(Bitmap bm, String dirPath) {
    //新建文件夹用于存放裁剪后的图片
    File tmpDir = new File(Environment.getExternalStorageDirectory() + "/" + dirPath);
    if (!tmpDir.exists()){
      tmpDir.mkdir();
    }

    //新建文件存储裁剪后的图片
    File img = new File(tmpDir.getAbsolutePath() + "/avator.png");
    try {
      //打开文件输出流
      FileOutputStream fos = new FileOutputStream(img);
      //将bitmap压缩后写入输出流(参数依次为图片格式、图片质量和输出流)
      bm.compress(Bitmap.CompressFormat.PNG, 85, fos);
      //刷新输出流
      fos.flush();
      //关闭输出流
      fos.close();
      //返回File类型的Uri
      return Uri.fromFile(img);
    } catch (FileNotFoundException e) {
      e.printStackTrace();
      return null;
    } catch (IOException e) {
      e.printStackTrace();
      return null;
    }

  }

  /**
   * 通过Uri传递图像信息以供裁剪
   * @param uri
   */
  private void startImageZoom(Uri uri){
    //构建隐式Intent来启动裁剪程序
    Intent intent = new Intent("com.android.camera.action.CROP");
    //设置数据uri和类型为图片类型
    intent.setDataAndType(uri, "image/*");
    //显示View为可裁剪的
    intent.putExtra("crop", true);
    //裁剪的宽高的比例为1:1
    intent.putExtra("aspectX", 1);
    intent.putExtra("aspectY", 1);
    //输出图片的宽高均为150
    intent.putExtra("outputX", 150);
    intent.putExtra("outputY", 150);
    //裁剪之后的数据是通过Intent返回
    intent.putExtra("return-data", true);
    startActivityForResult(intent, CROP_CODE);
  }
}

注:最后还需要在AndroidManifest文件中加入存储卡读写权限

代码如下:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


推荐阅读
  • 本文介绍了使用kotlin实现动画效果的方法,包括上下移动、放大缩小、旋转等功能。通过代码示例演示了如何使用ObjectAnimator和AnimatorSet来实现动画效果,并提供了实现抖动效果的代码。同时还介绍了如何使用translationY和translationX来实现上下和左右移动的效果。最后还提供了一个anim_small.xml文件的代码示例,可以用来实现放大缩小的效果。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文讨论了Alink回归预测的不完善问题,指出目前主要针对Python做案例,对其他语言支持不足。同时介绍了pom.xml文件的基本结构和使用方法,以及Maven的相关知识。最后,对Alink回归预测的未来发展提出了期待。 ... [详细]
  • 本文讲述了如何通过代码在Android中更改Recycler视图项的背景颜色。通过在onBindViewHolder方法中设置条件判断,可以实现根据条件改变背景颜色的效果。同时,还介绍了如何修改底部边框颜色以及提供了RecyclerView Fragment layout.xml和项目布局文件的示例代码。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • 本文介绍了在SpringBoot中集成thymeleaf前端模版的配置步骤,包括在application.properties配置文件中添加thymeleaf的配置信息,引入thymeleaf的jar包,以及创建PageController并添加index方法。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • Java验证码——kaptcha的使用配置及样式
    本文介绍了如何使用kaptcha库来实现Java验证码的配置和样式设置,包括pom.xml的依赖配置和web.xml中servlet的配置。 ... [详细]
  • Android系统移植与调试之如何修改Android设备状态条上音量加减键在横竖屏切换的时候的显示于隐藏
    本文介绍了如何修改Android设备状态条上音量加减键在横竖屏切换时的显示与隐藏。通过修改系统文件system_bar.xml实现了该功能,并分享了解决思路和经验。 ... [详细]
  • 本文介绍了Android 7的学习笔记总结,包括最新的移动架构视频、大厂安卓面试真题和项目实战源码讲义。同时还分享了开源的完整内容,并提醒读者在使用FileProvider适配时要注意不同模块的AndroidManfiest.xml中配置的xml文件名必须不同,否则会出现问题。 ... [详细]
  • Android开发实现的计时器功能示例
    本文分享了Android开发实现的计时器功能示例,包括效果图、布局和按钮的使用。通过使用Chronometer控件,可以实现计时器功能。该示例适用于Android平台,供开发者参考。 ... [详细]
  • ZSI.generate.Wsdl2PythonError: unsupported local simpleType restriction ... [详细]
  • HDFS2.x新特性
    一、集群间数据拷贝scp实现两个远程主机之间的文件复制scp-rhello.txtroothadoop103:useratguiguhello.txt推pushscp-rr ... [详细]
  • flowable工作流 流程变量_信也科技工作流平台的技术实践
    1背景随着公司业务发展及内部业务流程诉求的增长,目前信息化系统不能够很好满足期望,主要体现如下:目前OA流程引擎无法满足企业特定业务流程需求,且移动端体 ... [详细]
  • 本文介绍了在使用MSXML解析XML文件时出现DTD禁用问题的解决方案。通过代码示例和错误信息获取方法,解释了默认情况下DTD是禁用的,以及如何启用DTD的方法。此外,还提到了网上关于该问题的信息相对较少,因此本文提供了解决方案以供参考。 ... [详细]
author-avatar
蓝染
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有