1. Android
来源:互联网 发布:双系统windows连不上网 编辑:程序博客网 时间:2024/06/14 06:52
一、RecyclerView 普通列表实现
RecyclerView 可以实现 ListView 的效果,它通过使用 LayoutManager 来确定每一个 item 的排列方式,同时为增加和删除项目提供默认的动画效果。
1. 列表显示
MainActivity:初始化数据并设置适配器
public class MainActivity extends AppCompatActivity { private RecyclerView main_recycler_view; private List<String> mData; @Override protected void onCreate(Bundle savedInstanceState) { // ... initData(); // 设置自定义适配器 main_recycler_view.setAdapter(new RecyclerAdapter(this, mData)); // 设置布局管理器 main_recycler_view.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)); // 设置动画 main_recycler_view.setItemAnimator(new DefaultItemAnimator()); // 设置分割线 main_recycler_view.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL)); } // 初始化数据 private void initData() { mData = new ArrayList<>(); for (int i = 'A'; i <= 'z'; i++) { mData.add("" + (char) i); } }}
Item 布局文件
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="80dp"> <LinearLayout android:layout_width="360dp" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:id="@+id/item_text_title" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="XXX" android:textSize="24sp" android:textColor="@android:color/black" android:padding="5dp"/> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingLeft="5dp" android:text="content" android:textSize="16sp" android:textColor="@android:color/black"/> </LinearLayout></LinearLayout>
RecyclerAdapter:自定义适配器
// 设置 RecyclerAdapter 继承自 RecyclerView.Adapter<RecyclerAdapter.ViewHolder>public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.ViewHolder> { private Context mContext; private List<String> mData; // 构造方法,传入上下文和列表数据 public RecyclerAdapter(Context context, List<String> data) { this.mContext = context; this.mData = data; } // 加载 Item 的布局项 @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = View.inflate(mContext, R.layout.item_recycler_view, null); return new ViewHolder(view); } @Override public void onBindViewHolder(ViewHolder holder, int position) { // 获得当前数据对象并设置显示 String data = mData.get(position); holder.item_text_title.setText(data); } @Override public int getItemCount() { return mData.size(); } // ViewHolder 内部类 class ViewHolder extends RecyclerView.ViewHolder { TextView item_text_title; public ViewHolder(View itemView) { super(itemView); item_text_title = (TextView) itemView.findViewById(R.id.item_text_title); } }}
主页面布局以及内容项布局可以按自己的喜好设置。以下是 LayoutManager 进行各种不同设置时的运行结果。
2. Item 点击事件
有两种方法可以实现 Item 的点击事件,且都可以传入数据。
第一种,改写 ViewHolder 内部类,为其添加点击事件。
ViewHolder 类实现 OnclickListener 接口,itemView 设置该点击事件。
class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { // 在 bindData() 中传入数据(这里只是 String,一般为自定义数据对象) private String mData; // 视图对象 private TextView item_text_title; public ViewHolder(View itemView) { super(itemView); // 为 itemView 设置点击事件 itemView.setOnClickListener(this); item_text_title = (TextView) itemView.findViewById(R.id.item_text_title); } // 将点击的数据对象传入并设置视图对象的显示 public void bindData(String data) { mData = data; item_text_title.setText(mData); } @Override public void onClick(View v) { Toast.makeText(mContext, "你点击了" + mData, Toast.LENGTH_SHORT).show(); }}
之后在 adapter 的 onBindViewHolder(…) 中调用新添加的 bindData() 方法。
@Overridepublic void onBindViewHolder(ViewHolder holder, int position) { holder.bindData(mData.get(position));}
第二种,添加接口,使外部可以回调内部的点击事件。
首先在自定义的 RecyclerAdapter 中添加一个接口以及对应方法。
private OnMyItemClickListener listener;interface OnMyItemClickListener { void onItemClick(int position);}// 用于外部设置 RecyclerAdapter 中的接口,重写其方法。public void setOnMyItemClickListener(OnMyItemClickListener l) { this.listener = l;}
改写 ViewHolder 内的构造方法。
public ViewHolder(View itemView) { super(itemView); item_text_title = (TextView) itemView.findViewById(R.id.item_text_title); itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (listener != null) { listener.onItemClick(getLayoutPosition()); } } });}
在主页面中为 RecyclerAdapter 设置接口,重写 onItemClick() 方法。
adapter.setOnMyItemClickListener(new RecyclerAdapter.OnMyItemClickListener() { @Override public void onItemClick(int position) { Toast.makeText(MainActivity.this, mData.get(position) + " Clicked!", Toast.LENGTH_SHORT).show(); }});
3. 添加和删除 Item
在 adapter 中加入两个函数:addItem(position) 以及 removeItem(position)
在函数中,先对数据集合进行操作,再通知适配器数据已经更改。
注:这里使用 notifyItemInserted(position) 与 notifyItemRemoved (position) 通知适配器,而非 ListView 中常用的 adapter.notifyDataSetChanged()
// 添加 Item 项public void addItem(int position) { mData.add(position, "XXX"); notifyItemInserted(position);}// 删除 Item 项public void removeItem(int position) { mData.remove(position); notifyItemRemoved(position);}
设置 ToolBar,加入“添加”以及“删除”两个按钮进行操作,效果如下:
因为我们已经在刚开始设置了默认的动画效果:
main_recycler_view.setItemAnimator(new DefaultItemAnimator());
所以添加或者删除 Item 项时会有很不错的效果~
二、分类型 RecyclerView 的实现
分类型 RecyclerView 可以通过代码实现界面的多样化,如下图所示,一共三部分:最上方为轮播图片(Banner实现),中间是 GridView,下方是 ViewPager。
实现这样的效果,在总的布局文件中只需要定义一个 即可。
总 RecyclerView 及其 adapter
布局文件:
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v7.widget.RecyclerView android:id="@+id/home_recycle_view" android:layout_width="match_parent" android:layout_height="match_parent" /></RelativeLayout>
Adapter 代码:
public class HomeFragmentAdapter extends RecyclerView.Adapter { // 定义 3 种类型的编码 private static final int BANNER = 0; private static final int CHANNEL = 1; private static final int ACT = 2; // 当前类型 private int currentType = BANNER; private Context context; private JsonResult.ResultBean result; // 联网获得的 json 数据 private LayoutInflater layoutInflater; public HomeFragmentAdapter(Context context, JsonResult.ResultBean result) { this.context = context; this.result = result; layoutInflater = LayoutInflater.from(context); } //根据 RecyclerView 中的类型返回不同的 ViewHolder @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { if (viewType == BANNER) { return new BannerViewHolder(context, layoutInflater.inflate(R.layout.banner_view_pager, null)); } else if (viewType == CHANNEL) { return new ChannelViewHolder(context, layoutInflater.inflate(R.layout.channel_item, null)); } else if (viewType == ACT) { return new ActViewHolder(context, layoutInflater.inflate(R.layout.act_item, null)); } return null; } // 根据 position 判断 RecyclerView 类型并绑定数据 @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { if (getItemViewType(position) == BANNER) { BannerViewHolder bannerViewHolder = (BannerViewHolder) holder; bannerViewHolder.setData(result.getBanner_info()); } else if (getItemViewType(position) == CHANNEL) { ChannelViewHolder channelViewHolder = (ChannelViewHolder) holder; channelViewHolder.setData(result.getChannel_info()); } else if (getItemViewType(position) == ACT) { ActViewHolder actViewHolder = (ActViewHolder) holder; actViewHolder.setData(result.getAct_info()); } } // 获取当前 RecyclerView 的类型 @Override public int getItemViewType(int position) { switch (position) { case BANNER: currentType = BANNER; break; case CHANNEL: currentType = CHANNEL; break; case ACT: currentType = ACT; break; } return currentType; } // 一共有 3 种不同类型的 RecyclerView @Override public int getItemCount() { return 3; }}
1. BannerViewHolder
Banner 是一个第三方库,用于实现 Android 的图片轮播,效果如下所示。
github 地址:Banner
布局文件:
<?xml version="1.0" encoding="utf-8"?><LinearLayout 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="match_parent"> <com.youth.banner.Banner android:id="@+id/home_banner" android:layout_width="match_parent" android:layout_height="150dp" app:indicator_height="5dp" app:indicator_width="5dp" app:is_auto_play="true"> </com.youth.banner.Banner></LinearLayout>
代码:
public class BannerViewHolder extends RecyclerView.ViewHolder { private Context mContext; private Banner banner; public BannerViewHolder(Context context, View itemView) { super(itemView); this.mContext = context; this.banner = (Banner) itemView.findViewById(R.id.home_banner); } // 设置数据并开启轮播 public void setData(List<JsonResult.ResultBean.BannerInfoBean> banner_info) { List<String> imageUrls = new ArrayList<>(); for (int i = 0; i < banner_info.size(); i++) { imageUrls.add(banner_info.get(i).getImage()); } banner.setImages(imageUrls); // 设置图片 URL 的集合 banner.setImageLoader(new GlideImageLoader()); banner.setBannerAnimation(Transformer.Accordion); // 设置动画效果 banner.start(); } // 图片加载类 private class GlideImageLoader extends ImageLoader { @Override public void displayImage(Context context, Object path, ImageView imageView) { // 使用 Glide 加载图片 Glide.with(context).load(path).into(imageView); } }}
2. ChannelViewHolder
可以看出,整个频道模块就是一个 numColumns 为 5 的 GridView。
因此在 ChannelViewHolder 中初始化视图对象后要为此 GridView 设置适配器。
布局文件:
<?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="170dp" android:background="#fff" android:orientation="vertical"> <GridView android:id="@+id/home_gv_channel" android:layout_width="wrap_content" android:layout_height="150dp" android:numColumns="5"> </GridView></LinearLayout>
ChannelViewHolder 代码:
public class ChannelViewHolder extends RecyclerView.ViewHolder { private Context mContext; private GridView home_gv_channel; public ChannelViewHolder(Context context, View itemView) { super(itemView); this.mContext = context; home_gv_channel = (GridView) itemView.findViewById(R.id.home_gv_channel); } public void setData(List<JsonResult.ResultBean.ChannelInfoBean> channel_info) { ChannelAdapter adapter = new ChannelAdapter(mContext, channel_info); home_gv_channel.setAdapter(adapter); }}
Adapter 代码:
public class ChannelAdapter extends BaseAdapter { private Context mContext; private List<ChannelInfoBean> channel_info; public ChannelAdapter(Context context, List<ChannelInfoBean> channel_info) { this.mContext = context; this.channel_info = channel_info; } @Override public int getCount() { return channel_info.size(); } @Override public Object getItem(int position) { return channel_info.get(position); } @Override public long getItemId(int position) { return 0; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder viewHolder; if (convertView == null) { viewHolder = new ViewHolder(); convertView = View.inflate(mContext, R.layout.item_channel, null); viewHolder.iv_channel = (ImageView) convertView.findViewById(R.id.iv_channel); viewHolder.tv_channel = (TextView) convertView.findViewById(R.id.tv_channel); convertView.setTag(viewHolder); } else { viewHolder = (ViewHolder) convertView.getTag(); } ChannelInfoBean data = channel_info.get(position); Glide.with(mContext).load(data.getImage()).into(viewHolder.iv_channel); viewHolder.tv_channel.setText(data.getChannel_name()); return convertView; } private static class ViewHolder { ImageView iv_channel; TextView tv_channel; }}
- 1. Android
- Android(1.初识Android应用程序目录)
- Android学习笔记-1.Android工程结构
- 【Android】1. 搭建Android开发环境
- android开发--1.Android 源码下载
- Android学习笔记--1.初识Android
- 1. Android启动过程
- 1. android帧动画
- 1.Android数据库笔记
- 1.Android调用摄像头
- 1.Android随笔开篇
- 1.Android快速入门
- 1.Android系统架构
- 1.android体系结构介绍
- android学习1.activty
- 1.Android AlertDialog
- 1. Android Framework-Acitivty
- 1.android开发前沿
- 顺序栈的定义及相关操作
- OpenGL编程指南(第八版)第一个渲染三角形案例代码在win8双显卡电脑VS2015中运行方法总结
- 滑雪问题(dfs+递归)记忆化搜索 c语言
- HDU
- 【设计模式】行为型模式(上)
- 1. Android
- python学习笔记(三)面向对象
- TCP协议首部中URG与PSH的区别
- hdoj1016 Prime Ring Problem (深度搜索)
- USACO
- android 全屏模式下软键盘弹出问题
- Docker
- MySQL中B Tree索引原理
- java设计模式----单例模式