Android开源项目LifeUtil 之数据展示
来源:互联网 发布:关于程序员的搞笑图片 编辑:程序博客网 时间:2024/05/28 04:55
在上一篇文章中,我们已经实现了从网络获取(抓爬)数据。得到数据之后,我们首先要做的肯定就是让它以优美的形式展示出来啦。这就是我们本节要讲的内容!!!数据展示
废话不多说,先上图
列表图:
详情图:
下面,就来说说怎么实现这个”美妙的UI界面“(好丑),
首先,先看看这样一个效果用到了什么技术。可以从图片上得知,这是一个可以左右切换的列表。这里使用了viewpager + TabLayout +fragment实现,即先将不同分类的Fragment加载到viewpager,再使用TabLayout实现指示条效果。简单的实现了这样一个可切换的效果。
内容展示项,这里使用了一个RecyclerView + CardView实现。然后图片和阅读项具体布局内容(列表图中两者的布局)会有所不同,两个布局都很简单。
- 下面主要讲Adapter如何设计,先看下“阅读”模块的Adapter实现,下面跟着代码来看下实现步骤。
public class ReadAdapter extends RecyclerView.Adapter<ReadAdapter.ReadHolder> { //用来装载数据 private List<ReadItem> readlist; private Context context; private LayoutInflater inflater; public ReadAdapter(Context context, List<ReadItem> list) { this.context = context; this.readlist = list; this.inflater = LayoutInflater.from(context); } @Override public ReadHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = inflater.inflate(R.layout.item_read, parent, false); ReadHolder holder = new ReadHolder(view); return holder; } @Override public void onBindViewHolder(final ReadHolder holder, int position) { final ReadItem item = readlist.get(position); holder.rootView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //使用WebView跳转,查看详情界面 WebUtils.openInternal(context,item.getUrl()); } }); //将标题设置为 序号.内容这种格式 holder.tv_name.setText(String.format("%s. %s", position + 1, item.getName())); holder.tv_info.setText(item.getUpdateTime() + " • " + item.getFrom()); //使用Glide加载图片,并且将图片缓存到本地 Glide.with(context).load(item.getIcon()).asBitmap().diskCacheStrategy(DiskCacheStrategy.ALL).fitCenter().into(new SimpleTarget<Bitmap>() { @Override public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) { //圆形图片 RoundedBitmapDrawable circularBitmapDrawable = RoundedBitmapDrawableFactory.create(context.getResources(), resource); circularBitmapDrawable.setCircular(true); holder.iv.setImageDrawable(circularBitmapDrawable); } }); } /** * 设置新内容 * @param data 新内容 */ public void setNewData(List<ReadItem> data) { this.readlist = data; notifyDataSetChanged(); } @Override public int getItemCount() { return readlist == null ? 0 : readlist.size(); } //取得data数据 public List<ReadItem> getData() { return readlist; } //添加data数据 public void addData(int position, List<ReadItem> data) { this.readlist.addAll(position, data); //只更新新加入的数据 this.notifyItemRangeInserted(position, data.size()); } class ReadHolder extends RecyclerView.ViewHolder { TextView tv_name; TextView tv_info; ImageView iv; View rootView; ReadHolder(View view) { super(view); rootView = view; tv_name = (TextView) view.findViewById(R.id.tv_read_name); tv_info = (TextView) view.findViewById(R.id.tv_read_info); iv = (ImageView) view.findViewById(R.id.iv_read_icon); } }}
上面代码中,我们实现了RecyclerView中Adapter必须要实现的接个方法,然后添加了一个setNewData和addData。两个方法来重置和更新数据。具体注意事项上面代码有写注释,主要是RecyclerView 的Adapter的实现方式。
在Fragment中,这里因为数据数量比较特殊,每一页是有限的并且不大,所以不需要采用分页显示,而每次刷新重新获取全部即可。而在“图片”的靓女专题 因为数据量太大,每此只刷新显示6张图片。后面的需要上拉加载才能显示。所以这里会有一点小小的区别。
- “图片”模块 靓女专题 的Adapter,之前有提到过他与其他的不一样,所以这里做特殊处理。而其他的图片项,则是跟上面的阅读区使用一样的实现,只是显示的内容View不一样罢了。
下面说一下”靓女专题“的实现,它跟其他项不一样的区别在于它是使用API接口(接口在下面)回调的Gson数据,而其他的均是网上爬取。所以他们的区别在于靓女专题的数据很大,不适合在一次全部读取下来,而应该在用户需要的时候在加载更多。
public interface GirlsController { @GET ("http://gank.io/api/data/%E7%A6%8F%E5%88%A9/6/{page}") Observable<BaseGankResponse<List<Girl>>> getGank(@Path("page") String page); @GET ("http://gank.io/api/data/%E7%A6%8F%E5%88%A9/10/{page}") Observable<ResponseBody> getGankBody(@Path("page") String page);}
下面来看下它的Adapter是如何实现的。代码如下:
public class GankGirlAdapter extends RecyclerView.Adapter<GankGirlAdapter.GirlViewHolder> { private List<Girl> girlList = new ArrayList<>(); private Context mContext; public GankGirlAdapter(Context context, List<Girl> girlList) { mContext = context; this.girlList = girlList; } /** * 添加数据 * * @param datas 新增的数据 */ public void addDatas(List<Girl> datas) { girlList.addAll(datas); notifyItemChanged(getItemCount()); } /** * 设置新内容 * * @param data 新内容 */ public void setNewData(List<Girl> data) { this.girlList = data; notifyDataSetChanged(); } @Override public GirlViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(mContext).inflate(R.layout.item_photo, parent, false);//这个布局就是一个imageview用来显示图片 GirlViewHolder holder = new GirlViewHolder(view); return holder; } @Override public void onBindViewHolder(GirlViewHolder holder, final int position) { ViewGroup.LayoutParams params = holder.iv.getLayoutParams(); params.width = 520; params.height = (new Random().nextInt(100) + 600); holder.iv.setLayoutParams(params); holder.name.setText(girlList.get(position).getName()); holder.date.setText(girlList.get(position).getDate()); holder.iv.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = PicDetailActivity.newIntent(mContext, girlList.get(position).getUrl(), ""); mContext.startActivity(intent); } }); //使用params,width 和params.heght 去加载图片 Glide.with(mContext) .load(girlList.get(position) .getUrl()) .override(params.width, params.height) //设置加载尺寸 .centerCrop() .diskCacheStrategy(DiskCacheStrategy.ALL) .into((holder).iv);//加载网络图片 } @Override public int getItemCount() { return girlList == null ? 0 : girlList.size(); } //自定义ViewHolder,用于加载图片 class GirlViewHolder extends RecyclerView.ViewHolder { ImageView iv; TextView name; TextView date; GirlViewHolder(View view) { super(view); iv = (ImageView) view.findViewById(R.id.img); name = (TextView) view.findViewById(R.id.name); date = (TextView) view.findViewById(R.id.date); } }}
你会觉得这个是曾相识,是的!没错。跟第一个没什么区别,因为重点不在这,而在Fragment中。小二,上代码!好嘞。
/** * 获取数据 * * @param curPage 当前页 */ public void getGank(int curPage) { ApiFactory.getGirlsController().getGank(curPage + "").subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Subscriber<BaseGankResponse<List<Girl>>>() { @Override public void onCompleted() { ((MainActivity) getActivity()).showSnack("加载完成"); binding.swipRefreshLayout.setRefreshing(false); } @Override public void onError(Throwable e) { ((MainActivity) getActivity()).showSnack("加载失败"); binding.swipRefreshLayout.setRefreshing(false); } @Override public void onNext(BaseGankResponse<List<Girl>> response) { for (Girl girl : response.datas) { if (girl.getHeight() == 0) { girl.setHeight((new Random().nextInt(100)) + 500); } } if (isRefresh) { adapter.setNewData(response.datas); } else { adapter.addDatas(response.datas); } } }); }
可以看到,我们在得到图片数据之后,进行了判断如果是上拉的话就调用adapter.setNewData(response.datas)方法,如果是下拉刷新就调用adapter.addDatas(response.datas)。
下面是判断是否到达底部的代码:
binding.gridRecycler.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { //判断是否还能下滑 if (!binding.gridRecycler.canScrollVertically(1)) { isRefresh = false; getGank(++curPage); } } @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); } });
主要代码为!binding.gridRecycler.canScrollVertically(1),用于判断是否还能下拉,如果不能就调用下拉刷新的代码。
这样,两个模块的数据显示就实现了。。。下文将讲解关于界面和设置界面,敬请期待。
- Android开源项目LifeUtil 之数据展示
- Android开源项目LifeUtil
- Android开源项目LifeUtil 之Base类
- Android开源项目LifeUtil 之网络请求
- Android--图片展示--photoview开源项目解析与使用
- Android----------RecyclerView数据展示
- Android之截图展示
- android系统定制项目展示
- Android 项目之--数据存储
- XListView之网络数据展示
- Android achartengine 动态展示数据
- Android案例之商品展示
- Flex开源展示之SHELF_PIC
- Android项目okhttp请求+RecyclerView展示
- Android项目开发之Sqlite数据存储
- Android 小项目之--数据存储【Files】
- Android项目数据存储之SharedPreferences
- Android使用ListView展示列表数据
- 18. 4Sum 题解
- Android之JSON的三种解析方式
- 多线程的三种方式
- C++函数之函数与数组
- python——高阶函数——map reduce filter sorted
- Android开源项目LifeUtil 之数据展示
- 即拿即用-Android单线程断点下载
- C/C++ 共用体
- java的多线程(一)
- Hdu1576 A-A/B 扩展欧几里德
- Web响应式开发
- PostgreSQL 性能调优
- 老调重弹:JDBC系列 之 <驱动加载原理全面解析>
- 安卓·为控件添加事件