[Android] 图片裁剪总结——调用系统裁剪
花了两天时间看了下android的图片裁剪功能的实现。其实刚开始做这个我挺虚的,以为整个功能都需要自己写出来,但查了些资料,发现android已经提供了裁剪功能,需要的话自己调用就成了。soga,这下轻松多了。
原文地址请保留http://www.cnblogs.com/rossoneri/p/3976530.html
首先推荐几篇博客
要想弄明白裁剪功能,这系列博客非常重要,你可以不看我下面总结的,但你一定要看他这系列的几篇文章。
Android 图片裁剪功能实现详解(类似QQ自定义头像裁剪)
这篇也不错,比较喜欢他的注释。虽然也有些误导,比如说他有一段对setData,setType和setDataAndType方法的区别疑问,他说两种写法一样效果,我就信了,害得我找bug找了两个小时,一直怀疑别的参数出问题,实际上是这两个方法的差别。这一点后面会说。
其他的相关博客有很多,但基本上大同小异,包括我这篇。有了上面的两个博客,就可以大概搞懂这方面的原理了。
我要写的,就是多写一些注释,改变一些写法,增加点说明,积累点经验,为了自己以后方便重温自己做过的东西,而已。
不再浪费你我的时间,开始了。
丑得不能忍的分割区
RyanHoo的Demo写的很详细。但要学习,我习惯先把代码简化,看的逻辑清楚些。我选择了最适应自己需求的选择大图片裁剪的部分代码
我测试的简化代码
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" > <Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="click me!" /> <ImageView
android:id="@+id/imageview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerInside" /> </LinearLayout>
public class MainActivity extends Activity implements OnClickListener {
private Uri imageUri;
private static final String IMAGE_FILE_LOCATION = "file:///sdcard/temp.jpg";
private Button btn;
private ImageView iv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = (Button) findViewById(R.id.button);
btn.setOnClickListener(this);
imageUri = Uri.parse(IMAGE_FILE_LOCATION);
iv = (ImageView) findViewById(R.id.imageview);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
// 试着改成打开自己写的图片浏览器
switch (v.getId()) {
case R.id.button:
//这段代码使用ACTION_GET_CONTENT和ACTION_PICK效果相同
Intent intent = new Intent(Intent.ACTION_GET_CONTENT, null);
// Intent intent = new Intent(Intent.ACTION_PICK, null);
// 如果使用com.android.camera.action.CROP 则直接打开裁剪照片的activity 那么可以用自己的图片浏览器选择图片 传入参数并使用之
// Intent intent = new Intent("com.android.camera.action.CROP");
// 如果不设置type,则 ACTION_GET_CONTENT 会弹出异常FATAL EXCEPTION:main android.content.ActivityNotFoundException
// 而 ACTION_PICK 会弹出可用程序列表 但没有打开图片相关的程序(在我的两个设备上是这样)
intent.setType("image/*");
// 设置在开启的Intent中设置显示的view可裁剪
// 这段代码里设置成false也能裁剪啊。。。这是为什么?懂的给我讲讲了
// 这段注释掉就不会跳转到裁剪的activity
intent.putExtra("crop", "true");
// 设置x,y的比例,截图方框就按照这个比例来截 若设置为0,0,或者不设置 则自由比例截图
intent.putExtra("aspectX", 2);
intent.putExtra("aspectY", 1);
// 裁剪区的宽和高 其实就是裁剪后的显示区域 若裁剪的比例不是显示的比例,则自动压缩图片填满显示区域。若设置为0,0 就不显示。若不设置,则按原始大小显示
intent.putExtra("outputX", 200);
intent.putExtra("outputY", 100);
// 不知道有啥用。。可能会保存一个比例值 需要相关文档啊
intent.putExtra("scale", true);
// true的话直接返回bitmap,可能会很占内存 不建议
intent.putExtra("return-data", false);
// 上面设为false的时候将MediaStore.EXTRA_OUTPUT即"output"关联一个Uri
intent.putExtra("output", imageUri);
// 看参数即可知道是输出格式
intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
// 面部识别 这里用不上
intent.putExtra("noFaceDetection", false);
// 想从Activity中获得返回数据,在启动Activity时候使用startActivityForResult方法
// 1为请求代码,可以是任意值,个人感觉用资源id会比较清楚,而且不会重复 比如当前控件的R.id.button
startActivityForResult(intent, 1);
break;
default:
break;
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
super.onActivityResult(requestCode, resultCode, data);
if (resultCode != Activity.RESULT_OK) {// result is not correct
return;
} else {
switch (requestCode) {
case 1:
if (imageUri != null) {
Bitmap bitmap = decodeUriAsBitmap(imageUri);
// 把解析到的位图显示出来
iv.setImageBitmap(bitmap);
}
break;
default:
break;
}
}
}
private Bitmap decodeUriAsBitmap(Uri uri) {
Bitmap bitmap = null;
try {
// 先通过getContentResolver方法获得一个ContentResolver实例,
// 调用openInputStream(Uri)方法获得uri关联的数据流stream
// 把上一步获得的数据流解析成为bitmap
bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
}
return bitmap;
}
}
其实用法看前面的博客就已经很清楚了,这里主要部分就是Intent附加数据的具体含义解释与使用方法,我都尽量写在代码的注释当中了。
再丑也得忍的分割线
我后来想只调用裁剪窗口,而选图片的时候使用自己写的图片选择器,那么这个参数怎么传,怎么调用裁剪activity呢?
使用裁剪功能用"com.android.camera.action.CROP"就可以。
传图片的话有两个方法,一个是intent直接传bitmap数据,另一个是传uri。
private void startCropIntent(String path) throws FileNotFoundException {
Bitmap bmp = BitmapFactory.decodeFile(path);
Intent intent = new Intent("com.android.camera.action.CROP"); // Intent传输的bytes不能超过40k。不建议这样 无法处理大图
intent.putExtra("data", bmp);
// intent.setData(uri);
// intent.setType("image/*");
intent.setDataAndType(imageUri, "image/*");
intent.putExtra("crop", "true");
intent.putExtra("aspectX", 2);
intent.putExtra("aspectY", 1);
intent.putExtra("outputX", 300);
intent.putExtra("outputY", 150);
// 设置为true直接返回bitmap
intent.putExtra("return-data", true);
startActivityForResult(intent, 1);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode != Activity.RESULT_OK) {// result is not correct
return;
} else {
switch (requestCode) {
case 1:
Bundle bundle = data.getExtras();
Bitmap bitmap = bundle.getParcelable("data");
iv.setImageBitmap(bitmap);
break;
default:
break;
}
}
}
这里参数path是选择的图片的绝对路径。
这种方法有局限性,因为intent传递的数据不超过40k,只能选择40k以下的图片裁剪
还是使用uri比较好
private void startCropIntent(String path) throws FileNotFoundException {
Bitmap bmp = BitmapFactory.decodeFile(path);
File file = new File(path);
Intent intent = new Intent("com.android.camera.action.CROP");
Uri uri = Uri.fromFile(file);// parse(pathUri); intent.setDataAndType(uri, "image/*");
intent.putExtra("crop", "true");
intent.putExtra("aspectX", 2);
intent.putExtra("aspectY", 1);
intent.putExtra("outputX", 300);
intent.putExtra("outputY", 150);
// 设置为true直接返回bitmap
intent.putExtra("return-data", false);
// 上面设为false的时候将MediaStore.EXTRA_OUTPUT关联一个Uri
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
startActivityForResult(intent, 1);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode != Activity.RESULT_OK) {// result is not correct
return;
} else {
switch (requestCode) {
case 1:
if (imageUri != null) {
Bitmap bitmap = decodeUriAsBitmap(imageUri);
// 把解析到的位图显示出来
iv.setImageBitmap(bitmap);
}
break;
default:
break;
}
}
}
private Bitmap decodeUriAsBitmap(Uri uri) {
Bitmap bitmap = null;
try {
bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
}
return bitmap;
}
这里需要注意
intent.setData(uri);intent.setType("image/*");和
intent.setDataAndType(uri, "image/*");是有区别的。
我开始以为两个方法一样的,但看了源码就清楚了。
public Intent setDataAndType(Uri data, String type) {
mData = data;
mType = type;
return this;
}
public Intent setData(Uri data) {
mData = data;
mType = null;
return this;
}
public Intent setType(String type) {
mData = null;
mType = type;
return this;
}
好了,调用系统裁剪就这么些内容,这方面除了文档太难找,也没什么难的。
[Android] 图片裁剪总结——调用系统裁剪的更多相关文章
- Android开发中怎样调用系统Email发送邮件(多种调用方式)
在Android中调用其他程序进行相关处理,几乎都是使用的Intent,所以,Email也不例外,所谓的调用Email,只是说Email可以接收Intent并做这些事情 我们都知道,在Android中 ...
- Android开发_如何调用系统默认浏览器访问
Android开发_如何调用系统默认浏览器访问 2015-10-20 17:53 312人阅读 http://blog.sina.com.cn/s/blog_6efce07e010142w7.htm ...
- 调用系统文件管理器选择图片,调用系统裁剪AIP对图片处理,显示裁剪之后的图片
package com.pingyijinren.test; import android.annotation.TargetApi; import android.app.Notification; ...
- 调用系统相机拍照,保存照片,调用系统裁剪API对照片处理,显示裁剪之后的照片
package com.pingyijinren.test; import android.annotation.TargetApi; import android.app.Notification; ...
- Android连接wifi,调用系统API【转】
本文转载自:http://blog.csdn.net/aaa1050070637/article/details/54136472 直接上代码,简单粗暴,一看就懂 import android.con ...
- [Android Pro] 调用系统相机和图库,裁剪图片
private static final int PHOTO_REQUEST_TAKEPHOTO = 1;// 拍照 private static final int PHOTO_REQUEST_GA ...
- Android 图片的裁剪与相机调用
有时候我们需要的图片并不适合我们想要的大小, 那么我们就可以用到系统自带的图片裁剪功能, 把规定范围的图像给剪出来. 贴上部分代码: //调用图库 Intent intent = new Intent ...
- Android调用系统拍照裁剪和选图功能
最近项目中用到修改用户头像的功能,基本上都是模板代码,现在简单记录一下. 调用系统拍照 private fun openCamera() { //调用相机拍照 // 创建File对象,用于存储拍照后的 ...
- [Android] 图片裁剪总结——自定义裁剪工具
上次弄完调用系统裁剪之后,我又试着做一个自定义的裁剪工具. 原文地址请保留http://www.cnblogs.com/rossoneri/p/3988405.html 老习惯,文章开始前还是先把我参 ...
随机推荐
- (转)Python开发程序:支持多用户在线的FTP程序
原文链接:http://www.itnose.net/detail/6642756.html 作业:开发一个支持多用户在线的FTP程序 要求: 用户加密认证 允许同时多用户登录 每个用户有自己的家目录 ...
- tomcat 最大并发数
只针对BIO模式,目标请求会sleep两秒再返回结果,通过jmeter测试工具进行并发测试 操作系统:windows && linux tomcat7测试: <Connector ...
- 生产者消费者模式中条件判断是使用while而不是if
永远在循环(loop)里调用 wait 和 notify,不是在 If 语句现在你知道wait应该永远在被synchronized的背景下和那个被多线程共享的对象上调用,下一个一定要记住的问题就是,你 ...
- 一口一口吃掉Hexo(三)
如果你想得到更好的阅读效果,请访问我的个人网站 ,版权所有,未经许可不得转载! 相信通过前一节的学习,你已经在你的本地部署好了你的网站,那么接下来就让你的朋友们通过网络访问你的网站吧!通过这一节你将免 ...
- 全网最详细的Windows系统里PLSQL Developer 64bit安装之后的一些配置(图文详解)
不多说,直接上干货! 注意的是: 本地若没有安装Oracle服务端,Oracle server服务端64位,是远程连接,因此本地配置PLSQL Developer64位. PLSQL Develope ...
- salesforce 零基础学习(七十)使用jquery tree实现树形结构模式
项目中UI需要用到树形结构显示内容,后来尽管不需要做了,不过还是自己做着玩玩,mark一下,免得以后项目中用到. 实现树形结构在此使用的是jquery的dynatree.js.关于dynatree的使 ...
- Hadoop2源码分析-序列化篇
1.概述 上一篇我们了解了MapReduce的相关流程,包含MapReduce V2的重构思路,新的设计架构,与MapReduce V1的区别等内容,今天我们在来学习下在Hadoop V2中的序列化的 ...
- 人人,金山西山居,腾讯互娱,微信,网易游戏offer及面经
转自:http://www.itmian4.com/forum.php?mod=viewthread&tid=3985 首先感谢师兄在两年前发的贴([天道酬勤] 腾讯.百度.网易游戏.华为Of ...
- 基于Ip的刷投票排名及刷百度推广的自动化实现
所有基于Ip的刷投票排名,只要不涉及用户登录情况,都可以在手机端自动化实现,因为电信运营商的ip地址段是无限的,理论上,飞行模式开关一次,所分配ip地址是变化的,这就有了大量的ip可用 在手机端写个a ...
- 性能提速:debounce(防抖)、throttle(节流/限频)
debounce与throttle是用户交互处理中常用到的性能提速方案,debounce用来实现防抖动,throttle用来实现节流(限频).那么这两个方法到底是什么(what)?为何要用(why-解 ...