最近学习一个仿微信的即时通信,最后在关于获取assets目录下的表情图片时发现一点小问题,不知道怎么去获取,后来看了看相关的博客,实现了自己的思路,那么这里就来看看我是怎么一步一步来填坑的。
但是现在资源文件是这样的:
所以我们需要将所有的图片加载到一个集合,因为效果图里面的GridView适配器需要数据源。不过读取assets目录下面的资源文件需要提供路径,我们可以通过AssetManager类来访问这些文件。 我们先看看两个API(看不懂没有关系,后面马上就要用了,测试几次就明白了):
1.文件读取方式
AssetManager.open(String filename),返回的是一个InputSteam类型的字节流,这里的filename必须是文件,而不能是文件夹,AssetManager打开资源文件的open方法是一个重载方法,可以添加一个打开方式的int参数,根据参数不同可做相应操作。具体请看官方文档http://web.mit.edu/clio/MacData/afs/sipb/project/android/docs/reference/android/content/res/AssetManager.html
2.资源文件是可以存在文件夹以及子目录
public final String[]list(String path),返回当前目录下面的所有文件以及子目录的名称。可以通过递归遍历整个文件目录,实现所有资源文件的访问。String[] Array of strings, one for each asset. These file names are relative to ‘path’. You can open the file by concatenating ‘path’ and a name in the returned string (via File) and passing that to open().
知道API了,我们接下来获取所有emoji文件夹下面的表情图片,并将第一张图片加载到一个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:background="#ffffff"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:id="@+id/imageview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher"/>
LinearLayout>
Java代码:
package com.example.test;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.util.Log;
import android.widget.ImageView;
public class MainActivity extends Activity {
private ImageView ivimage;
private List emojidata = new ArrayList();
int i = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ivimage = (ImageView) findViewById(R.id.imageview);
deepFile(this,"emoji");
Log.i("tag", "图片数量:"+emojidata.size());
}
public void deepFile(Context ctxDealFile, String path) {
try {
//获取指定目录下的所有文件名称
String str[] = ctxDealFile.getAssets().list(path);
//emoji文件夹下面有两个文件,所有该数组的长度为1,str[0]是default文件夹,str[1]是xml文件;
if (str.length > 0) {//如果是目录
for (String string : str) {
path = path + "/" + string;
Log.i("tag", "路径:"+path+"文件长度:"+str.length);
deepFile(ctxDealFile, path);
}
} else {//如果是文件
//非指定类型的话直接返回
if(!path.endsWith(".png")){
return;
}
Log.i("tag", "路径:"+path+str.length);
i++;
if(i==1)
ivimage.setImageBitmap(getImageFromAssetsFile(path));
emojidata.add(getImageFromAssetsFile(path));
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 从Assets中读取图片
* @param fileName
* @return
*/
private Bitmap getImageFromAssetsFile(String fileName)
{
Bitmap image = null;
AssetManager am = getResources().getAssets();
try
{
InputStream is = am.open(fileName);
image = BitmapFactory.decodeStream(is);
is.close();
}
catch (IOException e)
{
e.printStackTrace();
}
return image;
}
}
最后我们得到了所有的图片,一共一百二十五张,并把第二张图片显示出来了!
那么我们接着加载预先收藏的表情图片看看有什么问题?
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ivimage = (ImageView) findViewById(R.id.imageview);
String[] listFileSticker = null;
try {
//获取第一层的文件集合
listFileSticker = this.getAssets().list("sticker");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//加载第二个文件夹的图片
deepFile(ctxDealFile,listFileSticker[1]);
Log.i("tag", "图片数量:"+emojidata.size());
}
这里说明我们根本没有得到图片,问题是出在哪里呢?
也就是说我们只能通过路径来加载文件夹下面的图片,直接调用文件是不行的!
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ivimage = (ImageView) findViewById(R.id.imageview);
deepFile(ctxDealFile,"sticker/lt");//路径:"sticker/lt"
Log.i("tag", "图片数量:"+emojidata.size());
}
如果我们不是加载文件夹,而是直接加载assets下面的图片呢?
很简单:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ivimage = (ImageView) findViewById(R.id.imageview); ivimage.setImageBitmap(getImageFromAssetsFile("ajmd_s_pressed.png"));
}
/**
* 从Assets中读取图片
* @param fileName
* @return
*/
private Bitmap getImageFromAssetsFile(String fileName)
{
Bitmap image = null;
AssetManager am = getResources().getAssets();
try
{
InputStream is = am.open(fileName);
image = BitmapFactory.decodeStream(is);
is.close();
}
catch (IOException e)
{
e.printStackTrace();
}
return image;
}
源码比较简单,已经写出来了,最后还是把工具类贴出来:
package com.weixing.myofwechat.utils;
/**
* 管理地址的类
* @author Administrator
*
*/
public class Const
{
/**
* 需要加载Assets文件里面的emoji文件
*/
public static final String ASSETS_TYPE_EMOJI = "emoji";
/**
* 需要加载Assets文件里面的ajmd文件
*/
public static final String ASSETS_TYPE_AJMD = "sticker/ajmd";
/**
* 需要加载Assets文件里面的lt文件
*/
public static final String ASSETS_TYPE_LT = "sticker/lt";
/**
* 需要加载Assets文件里面的xxy文件
*/
public static final String ASSETS_TYPE_XXY = "sticker/xxy";
}
package com.weixing.myofwechat.utils;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.util.Log;
/**
* 工具类
* @author Administrator
*
*/
public class Utis
{
private static String tag = "com.weixing.myofwechat.utils";
private static List bitmapData = new ArrayList();
/**
* 加载assets下指定文件的Bitmap集合
* @param context
* @param path
* @return
*/
public static List scanSpecifyFile(Context context,String path)
{
try {
String str[] = context.getAssets().list(path);
if (str.length > 0) {//如果是目录
File file = new File("/data/" + path);
file.mkdirs();
for (String string : str)
{
path = path + "/" + string;
System.out.println("zhoulc:\t" + path);
scanSpecifyFile(context, path);
path = path.substring(0, path.lastIndexOf('/'));
}
} else
{//如果是文件
if(!path.endsWith(".png"))
{ //如果不是指定的文件类型
return bitmapData;
}
Log.i("tag", "path:"+path+str.length);
bitmapData.add(getBitmapFromAssetsFile(context,path));
}
} catch (IOException e)
{
e.printStackTrace();
}
return bitmapData;
}
/**
* 从Assets中读取图片位图
* @param path
* @return
*/
private static Bitmap getBitmapFromAssetsFile(Context context,String fileName)
{
Bitmap image = null;
AssetManager am = context.getResources().getAssets();
try
{
InputStream is = am.open(fileName);
image = BitmapFactory.decodeStream(is);
is.close();
}
catch (IOException e)
{
e.printStackTrace();
}
return image;
}
/**
* 处理失真图形生成圆形头像,
* 失真图形指如资源文件生成的Bitmap
* @param context 上下文对象
* @param idsource ID资源
* @param min 圆形头像半径
* @return Bitmap
*/
public static Bitmap createCircleImage(Context context,int idsource, int min)
{
Bitmap source = BitmapFactory.decodeResource(context.getResources(), idsource);
final Paint paint = new Paint();
paint.setAntiAlias(true);
// 注意一定要用ARGB_8888
Bitmap target = Bitmap.createBitmap(min, min, Config.ARGB_8888);
Bitmap src = Bitmap.createScaledBitmap(source, min, min, false);
// 产生一个同样大小的画布
Canvas canvas = new Canvas(target);
// 首先绘制圆形
canvas.drawCircle(min / 2, min / 2, min / 2, paint);
// 使用SRC_IN
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
// 绘制图片
canvas.drawBitmap(src, 0, 0, paint);
return target;
}
}
参考文章:
http://blog.sina.com.cn/s/blog_5da93c8f0100wvcr.html
http://my.oschina.net/zhoulc/blog/118693