花了两天时间看了下android的图片裁剪功能的实现。其实刚开始做这个我挺虚的,以为整个功能都需要自己写出来,但查了些资料,发现android已经提供了裁剪功能,需要的话自己调用就成了。soga,这下轻松多了。

原文地址请保留http://www.cnblogs.com/rossoneri/p/3976530.html

首先推荐几篇博客

Android大图片裁剪终极解决方案

要想弄明白裁剪功能,这系列博客非常重要,你可以不看我下面总结的,但你一定要看他这系列的几篇文章。

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

这篇也不错,比较喜欢他的注释。虽然也有些误导,比如说他有一段对setData,setType和setDataAndType方法的区别疑问,他说两种写法一样效果,我就信了,害得我找bug找了两个小时,一直怀疑别的参数出问题,实际上是这两个方法的差别。这一点后面会说。

其他的相关博客有很多,但基本上大同小异,包括我这篇。有了上面的两个博客,就可以大概搞懂这方面的原理了。

我要写的,就是多写一些注释,改变一些写法,增加点说明,积累点经验,为了自己以后方便重温自己做过的东西,而已。

不再浪费你我的时间,开始了。


丑得不能忍的分割区


RyanHoo的Demo写的很详细。但要学习,我习惯先把代码简化,看的逻辑清楚些。我选择了最适应自己需求的选择大图片裁剪的部分代码

我测试的简化代码

 1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2     xmlns:tools="http://schemas.android.com/tools" 3     android:layout_width="match_parent" 4     android:layout_height="match_parent" 5     tools:context=".MainActivity" > 6  7     <Button 8         android:id="@+id/button" 9         android:layout_width="wrap_content"10         android:layout_height="wrap_content"11         android:text="click me!" />12 13     <ImageView14         android:id="@+id/imageview"15         android:layout_width="match_parent"16         android:layout_height="match_parent"17         android:scaleType="centerInside" />18 19 </LinearLayout>
  1 public class MainActivity extends Activity implements OnClickListener {  2   3     private Uri imageUri;  4     private static final String IMAGE_FILE_LOCATION = "file:///sdcard/temp.jpg";  5     private Button btn;  6     private ImageView iv;  7   8     @Override  9     protected void onCreate(Bundle savedInstanceState) { 10         super.onCreate(savedInstanceState); 11         setContentView(R.layout.activity_main); 12         btn = (Button) findViewById(R.id.button); 13         btn.setOnClickListener(this); 14         imageUri = Uri.parse(IMAGE_FILE_LOCATION); 15         iv = (ImageView) findViewById(R.id.imageview); 16     } 17  18     @Override 19     public boolean onCreateOptionsMenu(Menu menu) { 20         // Inflate the menu; this adds items to the action bar if it is present. 21         getMenuInflater().inflate(R.menu.activity_main, menu); 22         return true; 23     } 24  25     @Override 26     public void onClick(View v) { 27         // TODO Auto-generated method stub 28  29         // 试着改成打开自己写的图片浏览器 30         switch (v.getId()) { 31         case R.id.button: 32             // 这段代码使用ACTION_GET_CONTENT和ACTION_PICK效果相同 33             Intent intent = new Intent(Intent.ACTION_GET_CONTENT, null); 34             // Intent intent = new Intent(Intent.ACTION_PICK, null); 35  36             // 如果使用com.android.camera.action.CROP 则直接打开裁剪照片的activity 那么可以用自己的图片浏览器选择图片 传入参数并使用之 37             // Intent intent = new Intent("com.android.camera.action.CROP"); 38  39             // 如果不设置type,则 ACTION_GET_CONTENT 会弹出异常FATAL EXCEPTION:main android.content.ActivityNotFoundException 40             // 而 ACTION_PICK 会弹出可用程序列表 但没有打开图片相关的程序(在我的两个设备上是这样) 41             intent.setType("image/*"); 42  43             // 设置在开启的Intent中设置显示的view可裁剪 44             // 这段代码里设置成false也能裁剪啊。。。这是为什么?懂的给我讲讲了 45             // 这段注释掉就不会跳转到裁剪的activity 46             intent.putExtra("crop", "true"); 47  48             // 设置x,y的比例,截图方框就按照这个比例来截 若设置为0,0,或者不设置 则自由比例截图 49             intent.putExtra("aspectX", 2); 50             intent.putExtra("aspectY", 1); 51  52             // 裁剪区的宽和高 其实就是裁剪后的显示区域 若裁剪的比例不是显示的比例,则自动压缩图片填满显示区域。若设置为0,0 就不显示。若不设置,则按原始大小显示 53             intent.putExtra("outputX", 200); 54             intent.putExtra("outputY", 100); 55  56             // 不知道有啥用。。可能会保存一个比例值 需要相关文档啊 57             intent.putExtra("scale", true); 58  59             // true的话直接返回bitmap,可能会很占内存 不建议 60             intent.putExtra("return-data", false); 61             // 上面设为false的时候将MediaStore.EXTRA_OUTPUT即"output"关联一个Uri 62             intent.putExtra("output", imageUri); 63             // 看参数即可知道是输出格式 64             intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString()); 65             // 面部识别 这里用不上 66             intent.putExtra("noFaceDetection", false); 67  68             // 想从Activity中获得返回数据,在启动Activity时候使用startActivityForResult方法 69             // 1为请求代码,可以是任意值,个人感觉用资源id会比较清楚,而且不会重复 比如当前控件的R.id.button 70             startActivityForResult(intent, 1); 71             break; 72         default: 73             break; 74         } 75     } 76  77     @Override 78     protected void onActivityResult(int requestCode, int resultCode, Intent data) { 79         // TODO Auto-generated method stub 80         super.onActivityResult(requestCode, resultCode, data); 81         if (resultCode != Activity.RESULT_OK) {// result is not correct 82             return; 83         } else { 84             switch (requestCode) { 85             case 1: 86                 if (imageUri != null) { 87                     Bitmap bitmap = decodeUriAsBitmap(imageUri); 88                     // 把解析到的位图显示出来 89                     iv.setImageBitmap(bitmap); 90                 } 91                 break; 92             default: 93                 break; 94             } 95  96         } 97     } 98  99     private Bitmap decodeUriAsBitmap(Uri uri) {100         Bitmap bitmap = null;101         try {102             // 先通过getContentResolver方法获得一个ContentResolver实例,103             // 调用openInputStream(Uri)方法获得uri关联的数据流stream104             // 把上一步获得的数据流解析成为bitmap105             bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));106         } catch (FileNotFoundException e) {107             e.printStackTrace();108             return null;109         }110         return bitmap;111     }112 }

其实用法看前面的博客就已经很清楚了,这里主要部分就是Intent附加数据的具体含义解释与使用方法,我都尽量写在代码的注释当中了。


再丑也得忍的分割线


我后来想只调用裁剪窗口,而选图片的时候使用自己写的图片选择器,那么这个参数怎么传,怎么调用裁剪activity呢?

使用裁剪功能用"com.android.camera.action.CROP"就可以。

传图片的话有两个方法,一个是intent直接传bitmap数据,另一个是传uri。

 1     private void startCropIntent(String path) throws FileNotFoundException { 2         Bitmap bmp = BitmapFactory.decodeFile(path); 5         Intent intent = new Intent("com.android.camera.action.CROP"); 9         // Intent传输的bytes不能超过40k。不建议这样 无法处理大图10         intent.putExtra("data", bmp);11         // intent.setData(uri);12         // intent.setType("image/*");13         intent.setDataAndType(imageUri, "image/*");14         intent.putExtra("crop", "true");15         intent.putExtra("aspectX", 2);16         intent.putExtra("aspectY", 1);17         intent.putExtra("outputX", 300);18         intent.putExtra("outputY", 150);19         // 设置为true直接返回bitmap20         intent.putExtra("return-data", true);24         startActivityForResult(intent, 1);25     }26 27     @Override28     protected void onActivityResult(int requestCode, int resultCode, Intent data) {29         super.onActivityResult(requestCode, resultCode, data);30         if (resultCode != Activity.RESULT_OK) {// result is not correct31             return;32         } else {33             switch (requestCode) {34             case 1:40                 Bundle bundle = data.getExtras();41                 Bitmap bitmap = bundle.getParcelable("data");42                 iv.setImageBitmap(bitmap);43 44                 break;45 46             default:47                 break;48             }49         }51     }

这里参数path是选择的图片的绝对路径。

这种方法有局限性,因为intent传递的数据不超过40k,只能选择40k以下的图片裁剪

还是使用uri比较好

 1 private void startCropIntent(String path) throws FileNotFoundException { 2         Bitmap bmp = BitmapFactory.decodeFile(path); 3  4         File file = new File(path); 5         Intent intent = new Intent("com.android.camera.action.CROP"); 7         Uri uri = Uri.fromFile(file);// parse(pathUri);13         intent.setDataAndType(uri, "image/*");14         intent.putExtra("crop", "true");15         intent.putExtra("aspectX", 2);16         intent.putExtra("aspectY", 1);17         intent.putExtra("outputX", 300);18         intent.putExtra("outputY", 150);19         // 设置为true直接返回bitmap20         intent.putExtra("return-data", false);21         // 上面设为false的时候将MediaStore.EXTRA_OUTPUT关联一个Uri22         intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);23         intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());24         startActivityForResult(intent, 1);25     }26 27     @Override28     protected void onActivityResult(int requestCode, int resultCode, Intent data) {29         super.onActivityResult(requestCode, resultCode, data);30         if (resultCode != Activity.RESULT_OK) {// result is not correct31             return;32         } else {33             switch (requestCode) {34             case 1:35                 if (imageUri != null) {36                     Bitmap bitmap = decodeUriAsBitmap(imageUri);37                     // 把解析到的位图显示出来38                     iv.setImageBitmap(bitmap);39                 }44                 break;45 46             default:47                 break;48             }49         }50 51     }52 53     private Bitmap decodeUriAsBitmap(Uri uri) {54         Bitmap bitmap = null;55         try {59             bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));60         } catch (FileNotFoundException e) {61             e.printStackTrace();62             return null;63         }64         return bitmap;65     }

这里需要注意

intent.setData(uri);intent.setType("image/*");和
intent.setDataAndType(uri, "image/*");是有区别的。

我开始以为两个方法一样的,但看了源码就清楚了。

1  public Intent setDataAndType(Uri data, String type) {2         mData = data;3         mType = type;4         return this;5     }
1     public Intent setData(Uri data) {2         mData = data;3         mType = null;4         return this;5     }
1     public Intent setType(String type) {2         mData = null;3         mType = type;4         return this;5     }

好了,调用系统裁剪就这么些内容,这方面除了文档太难找,也没什么难的。

下面就是不调用系统,自己写一个裁剪图片的工具了。

更多相关文章

  1. Android—TextView的XML属性和方法
  2. Android(安卓)TextView属性详解
  3. Android之Adapter用法总结
  4. Android之Adapter用法总结
  5. Android之Adapter用法总结
  6. Android(安卓)基本控件及表单三大控件,事件处理
  7. Android(安卓)图片上传框架
  8. 【Android】TextView 属性详解
  9. 浅谈android的selector背景选择器

随机推荐

  1. android 由entity创建创建表的sql语句
  2. Android(安卓)保持屏幕常亮
  3. 【工具类】Android判断SD卡状态
  4. ANDROID画图PATH的使用
  5. Android滑动冲突解决方法
  6. Android常见错误处理(三)
  7. Android(安卓)Studio混淆错误:Missing cla
  8. android 添加预装的方法
  9. Android中获取电池电量
  10. Android的Intent+uri应用实例