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

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

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

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

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

<?xml version="1.0" encoding="utf-8"?

>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal" > <LinearLayout
android:id="@+id/dialog_layout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
android:gravity="center_horizontal"
android:orientation="vertical" > <LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@drawable/select_photo_up_bg"
android:orientation="vertical"
android:paddingBottom="5dp"
android:paddingTop="5dp" > <Button
android:id="@+id/btn_take_photo"
android:layout_width="fill_parent"
android:layout_height="35dp"
android:background="@drawable/select_photo_bg"
android:text="拍照选取"
android:textStyle="bold" /> <View
android:layout_width="fill_parent"
android:layout_height="0.5px"
android:background="#828282" /> <Button
android:id="@+id/btn_pick_photo"
android:layout_width="fill_parent"
android:layout_height="35dp"
android:layout_marginTop="0dip"
android:background="@drawable/select_photo_bg"
android:text="相冊选取"
android:textStyle="bold" />
</LinearLayout> <Button
android:id="@+id/btn_cancel"
android:layout_width="fill_parent"
android:layout_height="35dp"
android:layout_marginTop="20dip"
android:background="@drawable/select_photo_bg"
android:paddingBottom="5dp"
android:paddingTop="5dp"
android:text="取消"
android:textColor="#ffff0000"
android:textStyle="bold" />
</LinearLayout> </RelativeLayout>

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

public class SelectPhotoActivity extends Activity implements OnClickListener {
/** 使用照相机拍照获取图片 */
public static final int SELECT_PIC_BY_TACK_PHOTO = 1;
/** 使用相冊中的图片 */
public static final int SELECT_PIC_BY_PICK_PHOTO = 2;
/** 开启相机 */
private Button btn_take_photo;
/** 开启图冊 */
private Button btn_pick_photo;
/** 取消 */
private Button btn_cancel;
/** 获取到的图片路径 */
private String picPath;
private Intent lastIntent;
private Uri photoUri;
/** 从Intent获取图片路径的KEY */
public static final String KEY_PHOTO_PATH = "photo_path"; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_select_photo);
btn_take_photo = (Button) findViewById(R.id.btn_take_photo);
btn_pick_photo = (Button) findViewById(R.id.btn_pick_photo);
btn_cancel = (Button) findViewById(R.id.btn_cancel); lastIntent = getIntent(); btn_take_photo.setOnClickListener(this);
btn_pick_photo.setOnClickListener(this);
btn_cancel.setOnClickListener(this);
} @Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_take_photo : // 开启相机
takePhoto();
break;
case R.id.btn_pick_photo : // 开启图冊
pickPhoto();
break;
case R.id.btn_cancel : // 取消操作
this.finish();
break;
default :
break;
}
} /**
* 拍照获取图片
*/
private void takePhoto() {
// 运行拍照前,应该先推断SD卡是否存在
String SDState = Environment.getExternalStorageState();
if (SDState.equals(Environment.MEDIA_MOUNTED)) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);// "android.media.action.IMAGE_CAPTURE"
/***
* 须要说明一下,下面操作使用照相机拍照,拍照后的图片会存放在相冊中的 这里使用的这样的方式有一个优点就是获取的图片是拍照后的原图
* 假设不有用ContentValues存放照片路径的话。拍照后获取的图片为缩略图不清晰
*/
ContentValues values = new ContentValues();
photoUri = this.getContentResolver().insert(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, photoUri);
startActivityForResult(intent, SELECT_PIC_BY_TACK_PHOTO);
} else {
Toast.makeText(getApplicationContext(), "内存卡不存在",
Toast.LENGTH_SHORT).show();
}
} /***
* 从相冊中取图片
*/
private void pickPhoto() {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(intent, SELECT_PIC_BY_PICK_PHOTO);
} @Override
public boolean onTouchEvent(MotionEvent event) {
finish();
return super.onTouchEvent(event);
} @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == Activity.RESULT_OK) {
doPhoto(requestCode, data);
}
super.onActivityResult(requestCode, resultCode, data);
} /**
* 选择图片后。获取图片的路径
*
* @param requestCode
* @param data
*/
private void doPhoto(int requestCode, Intent data) {
if (requestCode == SELECT_PIC_BY_PICK_PHOTO) {// 从相冊取图片,有些手机有异常情况,请注意
if (data == null) {
Toast.makeText(getApplicationContext(), "选择图片文件出错",
Toast.LENGTH_SHORT).show();
return;
}
photoUri = data.getData();
if (photoUri == null) {
Toast.makeText(getApplicationContext(), "选择图片文件出错",
Toast.LENGTH_SHORT).show();
return;
}
}
String[] pojo = {MediaStore.Images.Media.DATA};
Cursor cursor = managedQuery(photoUri, pojo, null, null, null);
if (cursor != null) {
int columnIndex = cursor.getColumnIndexOrThrow(pojo[0]);
cursor.moveToFirst();
picPath = cursor.getString(columnIndex);
cursor.close();
}
if (picPath != null
&& (picPath.endsWith(".png") || picPath.endsWith(".PNG")
|| picPath.endsWith(".jpg") || picPath.endsWith(".JPG"))) {
lastIntent.putExtra(KEY_PHOTO_PATH, picPath);
setResult(Activity.RESULT_OK, lastIntent);
finish();
} else {
Toast.makeText(getApplicationContext(), "选择图片文件不对",
Toast.LENGTH_SHORT).show();
}
} }

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

<!-- 选取照片的Activity的样式风格,採取对话框的风格 -->
<style name="AnimBottom" parent="@android:style/Animation">
<item name="android:windowEnterAnimation">@anim/push_bottom_in</item>
<item name="android:windowExitAnimation">@anim/push_bottom_out</item>
</style> <style name="DialogStyleBottom" parent="android:Theme.Dialog">
<item name="android:windowAnimationStyle">@style/AnimBottom</item>
<item name="android:windowFrame">@null</item>
<!-- 边框 -->
<item name="android:windowIsFloating">false</item>
<!-- 是否浮如今activity之上 -->
<item name="android:windowIsTranslucent">true</item>
<!-- 半透明 -->
<item name="android:windowNoTitle">true</item>
<!-- 无标题 -->
<item name="android:windowBackground">@android:color/transparent</item>
<!-- 背景透明 -->
<item name="android:backgroundDimEnabled">true</item>
<!-- 模糊 -->
</style>

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

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

加入权限:

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

执行效果例如以下:

   

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

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

public class CropPictureActivity extends Activity {

	/** ImageView对象 */
private ImageView iv_photo;
private String[] items = new String[]{"选择本地图片", "拍照"};
/** 头像名称 */
private static final String IMAGE_FILE_NAME = "image.jpg"; /** 请求码 */
private static final int IMAGE_REQUEST_CODE = 0;
private static final int CAMERA_REQUEST_CODE = 1;
private static final int RESULT_REQUEST_CODE = 2; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_crop);
iv_photo = (ImageView) findViewById(R.id.iv_photo);
iv_photo.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
showDialog();
}
});
} /**
* 显示选择对话框
*/
private void showDialog() { new AlertDialog.Builder(this)
.setTitle("设置头像")
.setItems(items, new DialogInterface.OnClickListener() { @Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case 0 :
Intent intentFromGallery = new Intent();
intentFromGallery.setType("image/*"); // 设置文件类型
intentFromGallery
.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(intentFromGallery,
IMAGE_REQUEST_CODE);
break;
case 1 :
Intent intentFromCapture = new Intent(
MediaStore.ACTION_IMAGE_CAPTURE);
// 推断存储卡能否够用,可用进行存储
String state = Environment
.getExternalStorageState();
if (state.equals(Environment.MEDIA_MOUNTED)) {
File path = Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
File file = new File(path, IMAGE_FILE_NAME);
intentFromCapture.putExtra(
MediaStore.EXTRA_OUTPUT,
Uri.fromFile(file));
} startActivityForResult(intentFromCapture,
CAMERA_REQUEST_CODE);
break;
}
}
})
.setNegativeButton("取消", new DialogInterface.OnClickListener() { @Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
}).show(); } @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// 结果码不等于取消时候
if (resultCode != RESULT_CANCELED) {
switch (requestCode) {
case IMAGE_REQUEST_CODE :
startPhotoZoom(data.getData());
break;
case CAMERA_REQUEST_CODE :
// 推断存储卡能否够用,可用进行存储
String state = Environment.getExternalStorageState();
if (state.equals(Environment.MEDIA_MOUNTED)) {
File path = Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
File tempFile = new File(path, IMAGE_FILE_NAME);
startPhotoZoom(Uri.fromFile(tempFile));
} else {
Toast.makeText(getApplicationContext(),
"未找到存储卡,无法存储照片!", Toast.LENGTH_SHORT).show();
}
break;
case RESULT_REQUEST_CODE : // 图片缩放完毕后
if (data != null) {
getImageToView(data);
}
break;
}
}
super.onActivityResult(requestCode, resultCode, data);
} /**
* 裁剪图片方法实现
*
* @param uri
*/
public void startPhotoZoom(Uri uri) {
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setDataAndType(uri, "image/*");
// 设置裁剪
intent.putExtra("crop", "true");
// aspectX aspectY 是宽高的比例
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
// outputX outputY 是裁剪图片宽高
intent.putExtra("outputX", 340);
intent.putExtra("outputY", 340);
intent.putExtra("return-data", true);
startActivityForResult(intent, RESULT_REQUEST_CODE);
} /**
* 保存裁剪之后的图片数据
*
* @param picdata
*/
private void getImageToView(Intent data) {
Bundle extras = data.getExtras();
if (extras != null) {
Bitmap photo = extras.getParcelable("data");
Drawable drawable = new BitmapDrawable(this.getResources(), photo);
iv_photo.setImageDrawable(drawable);
}
}
}

效果图:

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. 在VC资源文件中加入声音资源

    本文介绍如何在VC资源文件中加入自己的声音资源,使自己的应用程序可以播放声音. 1.首先用文本编辑器(如记事本)打开资源文件(.rc文件) 在最后加入自己的声音资源,如下IDW WAVE " ...

  2. LVS Nginx HAProxy 优缺点

    搭建负载均衡高可用环境相对简单,主要是要理解其中原理.此文描述了三种负载均衡器的优缺点,以便在实际的生产应用中,按需求取舍. 目前,在线上环境中应用较多的负载均衡器硬件有F5 BIG-IP,软件有LV ...

  3. leetcode第一刷_Largest Rectangle in Histogram

    非常难的问题,数组线性时间. 属于我之前说的解法的借助辅助空间.给定两个柱子,他们之间的面积由什么确定呢?没错,他们之间的距离和他们之间最矮的那个柱子的高度.我们并不知道这个柱子在什么位置,所以仅仅能 ...

  4. Button UI Kit CSS3美丽Buttonbutton

    <!DOCTYPE HTML> <html lang="en-US"> <head> <meta charset="UTF-8& ...

  5. (step5.1.2)hdu 1305(Immediate Decodability——字典树)

    题目大意:输入一系列的字符串,判断这些字符串中是否存在其中的一个字符串是另外一个字符串的前缀.. 如果是,输出Set .. is not immediately decodable 否则输出Set . ...

  6. 飘逸的python - yield简明教程

    发现还有非常多人对yield不理解,云里雾里,于是试着用文字表述. 仅仅要函数含有yield语句,它就返回一个生成器.所以我们与其把其看成函数定义,不如看作是生成器定义.函数用return返回,而生成 ...

  7. UDP 通信

    import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; public ...

  8. Linux源文件夹结构呈现

    1.arch文件夹: - 相关的存储在不同平台上的代码,每个平台都采用了不同的文件夹来区分. ******Alpha平台 ******Arm平台 ******Arv32平台 ******X86平台 2 ...

  9. shu_1241 邮局位置问题

    http://202.121.199.212/JudgeOnline/problem.php?cid=1078&pid=5 分析: 由于题目中的距离是折线距离,所以能够分别考虑两个方向.又x方 ...

  10. VSTO学习笔记(七)基于WPF的Excel分析、转换小程序

    原文:VSTO学习笔记(七)基于WPF的Excel分析.转换小程序 近期因为工作的需要,要批量处理Excel文件,于是写了一个小程序,来提升工作效率. 小程序的功能是对Excel进行一些分析.验证,然 ...