(六)安卓框架搭建之RecyclerView和Adapter以及列表案例
来源:互联网 发布:淘宝零食店货源哪里来 编辑:程序博客网 时间:2024/05/17 23:25
recycalview和adapter
recycleview 的出现就是来替代listview,并且其性能上做了很多优化。今天用的这个是取自第三方的Xrecycleview,没错,这次又是站在了巨人的肩膀上。选Xrecycleview的原因是之前用这个写过一个自定义的头部刷新view.而且它在github上,评价也蛮好。
有点小遗憾就是刷新效果很老气。所以我决定重新写一个RefresHeader.如下
package com.example.burro.demo.appframework.recyclerview.xrecyclerview.custom;import android.animation.ValueAnimator;import android.content.Context;import android.graphics.drawable.AnimationDrawable;import android.os.Handler;import android.util.AttributeSet;import android.view.Gravity;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.ImageView;import android.widget.LinearLayout;import com.example.burro.demo.appframework.R;import com.example.burro.demo.appframework.recyclerview.xrecyclerview.BaseRefreshHeader;import com.example.burro.demo.appframework.recyclerview.xrecyclerview.SimpleViewSwitcher;/**自定义刷新view *Created by ex.zhong on 2017/9/17. */public class CustomerRefreshHeader extends LinearLayout implements BaseRefreshHeader { private LinearLayout mContainer; private ImageView mArrowImageView; private SimpleViewSwitcher mProgressBar; private int mState = STATE_NORMAL; public int mMeasuredHeight; private AnimationDrawable mAnimationDrawable; public CustomerRefreshHeader(Context context) { super(context); initView(); } /** * @param context * @param attrs */ public CustomerRefreshHeader(Context context, AttributeSet attrs) { super(context, attrs); initView(); } private void initView() { // 初始情况,设置下拉刷新view高度为0 mContainer = (LinearLayout) LayoutInflater.from(getContext()).inflate( R.layout.custom_listview_header, null); LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); lp.setMargins(0, 0, 0, 0); this.setLayoutParams(lp); this.setPadding(0, 0, 0, 0); addView(mContainer, new LayoutParams(LayoutParams.MATCH_PARENT, 0)); setGravity(Gravity.BOTTOM); mArrowImageView = (ImageView)findViewById(R.id.listview_header_arrow); //init the progress view mProgressBar = (SimpleViewSwitcher)findViewById(R.id.listview_header_progressbar); ImageView progressView= new ImageView(getContext()); progressView.setImageResource(R.drawable.refresh_headview); mAnimationDrawable=(AnimationDrawable)progressView.getDrawable(); mProgressBar.setView(progressView); measure(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); mMeasuredHeight = getMeasuredHeight(); } public void setProgressStyle(int style) { } //设置要动画图片 public void setProgressStyle(ImageView imageView) { if(imageView != null&&imageView.getDrawable()!=null){ mProgressBar.setView(imageView); mAnimationDrawable= (AnimationDrawable) imageView.getDrawable(); } } //设置背景图片 public void setRefreshBackground(int color) { mContainer.setBackgroundColor(color); } public void setArrowImageView(int resid){ mArrowImageView.setImageResource(resid); } public void setState(int state) { if (state == mState) return ; if (state == STATE_REFRESHING) { // 显示进度 mArrowImageView.clearAnimation(); mArrowImageView.setVisibility(View.INVISIBLE); mProgressBar.setVisibility(View.VISIBLE); mAnimationDrawable.start(); smoothScrollTo(mMeasuredHeight); } else if(state == STATE_DONE) { mArrowImageView.setVisibility(View.VISIBLE); mProgressBar.setVisibility(View.INVISIBLE); mAnimationDrawable.stop(); } else { // 显示箭头图片 mArrowImageView.setVisibility(View.VISIBLE); mProgressBar.setVisibility(View.INVISIBLE); mAnimationDrawable.stop(); } mState = state; } public int getState() { return mState; } @Override public void refreshComplete(){ setState(STATE_DONE); new Handler().postDelayed(new Runnable(){ public void run() { reset(); } }, 200); } public void setVisibleHeight(int height) { if (height < 0) height = 0; LayoutParams lp = (LayoutParams) mContainer .getLayoutParams(); lp.height = height; mContainer.setLayoutParams(lp); } public int getVisibleHeight() { LayoutParams lp = (LayoutParams) mContainer.getLayoutParams(); return lp.height; } @Override public void onMove(float delta) { if(getVisibleHeight() > 0 || delta > 0) { setVisibleHeight((int) delta + getVisibleHeight()); if (mState <= STATE_RELEASE_TO_REFRESH) { // 未处于刷新状态,更新箭头 if (getVisibleHeight() > mMeasuredHeight) { setState(STATE_RELEASE_TO_REFRESH); }else { setState(STATE_NORMAL); } } } } @Override public boolean releaseAction() { boolean isOnRefresh = false; int height = getVisibleHeight(); if (height == 0) // not visible. isOnRefresh = false; if(getVisibleHeight() > mMeasuredHeight && mState < STATE_REFRESHING){ setState(STATE_REFRESHING); isOnRefresh = true; } // refreshing and header isn't shown fully. do nothing. if (mState == STATE_REFRESHING && height <= mMeasuredHeight) { //return; } if (mState != STATE_REFRESHING) { smoothScrollTo(0); } if (mState == STATE_REFRESHING) { int destHeight = mMeasuredHeight; smoothScrollTo(destHeight); } return isOnRefresh; } public void reset() { smoothScrollTo(0); new Handler().postDelayed(new Runnable() { public void run() { setState(STATE_NORMAL); } }, 500); } private void smoothScrollTo(int destHeight) { ValueAnimator animator = ValueAnimator.ofInt(getVisibleHeight(), destHeight); animator.setDuration(300).start(); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { setVisibleHeight((int) animation.getAnimatedValue()); } }); animator.start(); }}
修改的思路起始很简单。只是把以前刷新时的旋转动画换成了帧动画。当下拉或刷新结束时。设置静态图片。当然要对核心的XRecyclerViewy也要稍加修改,使其适配我的CustomerRefreshHeader.布局请到demo中查看
adapter
XRecyclerViewy封装的很好,但是没有对他的兄弟adapter进行封装优化。BaseRecyclerViewAdapter是adapter的基类,直接贴上封装内容:
BaseRecyclerViewAdapter
package com.example.burro.demo.appframework.adapter;import android.content.Context;import android.support.v7.widget.RecyclerView;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import java.util.ArrayList;import java.util.List;/**Adapter基类 * Created by ex.zhong on 2017/9/29. */public abstract class BaseRecyclerViewAdapter<T> extends RecyclerView.Adapter<BaseViewHolder>{ protected Context mContext; private LayoutInflater inflater; private List<T> datas; private int layoutId; protected OnItemClickListner onItemClickListner;//单击事件 protected OnItemLongClickListner onItemLongClickListner;//长按单击事件 public BaseRecyclerViewAdapter(Context context, OnItemClickListner onItemClickListner) { this.mContext = context; this.datas = new ArrayList<>(); this.layoutId = initLayoutInflater(); this.inflater = LayoutInflater.from(context); this.onItemClickListner=onItemClickListner; } protected abstract int initLayoutInflater(); @Override public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { BaseViewHolder holder = new BaseViewHolder(inflater.inflate(layoutId, parent, false)); //可全局在此设置增加外层效果布局// MaterialRippleLayout.on(holder.getView(R.id.ll_all))// .rippleOverlay(true)// .rippleAlpha(0.2f)// .rippleColor(context.getResources().getColor(R.color.colorAccent))// .rippleHover(true)// .create(); return holder; } @Override public void onBindViewHolder(final BaseViewHolder holder, final int position) { holder.getRootView().setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if(onItemClickListner!=null) onItemClickListner.onItemClickListner(v,position); } }); bindData(holder, datas.get(position), position); } protected abstract void bindData(BaseViewHolder holder, T data, int position); @Override public int getItemCount() { return datas == null ? 0 : datas.size(); } //单击事件接口 public interface OnItemClickListner { void onItemClickListner(View v, int position); } //长按事件接口 public interface OnItemLongClickListner { void onItemLongClickListner(View v, int position); } //更新数据 public void updateData(List<T> list) { datas.clear(); if(list!=null){ datas.addAll(list); } notifyDataSetChanged(); } //增加更多 public void addMoreData(List<T> list){ if(list!=null){ datas.addAll(list); } notifyDataSetChanged(); } //获取数据集合数据 public List<T> getDataList(){ return datas; }}
BaseViewHolder
package com.example.burro.demo.appframework.adapter;import android.support.v7.widget.RecyclerView;import android.util.SparseArray;import android.view.View;/**全能的ViewHolder * Created by ex.zhong on 2017/9/29. */public class BaseViewHolder extends RecyclerView.ViewHolder{ private SparseArray<View> views; public BaseViewHolder(View view) { super(view); this.views = new SparseArray<>(); } public <T extends View> T getView(int viewId) { View view = views.get(viewId); if (view == null) { view = itemView.findViewById(viewId); views.put(viewId, view); } return (T) view; } public View getRootView() { return itemView; }}
我是不推荐直接的引用第三方的包,试想如果需求要调整,那岂不是每个页面都要去改动?所以!当然!要封装一个公用的类来继承它。我这里写一个类ComRecyclerView继承自XRecyclerView,各位也可以根据具体使用情况自由发挥!
package com.example.burro.demo.appframework.recyclerview;import android.content.Context;import android.support.v7.widget.LinearLayoutManager;import android.util.AttributeSet;import com.example.burro.demo.appframework.R;import com.example.burro.demo.appframework.recyclerview.xrecyclerview.ProgressStyle;import com.example.burro.demo.appframework.recyclerview.xrecyclerview.XRecyclerView;/**通用ComRecyclerView * Created by ex.zhong on 2017/9/27. */public class ComRecyclerView extends XRecyclerView { public ComRecyclerView(Context context) { super(context); initView(context); } public ComRecyclerView(Context context, AttributeSet attrs) { super(context, attrs); initView(context); } public ComRecyclerView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); initView(context); } private void initView(Context context) { // headerView的添加,可更具需要,在页面上动态设置// View header = LayoutInflater.from(context).inflate(R.layout.recyclerview_header, (ViewGroup)findViewById(android.R.id.content),false);// mRecyclerView.addHeaderView(header); //添加刷新动画 //默认线性布局,如需gridView,可重新设置 LinearLayoutManager layoutManager = new LinearLayoutManager(context); layoutManager.setOrientation(LinearLayoutManager.VERTICAL); this.setLayoutManager(layoutManager); this.setRefreshProgressStyle(ProgressStyle.BallSpinFadeLoader); this.setLoadingMoreProgressStyle(ProgressStyle.BallRotate); this.setArrowImageView(R.mipmap.mloading_0); }}
先前写过的电影列表中用到的Adapter,看看是不是很简洁!
为了保证demo的完整性,结合之前所写以及上述RecyclerView和Adapter的封装,接下来完善一下列表页面。我把test部分的内容全部移进movie里面。并增加了详情页面,页面跳转、MainActivity里增加新建的MovieListFragment等。由于这部分主要是业务内容。不多作说明,可以到源码中查看
下一篇将进一步完善框架
相关链接
(七)安卓框架搭建之其他必备要素的封装或引入
github源码地址
- (六)安卓框架搭建之RecyclerView和Adapter以及列表案例
- RecyclerView和Adapter 以及ViewHolder
- 安卓日记——RecyclerView进阶(下拉上拉刷新和万能Adapter)
- 安卓高级3 RecyclerView 和cardView使用案例
- windows 7+vs2012+cocos2d-x 3.2环境搭建以及安卓移植成功案例(亲测)
- 安卓学习之Adapter
- 安卓Adapter之SimpleAdapter
- Android客户端之“微服私访”App的系统学习(六)RecyclerView 展现复杂数据列表以及水波纹效果+CardView显示头像
- SeaSar之框架搭建和入门案例-yellowcong
- 安卓 框架搭建
- Dubbo框架的搭建以及入门案例
- RecyclerView,Adapter和ViewHolder
- 安卓的那些事儿-android之RecyclerView的使用,实现列表横向滚动
- Android-多列表的项目(Rxjava+Rtrofit+Recyclerview+Glide+Adapter封装)之(一)项目架构
- Android-多列表的项目(Rxjava+Rtrofit+Recyclerview+Glide+Adapter封装)之(二)网络层的封装
- Android-多列表的项目(Rxjava+Rtrofit+Recyclerview+Glide+Adapter封装)之(一)项目架构
- Android-多列表的项目(Rxjava+Rtrofit+Recyclerview+Glide+Adapter封装)之(二)网络层的封装
- 安卓数据库框架LitePal(六):修改和删除操作
- (五)安卓框架搭建之BaseFragment,MainActivity, Toolbar细化
- 汉诺塔问题
- MySQL数据库备份与恢复
- 设计模式之禅18
- Starship Troopers (树形dp+背包)
- (六)安卓框架搭建之RecyclerView和Adapter以及列表案例
- spark 机制原理自问自答
- (七)安卓框架搭建之其他必备要素的封装或引入
- python学习笔记 第三章
- Android事件分发机制总结
- 螺旋数组
- C语言预处理
- 腾讯面试官送给准程序员的一些建议!
- delphi FMX图像的直方图均衡