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 extends RecyclerView.Adapter{
protected Context mContext;
private LayoutInflater inflater;
private List 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 list) {
datas.clear();
if(list!=null){
datas.addAll(list);
}
notifyDataSetChanged();
}
//增加更多
public void addMoreData(List list){
if(list!=null){
datas.addAll(list);
}
notifyDataSetChanged();
}
//获取数据集合数据
public List 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 views;
public BaseViewHolder(View view) {
super(view);
this.views = new SparseArray<>();
}
public 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源码地址