最近实现了一个使用最新推出的CardView和RecyclerView实现列表功能的Demo,
接下来一一介绍:
1.首先介绍我使用了哪些工具
(1)LeanCloud的存储功能
(2)RecyclerView
(3)CardView
(4)ImageLoader
2.既然是列表,所以它里面的实现方式和ListView差不多,
一个(含有RecyclerView)主界面布局(activity_fm_item.xml),
一个Adapter(RecyclerView.Adapter),在这先把布局文件贴出来:
(1)activity_fm.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:background="@color/white">
<RelativeLayout android:layout_width="match_parent" android:layout_height="56dp" android:background="@color/basicColor_two">
<ImageButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/ic_arrow_back_black_24dp" android:id="@+id/fm_backBtn" android:layout_alignParentLeft="true" android:layout_centerVertical="true" android:layout_marginLeft="8dp"/>
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:gravity="center" android:text="用心聆听世界的声音" android:textSize="20sp" android:textColor="@color/white" />
</RelativeLayout>
<android.support.v7.widget.RecyclerView android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/fm_recyclerView" >
</android.support.v7.widget.RecyclerView>
</LinearLayout>
第一个RelativeLayout的布局实现的是ActionBar的布局,第二个里是RecyclerView的布局
(2)activity_fm_item.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="360dp" android:background="@color/white">
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_alignParentTop="true" android:layout_marginBottom="16dp" android:textColor="@color/txt_low" android:id="@+id/fm_date"/>
<android.support.v7.widget.CardView android:layout_width="match_parent" android:layout_height="296dp" android:layout_marginStart="16dp" android:layout_marginEnd="16dp" android:layout_below="@+id/fm_date" android:background="@color/white" app:cardCornerRadius="8dp" app:cardElevation="16dp" android:id="@+id/view">
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical">
<FrameLayout android:layout_width="match_parent" android:layout_height="148dp" >
<ImageView android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/fm_cardBack" android:scaleType="fitXY"/>
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal|bottom" android:layout_marginBottom="16dp" android:textColor="@color/white" android:textSize="24sp" android:id="@+id/fm_title"/>
</FrameLayout>
<RelativeLayout android:layout_width="match_parent" android:layout_height="148dp">
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/fm_summary" android:layout_alignParentTop="true" android:layout_marginTop="16dp" android:textSize="16sp" />
</RelativeLayout>
</LinearLayout>
</android.support.v7.widget.CardView>
</RelativeLayout>
应该根据Material Design的设计理念对cardView进行布局,比如标题的text的大小,正文的Text的大小等等,可以去官网中查一查
3.设置一个ItemBean,对数据进行封装
public class fm_itemBean {
String fm_imageUrl;
String fm_title;
String fm_summary;
String fm_date;
public String getFm_date() {
return fm_date;
}
public void setFm_date(String fm_date) {
this.fm_date = fm_date;
}
public fm_itemBean(String fm_imageUrl, String fm_title, String fm_summary, String fm_date) {
this.fm_imageUrl = fm_imageUrl;
this.fm_title = fm_title;
this.fm_summary = fm_summary;
this.fm_date = fm_date;
}
public String getFm_imageUrl() {
return fm_imageUrl;
}
public void setFm_imageUrl(String fm_imageUrl) {
this.fm_imageUrl = fm_imageUrl;
}
public String getFm_title() {
return fm_title;
}
public void setFm_title(String fm_title) {
this.fm_title = fm_title;
}
public String getFm_summary() {
return fm_summary;
}
public void setFm_summary(String fm_summary) {
this.fm_summary = fm_summary;
}
}
4.实现对于一个列表必须的Adapter--RecyclerView.Adapter,
从该Adapter看出Goolge已经开始强制使用ViewHolder模式了。介绍一下该Adapter所需要复写的方法--在
onCreateViewHolder中进行创建ViewHolder(相当于初始化控件--我是这么理解的),
getItemCount返回的是数据的数量,还需创建一个内部类来继承ViewHolder
public class MyRecyclerAdapter_fm extends RecyclerView.Adapter<MyRecyclerAdapter_fm.MyViewHolder>{
private LayoutInflater mInflater;
private List<fm_itemBean> mDatas=new ArrayList<>();
MyImageLoader myImageLoader;
public MyRecyclerAdapter_fm(Context context, List<fm_itemBean> mDatas) {
this.mDatas = mDatas;
mInflater=LayoutInflater.from(context);
myImageLoader=new MyImageLoader();
}
/* 实现接口的三步走:1.定义一个接口,在定义里写出对方法的定义 2.实例化一个接口对象,通过set方法将接口设置进来 3.在相应的地方使用(onBindViewHolder中) */
private OnItemClickListener onItemClickListener;
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
interface OnItemClickListener{
void onItemClick(View view,int position);
void onItemLongClick(View view ,int position);
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view=mInflater.inflate(R.layout.activity_fm_item,parent,false);
return new MyViewHolder(view);
}
@Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {
//给每个控件设置数据
holder.fm_txt_title.setText(mDatas.get(position).fm_title);
holder.fm_txt_summary.setText(mDatas.get(position).fm_summary);
holder.fm_date.setText(mDatas.get(position).fm_date);
String mUrl=mDatas.get(position).fm_imageUrl;
//给每个ImageView根据url设置相应的图片,使用的是ImageLoader方式。还可以使用多线程和AsyncTask
myImageLoader.setBitmapFromUrl(holder.fm_image_cardBack,mUrl);
// new ImageLoader().showImageByThread(holder.fm_image_cardBack,mUrl);
//实现点击事件的第三部
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (onItemClickListener!=null)
onItemClickListener.onItemClick(holder.itemView,position);
}
});
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
if (onItemClickListener!=null)
onItemClickListener.onItemLongClick(holder.itemView,position);
return false;
}
});
}
@Override
public int getItemCount() {
return mDatas.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder{
ImageView fm_image_cardBack;//CardView的背景
TextView fm_txt_title;//CardView的title
TextView fm_txt_summary;//cardView的summary
TextView fm_date;//每个CardView的时间
public MyViewHolder(View itemView) {
super(itemView);//初始化相应的控件,即item中所包含的控件
fm_image_cardBack= (ImageView) itemView.findViewById(R.id.fm_cardBack);
fm_txt_title= (TextView) itemView.findViewById(R.id.fm_title);
fm_txt_summary= (TextView) itemView.findViewById(R.id.fm_summary);
fm_date= (TextView) itemView.findViewById(R.id.fm_date);
}
}
}
5.在将url转成相应的图片使用了ImageLoader的模式
ImageLoader需要两个东西 (1)BitmapCache(使用LruCache)
(2)ImageLoaderListener
public class BitmapCache implements ImageLoader.ImageCache {
public LruCache<String ,Bitmap> cache;//使用LruCache
public int max=10*1024*1024;//缓存的大小
public BitmapCache(){
//初始化LruCache ,max为缓存的大小,sizeOf方法返回的是bitmap的大小
cache=new LruCache<String, Bitmap>(max){
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getRowBytes()*value.getRowBytes();
}
};
}
@Override
public Bitmap getBitmap(String s) {
return cache.get(s);
}
@Override
public void putBitmap(String s, Bitmap bitmap) {
cache.put(s,bitmap);
}
}
ImageLoader:将根据图片的url给相应的控件设置url所对应的图片
public class MyImageLoader {//ImageLoader需要三个东西,一个是Queues,第二个是ImageCahe,第三个是Listener
BitmapCache mBitmapCache=new BitmapCache();
public void setBitmapFromUrl(ImageView imageView,String url){
com.android.volley.toolbox.ImageLoader mImageLoader=new ImageLoader(MyApplication.getQueues(),mBitmapCache);
ImageLoader.ImageListener listener=ImageLoader.getImageListener(imageView, R.drawable.touxiang,R.drawable.touxiang);
mImageLoader.get(url,listener);
}
}
Application:(还需要在AndroidManifest.xml中设置application的
:name=.MyApplication)
public class MyApplication extends Application {
public static RequestQueue queues;
@Override
public void onCreate() {
super.onCreate();
queues= Volley.newRequestQueue(getApplicationContext());
AVOSCloud.initialize(this,AVCloudKey);//初始化AVcloud
}
public static RequestQueue getQueues() {
return queues;
}
}
接下来是主程序:在主程序中使用了Leancloud,因为我将所有的数据都放在了上面,并不是通过Json数据解析得来的
public class Activity_fm extends AppCompatActivity {
List<fm_itemBean> mDatas;
RecyclerView mRecyclerView;
ImageButton backBtn;
MyRecyclerAdapter_fm adapterFm;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fm);
initView();
initDatas();
}
private void initDatas() {
mDatas=new ArrayList<>();
AVQuery<AVObject> query=new AVQuery<>("FM");//从Leancloud的fm表中查询数据
query.findInBackground(new FindCallback<AVObject>() {
@Override
public void done(List<AVObject> list, AVException e) {//遍历FM 表
for (AVObject avObject:list){
//返回相应字段的值
String title= (String) avObject.get("title");
String summary= (String) avObject.get("summary");
String imageUrl= (String) avObject.get("imageUrl");
String date= (String) avObject.get("date");
//fm_itemBean实现数据的封装
fm_itemBean itemBean_fm=new fm_itemBean(imageUrl,title,summary,date);
mDatas.add(itemBean_fm);
adapterFm.notifyDataSetChanged();//此句不加会导致RecyclerView显示不出来
}
}
});
//给每个item设置点击事件
adapterFm=new MyRecyclerAdapter_fm(Activity_fm.this,mDatas);
adapterFm.setOnItemClickListener(new MyRecyclerAdapter_fm.OnItemClickListener() {
@Override
public void onItemClick(View view, int position) {
Intent intent=new Intent(Activity_fm.this,Activity_fm_content.class);
String title=mDatas.get(position).fm_title;
intent.putExtra("title",title);
startActivity(intent);
}
@Override
public void onItemLongClick(View view, int position) {
}
});
mRecyclerView.setAdapter(adapterFm);
//实现返回按钮
backBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent=new Intent(Activity_fm.this,MainActivity.class);
startActivity(intent);
}
});
}
//初始化控件
private void initView() {
mRecyclerView= (RecyclerView) findViewById(R.id.fm_recyclerView);
backBtn= (ImageButton) findViewById(R.id.fm_backBtn);
mRecyclerView.setLayoutManager(new LinearLayoutManager(Activity_fm.this));
}
}