1.布局框架
包类 | 功能 |
Adapter | 放置适配器 |
UI | 显示页面(activity) |
Dao | Music 实体类 |
Listener | 接口类,用于数据回调 |
BIZ | 业务类,只提供方法名 |
Util | 工具类,实现业务类中的方法 |
2.思路详解
**需要设置一个ListView 中要添加的每一个音乐的布局,可以自己设计,里面所需要的参数,可以通过我们的实体类进行设置
自定义一个MusicAdapter,继承自baseAdapter,用于实现把我们从数据库中查找到的数据添加到ListView 中去,数据的来源是通过异步加载来回调数据的,开始时候执行MusicAdapter,此时是没有数据的,然后我们通过Util工具类中的异步加载方式进行加载数据,当数据全部得到后,会通过OnLoadMusicFinish接口中的一个方法进行回传数据,及在MainAction中写该方法,当数据来了后,对adapter进行更新。
对于Util中的查询本地音乐的专辑图片,在数据库中的:缩略图是以二进制形式存储的。
把该图对应的byte[]值通过MediaMetadataRetriever获取,
MediaMetadataRetriever类提供了一个统一的接口用于从一个输入媒体文件中取得帧和元数据,获得缩略图,从该歌曲的路径中获取。然后通过BitmapFactory的方法获取:
MediaMetadataRetriever retriever = new MediaMetadataRetriever();// 能够获取多媒体文件元数据的类
retriever.setDataSource(filePath); // 设置数据源
byte[] embedPic = retriever.getEmbeddedPicture(); // 得到字节型数据
bitmap = BitmapFactory.decodeByteArray(embedPic, 0, embedPic.length); // 转换为图片
然后对图片进行切图:
切图圆的半径我们选择该图片宽高中较小的那个的一半
在这里我们使用的是PorterDuffXfermode的方法
通过图片详述我们可以中的,每一种模式是如何对矩形和圆的相交部分如何处理显示的
PorterDuffXfermode这个属性要设置给paint:paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
然后就是单位换算的问题
把一个数,转换为dp,sp等:
strokeWidth = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 2, context.getResources().getDisplayMetrics());
描边,画图方法中:
无非就是对canvas paint 设置各种属性,其中要注意的是
宽高以及单位的转换等等的问题,
** 各模块的功能实现
MainActivity
初始化控件
回调异步加载方法获得数据
Music
定义一首音乐该有的属性,名字,路径,专辑,专辑图片,作曲人
时长,等等
MusicAdapter
继承BaseAdapter
Context
Resource(要显示在哪个布局上的资源ID)
list(要显示的时间来源 如:List list)
使用viewHolder进行优化
BIZ 业务类
:构造方法要初始化一个context
:asnycLoadMusic 方法:
asnycLoadMusic(OnLoadBitmapFinish finish){
Util.asnycLoadMusic(context,finish);
}
OnLoadBitmapFinish
public interface OnLoadBitmapFinish {
void OnLoadFinish(List list);
}
Util工具类,实现业务类的方法
MainActivity代码:
public class MainActivity extends Activity {
private ListView listview;
List list;
MusicAdapter adapter;
Biz biz;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
biz=new Biz(this);
list=new ArrayList();
listview=(ListView) findViewById(R.id.listview);
adapter=new MusicAdapter(this, R.layout.music_list, list);
listview.setAdapter(adapter);
}
@Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
biz.asnycLoadMusic(new OnLoadBitmapFinish() {
@Override
public void OnLoadFinish(List<Music> list) {
// TODO Auto-generated method stub
adapter.addAll(list,true);
}
});
}
}
Music 实体类
需要什么信息,可以自己去定义
public class Music {
public Music() {
// TODO Auto-generated constructor stub
}
private String name;
private String path;
private Bitmap photo;
private int time;
private String album;
public String getName() {
return name;
}
@Override
public String toString() {
return "Music [name=" + name + ", path=" + path + ", photo=" + photo
+ ", time=" + time + ", album=" + album + "]";
}
public void setName(String name) {
this.name = name;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public Bitmap getPhoto() {
return photo;
}
public void setPhoto(Bitmap photo) {
this.photo = photo;
}
public int getTime() {
return time;
}
public void setTime(int time) {
this.time = time;
}
public String getAlbum() {
return album;
}
public void setAlbum(String album) {
this.album = album;
}
BIZ 业务类
public class Biz {
private Context context;
public Biz(Context context) {
// TODO Auto-generated constructor stub
this.context=context;
}
public void asnycLoadMusic(OnLoadBitmapFinish finish){
Util.asnycLoadMusic(context,finish);
}
}
MusicAdapter 类
public class MusicAdapter extends BaseAdapter {
private Context context;
private int resource;
private List list;
Biz biz;
public MusicAdapter(Context context,int resource,List list) {
// TODO Auto-generated constructor stub
this.context=context;
this.resource=resource;
this.list=list;
biz=new Biz(context);
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return list.size();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return list.get(position);
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
ViewHolder vh=null;
if(convertView==null){
convertView=View.inflate(context, resource, null);
vh=new ViewHolder();
vh.img=(ImageView) convertView.findViewById(R.id.photo_image);
vh.t1=(TextView) convertView.findViewById(R.id.author);
vh.t2=(TextView) convertView.findViewById(R.id.zhuanji);
vh.t3=(TextView) convertView.findViewById(R.id.time);
convertView.setTag(vh);
}
else{
vh=(ViewHolder) convertView.getTag();
}
Music music=(Music) getItem(position);
vh.img.setImageBitmap(music.getPhoto());
vh.t1.setText(music.getName());
vh.t2.setText(music.getAlbum());
vh.t3.setText(""+music.getTime());
return convertView;
}
class ViewHolder{
ImageView img;
TextView t1,t2,t3;
}
public void addAll(List<Music> list2, boolean b) {
// TODO Auto-generated method stub
if(b){
list.clear();
}
list.addAll(list2);
notifyDataSetChanged();
}
}
OnLoadBitmapFinish接口
public interface OnLoadBitmapFinish {
void OnLoadFinish(List list);
}
Util详细代码:
public class Util {
public Util() {
}
public static List getMusic(Context context) {
// TODO Auto-generated method stub
List musics=new ArrayList();
ContentResolver cr = context.getContentResolver();
Cursor cursor;
cursor=cr.query(
Media.EXTERNAL_CONTENT_URI,
new String[]{Media.TITLE,Media.ALBUM_ID,Media.DATA,Media.ARTIST,Media.DURATION},
null,null,null);
while(cursor.moveToNext()){
Music music=new Music();
music.setAlbum(cursor.getString(0));
music.setPath(cursor.getString(2));
music.setName(cursor.getString(3));
music.setTime(cursor.getInt(4));
music.setPhoto(createAlbumArt(context,cursor.getString(2)));
musics.add(music);
}
Log.i(“TAG”, musics.toString()+”\n”);
cursor.close();
return musics;
}
public static void asnycLoadMusic(final Context context, final OnLoadBitmapFinish finish) {
// TODO Auto-generated method stub
new AsyncTask