複雜ListView的多條目型別複用
阿新 • • 發佈:2019-01-03
複雜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 載入更多(沒有顯示)
}
}