图片资源获取的5种姿势
程序中,图片的存在是必不可少的。涉及的是程序颜值问题。
在Android中,图片是怎么获取的呢?
我们根据图片获取方式的不同,暂分为五种:
1、从本地获取,比如图片存在SD卡中,在程序中获取该图片;
2、从项目中获取,比如图片已经加载到项目文件中,从项目中获取;
3、从网络获取,你的Android是可以联网的,根据图片的地址,从网络获取;
4、从相册获取,这个可以算是本地的一种细分。相册在android中,我们理解为一种组件;
5、拍照后获取,拍照后,得到你拍的照片;
针对以上5种获取姿势,我们根据各自的情况,解释如何获取她们的引用:
先把基础工作准备好,在布局文件中,把我们需要的按钮和显示图片的imageView设置好:
<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"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context=".MainActivity" >
<Button
android:id="@+id/chose"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="选择相册图片" />
<Button
android:id="@+id/take_photo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="拍照" />
<Button
android:id="@+id/local_project_photo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="项目中的图片" />
<Button
android:id="@+id/local_photo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="已知名称的本地图片" />
<Button
android:id="@+id/net_photo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="已知名称的网络图片" />
<ImageView
android:id="@+id/img"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerInside"
>
</ImageView>
</LinearLayout>
本地获取图片资源
做这个操作,我们需要知道本地图片的路径以及名称。然后从本地文件中获取到这个资源,并显示在界面上的imageview中。
假设,在android设备中有个图片地址如下:/storage/emulated/0/Penguins.jpg(在SD卡根目录下)。那代码可以这么写:
1、根据路径获取bitmap格式的图片:
/**
* 本地图片获取后,转为bitmap格式
* @param path 路径
* @return Bitmap格式
* @throws FileNotFoundException
*/
private Bitmap getLocalImg(String path) throws FileNotFoundException
{
FileInputStream inputStream=new FileInputStream(path);
Bitmap bitmap=BitmapFactory.decodeStream(inputStream);
return bitmap;
}
2、将bitmap格式图片显示在界面上:
/**
* 本地SD卡上资源的引用
* @param path 路径
*/
private void showLocalImg(String path) {
try {
Bitmap bitmap=getLocalImg(path);
imageView.setImageBitmap(bitmap);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
3、调用第2步的函数,显示图片:
showLocalImg("/storage/emulated/0/Penguins.jpg");
通过以上三步即可将指定的本地图片显示在界面上。
简单的说就是,根据路径获取流,将流解析成bitmap格式图片,将bitmap格式图片显示。
注意,做这个操作需要赋予读取SD卡的权限。
项目中获取图片资源
这个方法应该是我们平常使用很频繁的方法,直接从项目的图片文件中取图片资源。以我们每个项目中默认存在的图片ic_launcher为例,代码如下:
/**
* 项目中图片资源的引用
*/
private void showProjectImg() {
imageView.setImageResource(R.drawable.ic_launcher);
}
网络中获取图片资源
这个的原理其实与本地获取图片资源类似,区别在于这个是在网络端的。我们需要联网,并向服务端请求图片。核心的代码如下:
/**
* 网络图片获取,并转为bitmap格式
* @param url 网络路径
* @return bitmap格式
* @throws IOException
*/
private Bitmap getNetImg(String url) throws IOException
{
Bitmap bitmap=null;
URL myuUrl=new URL(url);
HttpURLConnection httpURLConnection=(HttpURLConnection)myuUrl.openConnection();
if(httpURLConnection!=null)
{
httpURLConnection.setDoInput(true);
httpURLConnection.setReadTimeout(8000);
httpURLConnection.setRequestMethod("GET");
httpURLConnection.connect();
if(httpURLConnection.getResponseCode()==200)
{
InputStream inputStream= httpURLConnection.getInputStream();
bitmap=BitmapFactory.decodeStream(inputStream);
inputStream.close();
}
httpURLConnection.disconnect();
return bitmap;
}
return null;
}
看代码其实很简单,设置网络请求参数——连接网络——根据传入的URL,获取流——将流转为bitmap格式——图片显示(参考本地获取图片资源)。
此处,可以用该网络图片测试:https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo/bd_logo1_31bdc765.png。这是一张百度logo图片。
以上操作后,该logo显示在界面上。
该操作时,需要设置网络权限,如果URL中有空格或者汉字时,也需要额外处理,这里就暂不展开了。
相册中获取图片资源
这个方法,在android上是非常常用的。比如,你在android设备上点击按钮,想打开相册,选择你想要的一张图片,用来做头像、背景等。
但是,在选择好图片前,你是不知会选哪张图片的。因此,你也没办法定好文件路径。怎么办?
这里就用到Intent了。用意图打开相册、用startActivityForResult方法返回选择、显示选择好的图片。这就是它的逻辑,具体代码如下:
1、Intent打开相册
//相册图片选择
private void showChoseImg() {
Intent intent=new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
startActivityForResult(intent, CHOSETAG);
}
2、显示选择的图片
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
Uri uri=null;
switch (requestCode) {
case CHOSETAG:
if(resultCode==RESULT_OK)
{
uri=data.getData();
String path=getPathFromUri(uri);
imageView.setImageURI(Uri.fromFile(new File(path)));
}
break;
default:
break;
}
super.onActivityResult(requestCode, resultCode, data);
}
注意这里还有个getPathFromUri函数,它做的是将uri格式的资源定位符转为我们平常的路径,如下:
/**
* 将Uri转为String格式的路径
* @param uri 资源定位地址
* @return String格式路径
*/
private String getPathFromUri(Uri uri) {
String path="";
String[] projection={MediaStore.Images.Media.DATA};
ContentResolver cResolver=getContentResolver();
Cursor cursor= cResolver.query(uri, projection, null, null, null);
if(cursor!=null)
{
cursor.moveToFirst();
path=cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
cursor.close();
}
return path;
}
这个函数,用到了我们的ContentProvider中的内容,根据uri和固定列(_data)查找路径名。
经过以上的操作,你也成功的把图片显示在界面上了。
拍照获取图片资源
这个很容易理解,android极大部分设备都是有摄像头的,我们也经常拍了照片,就用这照片作为我们的头像等等。那具体是怎么实现的呢?
用Intent的特定action打开摄像头——拍照——拍照完成后,将临时的照片,存储本地——从本地取图片显示界面。
流程主要如上,代码如下:
//拍照
private void showTakePhotoImg()
{
//定义一个临时文件的路径
File file=new File(Environment.getExternalStorageDirectory(), "test.jpg");
//格式改为Uri格式
Uri uri=Uri.fromFile(file);
Intent intent=new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
//拍照后临时存储地址
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
startActivityForResult(intent, TAKETAG);
}
同样的,我们也要有个处理图片返回的地方:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
Uri uri=null;
switch (requestCode) {
case TAKETAG:
if(resultCode==RESULT_OK)
{
try {
Bitmap bitmap= getLocalImg(Environment.getExternalStorageDirectory()+"/test.jpg");
imageView.setImageBitmap(bitmap);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
break;
default:
break;
}
super.onActivityResult(requestCode, resultCode, data);
}
通过以上简单的两步,我们也成功的显示了拍照图片。
但,有时候,你拍照得到的图片对你来说不适合,太大了,不合适做头像,怎么办?
我们可以在这个基础上对图片进行裁剪:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
Uri uri=null;
switch (requestCode) {
case TAKETAG:
if(resultCode==RESULT_OK)
{
cropPicture(Uri.fromFile(new File(Environment.getExternalStorageDirectory()+"/test.jpg")));
/*
try {
Bitmap bitmap= getLocalImg(Environment.getExternalStorageDirectory()+"/test.jpg");
imageView.setImageBitmap(bitmap);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
*/
}
break;
case CROPTAG:
if(resultCode==RESULT_OK)
{
Bitmap bitmap;
try {
bitmap = getLocalImg(Environment.getExternalStorageDirectory()+"/test.jpg");
imageView.setImageBitmap(bitmap);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
break;
default:
break;
}
super.onActivityResult(requestCode, resultCode, data);
}
其中涉及的函数,cropPicture写法如下:
/**
* 相片裁剪
* @param uri 相片地址Uri格式
*/
private void cropPicture(Uri uri)
{
Intent intent=new Intent("com.android.camera.action.CROP");
intent.setDataAndType(uri, "image/*");
intent.putExtra("crop", "true");
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(Environment.getExternalStorageDirectory()+"/test.jpg")));
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
intent.putExtra("outputX", 300);
intent.putExtra("outputY", 300);
startActivityForResult(intent, CROPTAG);
}
我们给图片设定了一个裁剪的初始设置,X,Y方向比例相等,长度相等。你可以在照片拍摄好后,在这个基础上调整想要裁剪的图片的大小。
得到一个你想要的图片,确定,就可以在界面上显示出来了。
以上,是我们获取图片资源的5种方式,简约。