复杂ListView的多条目类型复用

复杂ListVIew的多条目类型复用
即adapter、VIewHolder配合使用
· DefaultAdapter.java
public abstract class DefaultAdapter<Data> extends BaseAdapter implements AdapterView.OnItemClickListener {
//Data为泛型
    private static final int MORE_ITEM = 1;
    private static final int DEFAULT_ITEM = 0;
    private MoreHolder moreHolder;
    List<Data> datas ;
    private ListView listView;

    public DefaultAdapter(List<Data> datas,ListView listView) {
        this.datas = datas;
        listView.setOnItemClickListener(this);
        this.listView = listView;
    }

    public List<Data> getDatas() {
        return datas;
    }

    public void setDatas(List<Data> datas) {
        this.datas = datas;
    }

    @Override
    public int getCount() {
        return datas.size()+1;//加1为普通条目数+加载更多的条目
    }

    @Override
    public Object getItem(int position) {
        return datas.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    /** 根据位置 判断当前条目是什么类型 */
    @Override
    public int getItemViewType(int position) {
        if(position == datas.size()){// 当前是最后一个条目
            return MORE_ITEM;
        }
        return getInnerItemViewType(position); // 如果不是最后一个条目 返回默认类型
    }
    /**子类Adapter可以覆写该方法,可以继续增加条目类型,返回不同的类型*/
    protected int getInnerItemViewType(int position) {
        return DEFAULT_ITEM;
    }

    /** 当前ListView 有几种不同的条目类型 */
    @Override
    public int getViewTypeCount() {
        return super.getViewTypeCount()+1;//默认一种类型,+1就是2种类型
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        BaseHolder holder = null;
        switch (getItemViewType(position)) {  // 判断当前条目时什么类型
            case MORE_ITEM:
                if (convertView == null) {
                    holder = getMoreHolder();
                } else {
                    holder = (BaseHolder) convertView.getTag();
                }
                break;
            default:
                if (convertView == null) {
                    holder = getHolder();
                } else {
                    holder = (BaseHolder) convertView.getTag();
                }
                if (position < datas.size()) {
                    holder.setData(datas.get(position));
                }
                break;
        }
        return holder.getContentView();
    }


    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        position = position - listView.getHeaderViewsCount();// 获取到顶部条目的数量   位置去掉顶部view的数量
        onInnerItemClick(position);
    }
    /**在该方法去处理条目的点击事件,可以在相应Fragment中覆写,各个Fragment中listview的adapter都可以继承DefaultAdapter*/
    public void onInnerItemClick(int position) {
    }

    /**
     * 是否有额外的数据,子类重写就可以自定义是否显示加载更多
     * @return
     */
    protected boolean hasMore() {
        return true;
    }
    /**
     *拿到MoreHolder对象
     */
    private BaseHolder getMoreHolder() {
        if(moreHolder!=null){
            return moreHolder;
        }else{
            moreHolder=new MoreHolder(this,hasMore());
            return moreHolder;
        }
    }

    public abstract BaseHolder<Data> getHolder();

    /**
     * 当加载更多条目显示的时候 调用该方法
     * 调用onLoadMore方法访问服务器
     * runOnUiThread内显示MoreHolder,notifyDataSetChanged();更新界面
     */
    public void loadMore() {
        ThreadManager.getInstance().createLongPool().execute(
                new Runnable() {
                    @Override
                    public void run() {
                        final List<Data> newData = onLoadMore();
                        UIutil.runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                if(newData == null){
                                    moreHolder.setData(moreHolder.LOAD_ERROR);
                                }else if(newData.size() == 0){
                                    moreHolder.setData(moreHolder.HAS_NO_MORE);
                                }else {
                                    moreHolder.setData(moreHolder.HAS_MORE);
                                    datas.addAll(newData);
                                    notifyDataSetChanged();
                                }
                            }
                        });
                    }
                }
        );
    }

    protected abstract List<Data> onLoadMore();
}
· BaseHolder的实现
package com.appstore.holder;
import android.view.View;
import com.appstore.utils.BitmapUtil;
import com.lidroid.xutils.BitmapUtils;

public abstract class BaseHolder<Data> {

    private View contentView;//与getView方法的convertView意义相同
    private Data data;
    protected BitmapUtils bitmapUtils;
    public BaseHolder(){
        bitmapUtils = BitmapUtil.getBitmap();
        contentView=initView();//初始化view
        contentView.setTag(this);//view与当前viewHolder绑定
    }
    /** 创建界面*/
    public  abstract View initView();
    /**给Adapter的getView方法返回一个与ViewHolder绑定好的并且初始化的View*/
    public View getContentView() {
        return contentView;
    }
    public void setData(Data data){
        this.data=data;
        refreshView(data);
    }
    /** 根据数据刷新界面*/
    public abstract void refreshView(Data data);
}
· AppAdapter.java 继承DefaultAdapter继续实现细节
public abstract class AppAdapter extends DefaultAdapter<AppInfo> {
    public AppAdapter(List<AppInfo> appInfos, ListView listView) {
        super(appInfos,listView);
    }

    @Override
    public BaseHolder<AppInfo> getHolder() {
        return new AppHolder();//返回普通条目的ViewHolder对象
    }

    @Override
    protected abstract List<AppInfo> onLoadMore();

    /**点击listview条目继续实现*/
    @Override
    public void onInnerItemClick(int position) {
        super.onInnerItemClick(position);
        Toast.makeText(UIutil.getContext(), "position:"+position, 0).show();
        AppInfo appInfo = datas.get(position);
        Intent intent=new Intent(UIutil.getContext(), DetailActivity.class);
        intent.putExtra("packageName", appInfo.getPackageName());
        UIutil.startActivity(intent);//实现点击listview条目activity跳转
    }
}
· MoreHolder
public class MoreHolder extends BaseHolder<Integer> {

    public static final int HAS_NO_MORE = 0;
    public static final int LOAD_ERROR = 1;
    public static final int HAS_MORE = 2;

    private RelativeLayout loading_more,loadMore_error;

    private DefaultAdapter adapter;

    private boolean  hasMore;

    public MoreHolder(DefaultAdapter adapter,boolean hasMore) {
        super();
        this.adapter=adapter;
        this.hasMore = hasMore;
        /**当子类重写的hasMore值为假时,setData在父类BaseHolder中内部调用refreshView,传入0,对应静态常量HAS_NO_MORE,不再显示加载更多的界面*/
        if(!hasMore){
            setData(0);
        }
    }

    @Override
    public View initView() {
        View view = View.inflate(UIutil.getContext(), R.layout.load_more,null);
        loading_more = (RelativeLayout) view.findViewById(R.id.rl_more_loading);
        loadMore_error = (RelativeLayout) view.findViewById(R.id.rl_more_error);
        return view;
    }
/**是否显示加载更多和加载更多失败界面*/
    @Override
    public void refreshView(Integer integer) {
        loading_more.setVisibility(integer == HAS_MORE ? View.VISIBLE : View.GONE);
        loadMore_error.setVisibility(integer == LOAD_ERROR ? View.VISIBLE : View.GONE);
    }
/***/
    @Override
    public View getContentView() {
        if(hasMore) {
            loadMore();
        }
        return super.getContentView();
    }

    private void loadMore() {
        // 请求服务器   加载下一批数据
        //  交给DefaultAdapter  让Adapter加载更多数据
        adapter.loadMore();
    }
}
· HomePictureHolder 再给listview加个头部。实现如图


Code:

package com.appstore.holder;

import android.app.ActionBar;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.ImageView;

import com.appstore.R;
import com.appstore.utils.UIutil;

import java.util.LinkedList;
import java.util.List;

public class HomePictureHolder extends BaseHolder<List<String>> {
    private ViewPager viewPager;
    private List<String> datas;

    private AutoRunTask autoRunTask;
    boolean flag;
    @Override
    public View initView() {
        viewPager = new ViewPager(UIutil.getContext());
        viewPager.setLayoutParams(new AbsListView.LayoutParams(ActionBar.LayoutParams.MATCH_PARENT,
                UIutil.getDimen(R.dimen.home_headItem_height)));
        return viewPager;
    }

    @Override
    public void refreshView(List<String> strings) {

        this.datas = strings;
        viewPager.setAdapter(new picAdapter());//轮播图
        viewPager.setCurrentItem(Integer.MAX_VALUE / 2);

        viewPager.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch(event.getAction()){
                    case MotionEvent.ACTION_DOWN:
                        autoRunTask.stop();
                        break;
                    case MotionEvent.ACTION_CANCEL:
                    case MotionEvent.ACTION_UP:
                        autoRunTask.start();
                        break;

                }
                return false; // viewPager 触摸事件 返回值要是false
            }
        });

        autoRunTask = new AutoRunTask();
        autoRunTask.start();

    }

    class picAdapter extends PagerAdapter{
        // 当前viewPager里面有多少个条目
        LinkedList<ImageView> imageViews = new LinkedList<>();
        @Override
        public int getCount() {
            return Integer.MAX_VALUE;
        }

        /* 判断返回的对象和 加载view对象的关系 */
        @Override
        public boolean isViewFromObject(View view, Object object) {
            return view == object;
        }

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            ImageView view = (ImageView) object;
            imageViews.add(view);// 把移除的对象 添加到缓存集合中
            container.removeView((View) object);
        }

        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            int index = position % datas.size();
            ImageView imageView;
            if(imageViews.size() > 0){
                imageView = imageViews.remove(0);
            }else {
                imageView = new ImageView(UIutil.getContext());
            }
            bitmapUtils.display(imageView,"http://127.0.0.1:8090/image?name="+datas.get(index));
            container.addView(imageView);
            return imageView;
        }
    }

    /**自动轮询*/
    class AutoRunTask implements Runnable{

        @Override
        public void run() {
            if(flag){
                UIutil.cancel(this);
                int currentItem = viewPager.getCurrentItem();
                currentItem ++;
                viewPager.setCurrentItem(currentItem);
                UIutil.postDelayed(this,2000);
            }

        }

        public void start(){
            if(!flag){
                UIutil.cancel(this);  // 取消之前
                flag = true;
                UIutil.postDelayed(this, 2000);// 递归调用
            }
        }

        public void stop(){
            if(flag) {
                flag = false;
                UIutil.cancel(this);
            }
        }
    }
}
· 最后 HomeFragment中实例化listview
@Override
    public View onCreateView(LayoutInflater inflater,  ViewGroup container,  Bundle savedInstanceState) {
BaseListView mListView = new BaseListView(getContext());

        HomePictureHolder picHolder = new HomePictureHolder();
        picHolder.setData(pictures);
        View contentView = picHolder.getContentView();
        mListView.addHeaderView(contentView);

        mListView.setAdapter(new AppAdapter(datas,mListView) {
            @Override
            protected List<AppInfo> onLoadMore() {
                HomeProtocol protocol = new HomeProtocol();
                List<AppInfo> list = protocol.load(datas.size());
                datas.addAll(list);
                return list;
            }
        });
        bitmapUtils = BitmapUtil.getBitmap();
        // 第二个参数 慢慢滑动的时候是否加载图片 false  加载   true 不加载
        //  第三个参数  飞速滑动的时候是否加载图片  true 不加载
        mListView.setOnScrollListener(new PauseOnScrollListener(bitmapUtils,false,true));
        bitmapUtils.configDefaultLoadingImage(R.drawable.ic_default);
        bitmapUtils.configDefaultLoadFailedImage(R.drawable.ic_default);
        return mListView;
}

· 这里继续增加listview的第三种条目类型。实现这种效果

  • CategoryFragment
public class CategoryFragment extends BaseFragment {

    private List<CategoryInfo> datas;
    public static int ITEM_TITLE =2;

    // 创建成功的界面
    @Override
    public View onCreateView() {
        BaseListView listView = new BaseListView(UIutil.getContext());
        listView.setAdapter(new CategoryAdapter(datas, listView));
        return listView;
    }

    private class CategoryAdapter extends DefaultAdapter<CategoryInfo> {
        private int position;// 当前条目位置记录
        public CategoryAdapter(List<CategoryInfo> datas, ListView lv) {
            super(datas, lv);
        }

        // 实现每个条目的界面
        @Override
        public BaseHolder<CategoryInfo> getHolder() {
            if (!datas.get(position).isTitle()) {
                return new CategoryContentHolder();
            }else{
                return new CategoryTitleHolder();
            }
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            this.position = position;
            return super.getView(position, convertView, parent);
        }

        @Override
        protected boolean hasMore() { // 当前方法 如果为false onload就不会被调用了
            return false;
        }

        @Override
        protected int getInnerItemViewType(int position) {
            if (datas.get(position).isTitle()) {
                return ITEM_TITLE;
            } else {
                return super.getInnerItemViewType(position);
            }
        }

        @Override
        protected List<CategoryInfo> onLoadMore() {
            return null;
        }
        //  集合 管理三个convertView
        @Override
        public int getViewTypeCount() {
            return super.getViewTypeCount() + 1; // 又额外多了一种条目类型  现在又三种  1 标题 2 内容 3 加载更多(没有显示)
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值