转载请注明出处:http://blog.csdn.net/allen315410/article/details/39994913

近期从曾经的项目中扒下来一个经常使用的模块。在这里有必要记录一下的。就是android上获取图片以及裁剪图片,怎么样?这个功能是不是非经常常使用啊,你随便打开一个App。仅仅要它有注冊功能都会有设置人物头像的功能,尤其在内容型的app中更为常见,那么这些功能是怎么实现的呢?今天,在这里就记录一下好了。防止以后的项目中也会用到,就直接拿来用好了。

1.通过拍照或者图冊获取图片(不须要剪裁)

这样的获取图片的方式就比較次了,由于不设置图片的剪裁功能,有可能由于图片过大。导致OOM。可是这样的方式也是有必要讲一下的,其获取图片的方式有两种。一是调用系统相机实时拍摄一张图片,二十打开设备上已有的图库。在图库中选择一张照片。这两种方式实现方法都是一个道理,无非就是通过Intent调用系统的东西。以下是源代码,首先是图片选择方式的Activity,这个Activity被设置成了Dialog模式,须要进行设置一下。

布局文件/res/layout/activity_select_photo.xml:

  1. <?xml version="1.0" encoding="utf-8"?
  2.  
  3. >
  4. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  5. android:layout_width="fill_parent"
  6. android:layout_height="wrap_content"
  7. android:gravity="center_horizontal" >
  8.  
  9. <LinearLayout
  10. android:id="@+id/dialog_layout"
  11. android:layout_width="fill_parent"
  12. android:layout_height="wrap_content"
  13. android:layout_alignParentBottom="true"
  14. android:layout_marginLeft="10dip"
  15. android:layout_marginRight="10dip"
  16. android:gravity="center_horizontal"
  17. android:orientation="vertical" >
  18.  
  19. <LinearLayout
  20. android:layout_width="fill_parent"
  21. android:layout_height="wrap_content"
  22. android:background="@drawable/select_photo_up_bg"
  23. android:orientation="vertical"
  24. android:paddingBottom="5dp"
  25. android:paddingTop="5dp" >
  26.  
  27. <Button
  28. android:id="@+id/btn_take_photo"
  29. android:layout_width="fill_parent"
  30. android:layout_height="35dp"
  31. android:background="@drawable/select_photo_bg"
  32. android:text="拍照选取"
  33. android:textStyle="bold" />
  34.  
  35. <View
  36. android:layout_width="fill_parent"
  37. android:layout_height="0.5px"
  38. android:background="#828282" />
  39.  
  40. <Button
  41. android:id="@+id/btn_pick_photo"
  42. android:layout_width="fill_parent"
  43. android:layout_height="35dp"
  44. android:layout_marginTop="0dip"
  45. android:background="@drawable/select_photo_bg"
  46. android:text="相冊选取"
  47. android:textStyle="bold" />
  48. </LinearLayout>
  49.  
  50. <Button
  51. android:id="@+id/btn_cancel"
  52. android:layout_width="fill_parent"
  53. android:layout_height="35dp"
  54. android:layout_marginTop="20dip"
  55. android:background="@drawable/select_photo_bg"
  56. android:paddingBottom="5dp"
  57. android:paddingTop="5dp"
  58. android:text="取消"
  59. android:textColor="#ffff0000"
  60. android:textStyle="bold" />
  61. </LinearLayout>
  62.  
  63. </RelativeLayout>

接着是获取图片Activity里的代码SelectPhotoActivity:

  1. public class SelectPhotoActivity extends Activity implements OnClickListener {
  2. /** 使用照相机拍照获取图片 */
  3. public static final int SELECT_PIC_BY_TACK_PHOTO = 1;
  4. /** 使用相冊中的图片 */
  5. public static final int SELECT_PIC_BY_PICK_PHOTO = 2;
  6. /** 开启相机 */
  7. private Button btn_take_photo;
  8. /** 开启图冊 */
  9. private Button btn_pick_photo;
  10. /** 取消 */
  11. private Button btn_cancel;
  12. /** 获取到的图片路径 */
  13. private String picPath;
  14. private Intent lastIntent;
  15. private Uri photoUri;
  16. /** 从Intent获取图片路径的KEY */
  17. public static final String KEY_PHOTO_PATH = "photo_path";
  18.  
  19. @Override
  20. protected void onCreate(Bundle savedInstanceState) {
  21. super.onCreate(savedInstanceState);
  22. setContentView(R.layout.activity_select_photo);
  23. btn_take_photo = (Button) findViewById(R.id.btn_take_photo);
  24. btn_pick_photo = (Button) findViewById(R.id.btn_pick_photo);
  25. btn_cancel = (Button) findViewById(R.id.btn_cancel);
  26.  
  27. lastIntent = getIntent();
  28.  
  29. btn_take_photo.setOnClickListener(this);
  30. btn_pick_photo.setOnClickListener(this);
  31. btn_cancel.setOnClickListener(this);
  32. }
  33.  
  34. @Override
  35. public void onClick(View v) {
  36. switch (v.getId()) {
  37. case R.id.btn_take_photo : // 开启相机
  38. takePhoto();
  39. break;
  40. case R.id.btn_pick_photo : // 开启图冊
  41. pickPhoto();
  42. break;
  43. case R.id.btn_cancel : // 取消操作
  44. this.finish();
  45. break;
  46. default :
  47. break;
  48. }
  49. }
  50.  
  51. /**
  52. * 拍照获取图片
  53. */
  54. private void takePhoto() {
  55. // 运行拍照前,应该先推断SD卡是否存在
  56. String SDState = Environment.getExternalStorageState();
  57. if (SDState.equals(Environment.MEDIA_MOUNTED)) {
  58. Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);// "android.media.action.IMAGE_CAPTURE"
  59. /***
  60. * 须要说明一下,下面操作使用照相机拍照,拍照后的图片会存放在相冊中的 这里使用的这样的方式有一个优点就是获取的图片是拍照后的原图
  61. * 假设不有用ContentValues存放照片路径的话。拍照后获取的图片为缩略图不清晰
  62. */
  63. ContentValues values = new ContentValues();
  64. photoUri = this.getContentResolver().insert(
  65. MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
  66. intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, photoUri);
  67. startActivityForResult(intent, SELECT_PIC_BY_TACK_PHOTO);
  68. } else {
  69. Toast.makeText(getApplicationContext(), "内存卡不存在",
  70. Toast.LENGTH_SHORT).show();
  71. }
  72. }
  73.  
  74. /***
  75. * 从相冊中取图片
  76. */
  77. private void pickPhoto() {
  78. Intent intent = new Intent();
  79. intent.setType("image/*");
  80. intent.setAction(Intent.ACTION_GET_CONTENT);
  81. startActivityForResult(intent, SELECT_PIC_BY_PICK_PHOTO);
  82. }
  83.  
  84. @Override
  85. public boolean onTouchEvent(MotionEvent event) {
  86. finish();
  87. return super.onTouchEvent(event);
  88. }
  89.  
  90. @Override
  91. protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  92. if (resultCode == Activity.RESULT_OK) {
  93. doPhoto(requestCode, data);
  94. }
  95. super.onActivityResult(requestCode, resultCode, data);
  96. }
  97.  
  98. /**
  99. * 选择图片后。获取图片的路径
  100. *
  101. * @param requestCode
  102. * @param data
  103. */
  104. private void doPhoto(int requestCode, Intent data) {
  105. if (requestCode == SELECT_PIC_BY_PICK_PHOTO) {// 从相冊取图片,有些手机有异常情况,请注意
  106. if (data == null) {
  107. Toast.makeText(getApplicationContext(), "选择图片文件出错",
  108. Toast.LENGTH_SHORT).show();
  109. return;
  110. }
  111. photoUri = data.getData();
  112. if (photoUri == null) {
  113. Toast.makeText(getApplicationContext(), "选择图片文件出错",
  114. Toast.LENGTH_SHORT).show();
  115. return;
  116. }
  117. }
  118. String[] pojo = {MediaStore.Images.Media.DATA};
  119. Cursor cursor = managedQuery(photoUri, pojo, null, null, null);
  120. if (cursor != null) {
  121. int columnIndex = cursor.getColumnIndexOrThrow(pojo[0]);
  122. cursor.moveToFirst();
  123. picPath = cursor.getString(columnIndex);
  124. cursor.close();
  125. }
  126. if (picPath != null
  127. && (picPath.endsWith(".png") || picPath.endsWith(".PNG")
  128. || picPath.endsWith(".jpg") || picPath.endsWith(".JPG"))) {
  129. lastIntent.putExtra(KEY_PHOTO_PATH, picPath);
  130. setResult(Activity.RESULT_OK, lastIntent);
  131. finish();
  132. } else {
  133. Toast.makeText(getApplicationContext(), "选择图片文件不对",
  134. Toast.LENGTH_SHORT).show();
  135. }
  136. }
  137.  
  138. }

由于这Activity是要设置成Dialog模式的,所以须要在清单文件里设置一下style,/res/values/styles.xml里加入例如以下:

  1. <!-- 选取照片的Activity的样式风格,採取对话框的风格 -->
  2. <style name="AnimBottom" parent="@android:style/Animation">
  3. <item name="android:windowEnterAnimation">@anim/push_bottom_in</item>
  4. <item name="android:windowExitAnimation">@anim/push_bottom_out</item>
  5. </style>
  6.  
  7. <style name="DialogStyleBottom" parent="android:Theme.Dialog">
  8. <item name="android:windowAnimationStyle">@style/AnimBottom</item>
  9. <item name="android:windowFrame">@null</item>
  10. <!-- 边框 -->
  11. <item name="android:windowIsFloating">false</item>
  12. <!-- 是否浮如今activity之上 -->
  13. <item name="android:windowIsTranslucent">true</item>
  14. <!-- 半透明 -->
  15. <item name="android:windowNoTitle">true</item>
  16. <!-- 无标题 -->
  17. <item name="android:windowBackground">@android:color/transparent</item>
  18. <!-- 背景透明 -->
  19. <item name="android:backgroundDimEnabled">true</item>
  20. <!-- 模糊 -->
  21. </style>

在Activity的节点下。设置这个style:

  1. <activity
  2. android:name="com.example.croppictrue.SelectPhotoActivity"
  3. android:screenOrientation="portrait"
  4. android:theme="@style/DialogStyleBottom" >
  5. </activity>

加入权限:

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

执行效果例如以下:

   

2.通过拍照或者图冊获取图片(须要剪裁)

上面第一种方式获取图片是没有经过剪裁的,可是大多项目需求是须要剪裁图片后再使用,比如改动用户头像等等功能。那么,以下,就奉上剪裁图片的代码吧:

  1. public class CropPictureActivity extends Activity {
  2.  
  3. /** ImageView对象 */
  4. private ImageView iv_photo;
  5. private String[] items = new String[]{"选择本地图片", "拍照"};
  6. /** 头像名称 */
  7. private static final String IMAGE_FILE_NAME = "image.jpg";
  8.  
  9. /** 请求码 */
  10. private static final int IMAGE_REQUEST_CODE = 0;
  11. private static final int CAMERA_REQUEST_CODE = 1;
  12. private static final int RESULT_REQUEST_CODE = 2;
  13.  
  14. @Override
  15. protected void onCreate(Bundle savedInstanceState) {
  16. super.onCreate(savedInstanceState);
  17. setContentView(R.layout.activity_crop);
  18. iv_photo = (ImageView) findViewById(R.id.iv_photo);
  19. iv_photo.setOnClickListener(new OnClickListener() {
  20.  
  21. @Override
  22. public void onClick(View v) {
  23. showDialog();
  24. }
  25. });
  26. }
  27.  
  28. /**
  29. * 显示选择对话框
  30. */
  31. private void showDialog() {
  32.  
  33. new AlertDialog.Builder(this)
  34. .setTitle("设置头像")
  35. .setItems(items, new DialogInterface.OnClickListener() {
  36.  
  37. @Override
  38. public void onClick(DialogInterface dialog, int which) {
  39. switch (which) {
  40. case 0 :
  41. Intent intentFromGallery = new Intent();
  42. intentFromGallery.setType("image/*"); // 设置文件类型
  43. intentFromGallery
  44. .setAction(Intent.ACTION_GET_CONTENT);
  45. startActivityForResult(intentFromGallery,
  46. IMAGE_REQUEST_CODE);
  47. break;
  48. case 1 :
  49. Intent intentFromCapture = new Intent(
  50. MediaStore.ACTION_IMAGE_CAPTURE);
  51. // 推断存储卡能否够用,可用进行存储
  52. String state = Environment
  53. .getExternalStorageState();
  54. if (state.equals(Environment.MEDIA_MOUNTED)) {
  55. File path = Environment
  56. .getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
  57. File file = new File(path, IMAGE_FILE_NAME);
  58. intentFromCapture.putExtra(
  59. MediaStore.EXTRA_OUTPUT,
  60. Uri.fromFile(file));
  61. }
  62.  
  63. startActivityForResult(intentFromCapture,
  64. CAMERA_REQUEST_CODE);
  65. break;
  66. }
  67. }
  68. })
  69. .setNegativeButton("取消", new DialogInterface.OnClickListener() {
  70.  
  71. @Override
  72. public void onClick(DialogInterface dialog, int which) {
  73. dialog.dismiss();
  74. }
  75. }).show();
  76.  
  77. }
  78.  
  79. @Override
  80. protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  81. // 结果码不等于取消时候
  82. if (resultCode != RESULT_CANCELED) {
  83. switch (requestCode) {
  84. case IMAGE_REQUEST_CODE :
  85. startPhotoZoom(data.getData());
  86. break;
  87. case CAMERA_REQUEST_CODE :
  88. // 推断存储卡能否够用,可用进行存储
  89. String state = Environment.getExternalStorageState();
  90. if (state.equals(Environment.MEDIA_MOUNTED)) {
  91. File path = Environment
  92. .getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
  93. File tempFile = new File(path, IMAGE_FILE_NAME);
  94. startPhotoZoom(Uri.fromFile(tempFile));
  95. } else {
  96. Toast.makeText(getApplicationContext(),
  97. "未找到存储卡,无法存储照片!", Toast.LENGTH_SHORT).show();
  98. }
  99. break;
  100. case RESULT_REQUEST_CODE : // 图片缩放完毕后
  101. if (data != null) {
  102. getImageToView(data);
  103. }
  104. break;
  105. }
  106. }
  107. super.onActivityResult(requestCode, resultCode, data);
  108. }
  109.  
  110. /**
  111. * 裁剪图片方法实现
  112. *
  113. * @param uri
  114. */
  115. public void startPhotoZoom(Uri uri) {
  116. Intent intent = new Intent("com.android.camera.action.CROP");
  117. intent.setDataAndType(uri, "image/*");
  118. // 设置裁剪
  119. intent.putExtra("crop", "true");
  120. // aspectX aspectY 是宽高的比例
  121. intent.putExtra("aspectX", 1);
  122. intent.putExtra("aspectY", 1);
  123. // outputX outputY 是裁剪图片宽高
  124. intent.putExtra("outputX", 340);
  125. intent.putExtra("outputY", 340);
  126. intent.putExtra("return-data", true);
  127. startActivityForResult(intent, RESULT_REQUEST_CODE);
  128. }
  129.  
  130. /**
  131. * 保存裁剪之后的图片数据
  132. *
  133. * @param picdata
  134. */
  135. private void getImageToView(Intent data) {
  136. Bundle extras = data.getExtras();
  137. if (extras != null) {
  138. Bitmap photo = extras.getParcelable("data");
  139. Drawable drawable = new BitmapDrawable(this.getResources(), photo);
  140. iv_photo.setImageDrawable(drawable);
  141. }
  142. }
  143. }

效果图:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYWxsZW4zMTU0MTA=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" width="240" height="320" alt="">     

在这个Activity里为了简便处理,我没有在选择图片时候start一个Dialog风格的Activity了,就直接一个普通的对话框提示用户选择,效果或许。事实上实现的原理都比較简单,实现图片的剪裁就是发一个Intent请求,调用设备上全部具有剪裁图片功能的app去剪裁图片,我的设备上除了android系统自带的图库以外。还装有“快图浏览”这个app,这个app也自带一个图片剪裁的功能,全部当选择好图片后,会出现一个选择提示。用户能够依据提示选择究竟使用哪个app提供的剪裁功能区剪裁图片。

        以上代码均在模拟器上測试过。因为模拟器对相机支持的不好,所以就没有演示打开相机拍摄图片了。有兴趣的朋友能够先请下载这个Demo的源代码,执行在手机上试试看效果怎样,如若疏漏之后。欢迎大家批评指正!

源代码请在这里下载

版权声明:本文博客原创文章,博客,未经同意,不得转载。

android选择和裁剪图像拍摄的图像的更多相关文章

  1. Android大图片裁剪终极解决方案(上:原理分析)

    转载声明:Ryan的博客文章欢迎您的转载,但在转载的同时,请注明文章的来源出处,不胜感激! :-)  http://my.oschina.net/ryanhoo/blog/86842 约几个月前,我正 ...

  2. Halcon将裁剪后的图像还原为原始大小

    ************************************************************* * Halcon将裁剪后的图像还原为原始大小 * Author: LiGua ...

  3. android 头像选择以及裁剪

    一.布局申明 <ImageView android:id="@+id/head_image" android:layout_width="80dp" an ...

  4. Android 图片压缩、照片选择、裁剪,上传、一整套图片解决方案

    1.Android一整套图片解决方案 http://mp.weixin.qq.com/s?__biz=MzAxMTI4MTkwNQ==&mid=2650820998&idx=1& ...

  5. Android照片库选择图片裁剪闪退(兼容小米以及7.0以上机型)

    未经允许,禁止

  6. Android 图片的裁剪与相机调用

    有时候我们需要的图片并不适合我们想要的大小, 那么我们就可以用到系统自带的图片裁剪功能, 把规定范围的图像给剪出来. 贴上部分代码: //调用图库 Intent intent = new Intent ...

  7. android Shader类简介_渲染图像示例

    Android中提供了Shader类专门用来渲染图像以及一些几何图形,Shader下面包括几个直接子类,分别是BitmapShader. ComposeShader.LinearGradient.Ra ...

  8. Android大图片裁剪终极解决方案 原理分析

    约几个月前,我正为公司的APP在Android手机上实现拍照截图而烦恼不已. 上网搜索,确实有不少的例子,大多都是抄来抄去,而且水平多半处于demo的样子,可以用来讲解知识点,但是一碰到实际项目,就漏 ...

  9. xamarin.Android 选择本地图片、拍摄图片、剪裁图片

    [Activity(Theme = "@style/MyStyleBottom")] public class SelectPicPopupWindow : Activity, I ...

随机推荐

  1. 与众不同 windows phone (18) - Device(设备)之加速度传感器, 数字罗盘传感器

    原文:与众不同 windows phone (18) - Device(设备)之加速度传感器, 数字罗盘传感器 [索引页][源码下载] 与众不同 windows phone (18) - Device ...

  2. POJ 2112 Optimal Milking【网络流+二分+最短路】

    求使所有牛都可以被挤牛奶的条件下牛走的最长距离. Floyd求出两两节点之间的最短路,然后二分距离. 构图: 将每一个milking machine与源点连接,边权为最大值m,每个cow与汇点连接,边 ...

  3. LeetCode——Populating Next Right Pointers in Each Node II

    Follow up for problem "Populating Next Right Pointers in Each Node". What if the given tre ...

  4. HDU 2112 HDU Today(Dijkstra)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2112 HDU Today Time Limit: 15000/5000 MS (Java/Others ...

  5. BEGINNING SHAREPOINT&#174; 2013 DEVELOPMENT 第3章节--SharePoint 2013 开发者工具 站点设置

    BEGINNING SHAREPOINT® 2013 DEVELOPMENT 第3章节--SharePoint 2013 开发者工具 站点设置         你应该熟悉(假设还咩有)的SharePo ...

  6. 第一章. ActionScript 语言基础

    第一章. ActionScript 语言基础 1.0. ActionScript 3.0 Cookbook 概述 1.1. 新建一个 ActionScript project 1.2. 自己定义应用程 ...

  7. ON、WHERE、HAVING的差别

    ON .WHERE.HAVING都能通过限制条件筛选数据,但他们的使用及其不同.以下我们来分析三者之间的差别. 1.       ON 和WHERE 全部的查询都回产生一个中间暂时报表,查询结果就是从 ...

  8. bash学习之环境变量

    1.查看系统存在的环境变量env 和 export env命令:查看环境变量 [CJP@CJP ~]$ env HOSTNAME=CJP SHELL=/bin/bash HISTSIZE=1000 U ...

  9. Wix打包系列(四) 自定义UI

    原文:Wix打包系列(四) 自定义UI 除了标准的安装界面,如果我们要在安装时需要提供一些额外的信息时,这时就需要自定义界面来显示和录入这些信息. 4.1  自定义对话框 如上一章中我们测试数据库的连 ...

  10. hdu1535(最短路)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=1535 题意:给你一个源点,让你从这里派发n个学生去其余的n-1个站点去邀请人们去CSS,然后再返回CS ...