1. 程式人生 > >複雜ListView的多條目型別複用

複雜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 載入更多(沒有顯示)
        }
    }