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文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:orientation="vertical">

  <ImageView
    android:id="@+id/show_image"
    android:layout_width="match_parent"
    android:layout_height="300dp"/>
  <Button
    android:id="@+id/choose_camera"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="摄像头"/>
  <Button
    android:id="@+id/choose_gallery"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="相册"/>
</LinearLayout>

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文件中加入存储卡读写权限

复制代码 代码如下:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

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

时间: 2016-08-20

Android选择图片或拍照图片上传到服务器

最近要搞一个项目,需要上传相册和拍照的图片,不负所望,终于完成了!  不过需要说明一下,其实网上很多教程拍照的图片,都是缩略图不是很清晰,所以需要在调用照相机的时候,事先生成一个地址,用于标识拍照的图片URI 具体上传代码: 1.选择图片和上传界面,包括上传完成和异常的回调监听 package com.spring.sky.image.upload; import java.util.HashMap; import java.util.Map; import android.app.Activi

android中写一个内部类来选择文件夹中指定的图片类型实例说明

复制代码 代码如下: /**本类是用来选择文件夹中是.jpg类型的图片*/ private class JpgFileFilter implements FilenameFilter{ @Override public boolean accept(File dir, String filename) { // TODO Auto-generated method stub return filename.endsWith(".jpg"); } }

Android实现QQ图片说说照片选择效果

本文实例为大家分享了Android实现QQ图片说说照片选择的具体代码,供大家参考,具体内容如下 效果展示 布局文件 布局是很简单的,一个GridView,直接上布局: layout/activity_add_photo.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/andr

分享实现Android图片选择的两种方式

Android选择图片的两种方式: 第一种:单张选取 通过隐式启动activity,跳转到相册选择一张返回结果 关键代码如下: 发送请求: private static final int PICTURE = 10086; //requestcode Intent intent = new Intent(); if (Build.VERSION.SDK_INT < 19) {//因为Android SDK在4.4版本后图片action变化了 所以在这里先判断一下 intent.setAction

Android实现本地图片选择及预览缩放效果

在做项目时经常会遇到选择本地图片的需求,以前都是懒得写直接调用系统方法来选择图片,但是这样并不能实现多选效果,最近又遇到了,所以还是写一个demo好了,以后也方便使用.还是首先来看看效果: 显示的图片使用RecyclerView实现的,利用Glide来加载:下面弹出的图片文件夹效果是采用PopupWindow实现,这里比采用PopupWindow更方便,弹出显示的左边图片是这个文件夹里的第一张图片:选中的图片可以进行预览,使用网上一个大神写的来实现的:至于图片的获取是用ContentProvid

android完美实现 拍照 选择图片 剪裁等代码分享

前言,版本兼容问题主要是由于4.4以前和4.4以后的Uri的格式不同所造成的错误 1.拍照 和选择图片   ①选择图片 intent = new Intent(Intent.ACTION_GET_CONTENT); intent.setType("image/*"); startActivityForResult(intent, GALLERY_REQUEST_CODE); ②拍照 intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE)

Android实现拍照、选择图片并裁剪图片功能

一. 实现拍照.选择图片并裁剪图片效果 按照之前博客的风格,首先看下实现效果. 二. uCrop项目应用 想起之前看到的Yalantis/uCrop效果比较绚,但是研究源码之后发现在定制界面方面还是有一点的限制,于是在它的基础上做了修改Android-Crop,把定制界面独立出来,让用户去自由设置.下图为使用Android-Crop实现的模仿微信选择图片并裁剪Demo. 三. 实现思路 比较简单的选择设备图片裁剪,并将裁剪后的图片保存到指定路径: 调用系统拍照,将拍照图片保存在SD卡,然后裁剪图

Android仿微信选择图片和拍照功能

本文实例为大家分享了 Android微信选择图片的具体代码,和微信拍照功能,供大家参考,具体内容如下 1.Android6.0系统,对于权限的使用都是需要申请,选择图片和拍照需要申请Manifest.permission.CAMERA, Manifest.permission.READ_EXTERNAL_STORAGE这两个权限. if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageM

Android仿微信照片选择器实现预览查看图片

好了下面进入正题,我们先看一下实现效果吧: 下面来介绍一下代码: 本思路就是: 1.先到手机中扫描jpeg和png的图片 2.获取导图片的路径和图片的父路径名也就是文件夹名 3.将图片路径和文件夹名分别添加导数据源中 4.数据源有了就是显示了,文件夹显示是利用的popwindow,而图片显示则是GridView 看一下具体代码: 首先开启一个线程去扫描图片 /** * 利用ContentProvider扫描手机中的图片,此方法在运行在子线程中 完成图片的扫描,最终获得jpg最多的那个文件夹 */

浅谈谈Android 图片选择器

ImageSelector 简介 Android自定义相册,实现了拍照.图片选择(单选/多选).ImageLoader无绑定 任由开发者选择 https://github.com/YancyYe/ImageSelector Demo Download Apk 更新内容 UI重改 所有功能可配置 解决OOM情况 图片手动选择 支持汉语和英语 截图展示 使用说明 步骤一: 通过Gradle抓取 dependencies { compile 'com.yancy.imageselector:image

Android图片选择器 丰富的配置选项

最近也是刚好项目用到,于是就动手写了一个Android 图片选择器的库.支持图库多选/单选/图片裁剪/拍照/自定义图片加载库,极大程度的简化使用. 截图 优点 1.通过实现ImageLoader接口,可以实现自定义图片加载器的功能.例如可以用Glide.Picasso.ImageLoader,暂不支持Fresco,因为SimpleDraweeView本身并不属于ImageView.当然,也可用相同的思路来实现. 2.可配置的ImgSelConfig.方便进行扩展. 3.简化使用 项目地址:htt

Android图片选择器ImageEditContainer

1. 简介 本次demo中一共封装了两个组件:ImageEditButton 和 ImageEditContainer.其中ImageEditContainer 是在 ImageEditButton,两个组件可单独使用. 在demo中,实现了 图片选择(拍照+本地),裁剪,压缩,保存本地 以及对已选择图片的删除操作(如果有修改需求,也可以使用对应方法进行操作,该方法已添加): 还有就是 针对 6.0权限的处理问题,本次使用了第三方库 rxpermissions 进行权限的处理. 2.项目主目录结

Android仿微信图片选择器ImageSelector使用详解

今天给大家介绍一个仿微信的图片选择器:ImageSelector.ImageSelector支持图片的单选.限数量的多选和不限数量的多选.支持图片预览和图片文件夹的切换.在上一篇文章 <Android 实现一个仿微信的图片选择器> 中我介绍了ImageSelector的实现思路和分析了它的核心代码,有兴趣的同学可以看一下.完整的代码放在了GitHub,欢迎大家下载和使用.本篇文章为大家介绍ImageSelector的具体使用方式. 先上效果图: 1.引入依赖 在Project的build.gr

Android ImageSelector微信图片选择器

前言 现在绝大多数的App都上传图片的功能,比如设置用户头像.聊天发送图片.发表动态.论坛帖子等.上传图片需要先从选择手机中选择要上传的图片,所以图片选择器在App中是很常见的组件,一般的手机都会自带一个图片选择器.不过很多App并不喜欢用手机自带的选择器,而是自己实现一个图片选择器. 比如微信的图片选择器就做的很好.没办法,谁让微信这么强大,我不超抄袭你,但是,我可以模仿你. 效果图 是不是和真的一样,哈哈,不过,作者的唯一缺陷就是没有提供拍照,唉,有一点遗憾,但是,这个就够用了! 思路 1.

浅谈Android获取ImageView上的图片,和一个有可能遇到的问题

1.在获取图片前先调用setDrawingCacheEnabled(true)这个方法: 举例:mImageView.setDrawingCacheEnabled(true); 2.之后可以通过getDrawingCache()获取图片 举例:Bitmap obmp = Bitmap.createBitmap(mImageView.getDrawingCache());  //获取到Bitmap的图片 3.获取完图片后记得调用setDrawingCacheEnabled(false) 举例:mI

Android 高仿QQ图片选择器

当做一款APP,需要选择本地图片时,首先考虑的无疑是系统相册,但是Android手机五花八门,再者手机像素的提升,大图无法返回等异常因数,导致适配机型比较困难,微信.QQ都相继的在自己的APP里集成了图片选择功能,放弃了系统提供的图片选择器,这里仿造QQ做了一个本地图片选择器,PS:之前有人说"仿"写成"防"了,今儿特意注意了下,求不错. 先上一张效果图,无图无真相啊~~~ 实现的效果大概是这样的: 1.单选:跳转到本地图片选择文件夹,选择文件夹后,进入到该文件夹下

Android实现图片选择器功能

本文实例为大家分享了Android实现图片选择器功能的具体代码,供大家参考,具体内容如下 图片选择功能用的是GitHub上的依赖库,网址 先来看下我运行的效果图如下所示: 该依赖库是Android平台上拍照/录像,图片/视频选择,编辑和压缩的一站式解决方案. 添加依赖,在app->build.gradle里面添加依赖 //图片/视频选择.预览.编辑与拍照 implementation 'com.github.guoxiaoxing:phoenix:1.0.15' 初始化: public clas

Android实现微信的图片选择器

现在大部分的App都上传图片的功能,比如设置用户头像.聊天发送图片.发表动态.论坛帖子等.上传图片需要先从选择手机中选择要上传的图片,所以图片选择器在App中是很常见的组件,一般的手机都会自带一个图片选择器.不过很多App并不喜欢用手机自带的选择器,而是自己实现一个图片选择器.比如微信的图片选择器就做的很好.所以我也仿照微信的样式和交互效果,自己做了一个图片选择器:ImageSelector.ImageSelector支持图片的单选.限数量的多选和不限数量的多选.支持图片预览和图片文件夹的切换.

Android自定义图片选择器简单版

前言:图片选择器基本上是每个App必备的东西,用公认好的第三方也可以,但是自己写的改起来方便,用起来顺手,而且这东西想想可能没动手之前想想比较难,实际操作起来就很简单了,这次先主要写流程,具体优化的细节以后在写. 难点:动手之前最困惑的问题就是怎么获取到手机里所有的图片,获取到之后,显示出来,处理逻辑这些就简单了. 步骤1:动态申请权限 private boolean permissionOpen() { if (ContextCompat.checkSelfPermission(this, M