模板代碼 - 列表和下拉刷新

模板代碼 - 列表和下拉刷新

  手機應用一個常見的界面模式就是:頂部的ActionBar + TabStrip導航,中間的ListView,能夠下拉刷新或者是底部的加載更多。一般ListView都須要是顯示多種類型的條目。

ActionBar-ViewPager-Fragment

  • 自定義一個帶有ActionBar的主題:這樣既能夠得到ActionBar效果,又能夠本身調整ActionBar的顯示,如背景和字體等。下面主要是從新指定了tab_indicator。android

    //在values/style.xml裏:actionbar_tab_indicator的內容省略,官方文檔有,很羅嗦。
    <style name="CustomActionBarTheme"
           parent="@android:style/Theme.Holo.Light">
        <item name="android:actionBarTabStyle">@style/MyActionBarTabs</item>
    </style>
    
    <!-- ActionBar tabs styles -->
    <style name="MyActionBarTabs"
           parent="@style/android:Widget.Holo.ActionBar.TabView">
        <!-- tab indicator -->
        <item name="android:background">@drawable/actionbar_tab_indicator</item>
    </style>
  • 讓Activity繼承FragmentActivity,定義一個繼承自FragmentStatePagerAdapter的子類——MyPagerAdapter,活動佈局中放置一個ViewPager填充整個界面。Activity.onCreate方法裏爲ActionBar設置屬性:markdown

    ActionBar actionBar = getActionBar();
    actionBar.setDisplayHomeAsUpEnabled(true);
    actionBar.setHomeButtonEnabled(true);
    
    //FragmentStatePagerAdapter的public Fragment getItem(int position)等相關方法正是配合ViewPager來完成
    //整個界面裏切換Fragment的功能。它一直保持正在顯示的,和左右(若是有)2個Fragment實例。
    
    //關聯viewPager和FragmentStatePagerAdapter實例
    viewPager.setAdapter(new MyPagerAdapter(getSupportFragmentManager()));
  • 在佈局文件,ViewPager內放置android.support.v4.view.PagerTabStrip控件,這樣能夠顯示ActionBar的tabs爲特殊的樣式,就是一直顯示「左、中、右」 3個tab指示器,左右滑動ViewPager切換Fragment時,或者點擊tab標籤時左右滾動來顯示更多其它的tab。(之後上圖。。。)app

ListView顯示多種類型的條目

  ListView支持顯示多種類型的條目,而且能夠同時複用不一樣條目的view。假設咱們使用ListView顯示一個下載應用的列表界面,在ListView的底部顯示「加載更多」這樣的按鈕,那麼就是讓ListView同時顯示2種類型的條目。

  ListView的getView方法正是咱們爲ListView提供要顯示條目的地方,爲了便於爲普通的條目對應的view對象添加更多的控制,能夠定義ViewHolder來組合View,並負責它的建立和狀態控制。async

  • 爲顯示的「應用信息」列表條目定義AppInfoViewHolder,它包含一個name和icon,佈局文件item_appinfo是簡單的ImageView和TextView,其ViewHolder定義以下:ide

    class AppInfoViewHolder{
        ImageView icon;
        TextView name;
        View itemView;
    
        public AppInfoViewHolder(){
            itemView = View.inflate(AppHelper.getContext(), R.layout.item_appinfo,null);
            icon = (ImageView)itemView.findViewById(R.id.appIcon);
            name = (TextView)itemView.findViewById(R.id.appName);
            //關聯當前Holder和View
            itemView.setTag(this);
        }
    
        public void setViewData(AppInfo info){
            icon.setImageResource(info.getIconResId());
            name.setText(info.getName());
        }
    
        public View getView(){
            return itemView;
        }       
    }
  • 以後定義「加載更多」的LoadMoreViewHolder:佈局

    public class LoadMoreViewHolder {   
    
        private View contentView;       
        private View loadMore;
        private View loading;
        private Button bt_loadMore;
    
        OnLoadMoreExecute loadMoreListener;
    
        public LoadMoreViewHolder{
            contentView = View.inflate(UIUtils.getContext(), R.layout.load_more, null);
            loadMore = contentView.findViewById(R.id.view_load_more);
            loading = contentView.findViewById(R.id.view_loading);
            bt_loadMore =  (Button) contentView.findViewById(R.id.bt_load_more);
            //關聯當前Holder和View
            contentView.setTag(this);
            showLoadMore();
        }
    
        public interface OnLoadMoreExecute{
            void loadMore(LoadMoreHolder holder);
        }           
    
        //設置「加載更多」的業務邏輯
        public void setOnLoadMoreListener(OnLoadMoreExecute action){
            loadMoreListener = action;
            if(loadMoreListener != null ){                      
                bt_loadMore.setOnClickListener(new OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        loadMoreListener.loadMore(LoadMoreViewHolder.this);
                    }
                });                             
            }   
        }       
    
        public void showLoading(){
            loading.setVisibility(View.VISIBLE);
            loadMore.setVisibility(View.INVISIBLE);
        }
    
        public void showLoadMore(){
            loadMore.setVisibility(View.VISIBLE);
            loading.setVisibility(View.INVISIBLE);
        }
    
        public View getView(){              
            return contentView;
        }
    }

      LoadMoreViewHolder提供加載更多加載中兩種界面,當數據加載失敗或者沒有更多數據時,可使用Toast進行界面提示,固然也能夠動態改變「加載更多」按鈕的顯示文本。字體

      上面的LoadMoreViewHolder顯示了使用ViewHolder來管理每一個列表條目對應的View是很是方便的,這樣可讓ListView的每一個條目的建立、狀態修改的代碼都集中在一個類中,若是不是使用ViewHolder來組合View,那麼對View狀態的修改的代碼就很容易分散地複雜起來。this

  • ListView的多條目類型複用,主要是getView、getViewTypeCount、getItemViewType和getCount搭配使用。設計

    public class AppInfoAdapter extends BaseAdapter {
    
        List<AppInfo> infos;
        private final int ITEMTYPE_APP = 0;//條目類型對應的值範圍是:0 ~ getViewTypeCount()-1
        private final int ITEMTYPE_MORE = 1;
    
        //顯示的條目總數
        @Override
        public int getCount() {
            return infos.size() + 1;
        }
    
        //position處的條目的類型,條目類型對應的值範圍是:0 ~ getViewTypeCount()-1
        @Override
        public int getItemViewType(int position) {
            if(position == infos.size()){
                return ITEMTYPE_MORE;
            }else{
                return ITEMTYPE_APP;
            }
        }
    
        //顯示條目的類型數
        @Override
        public int getViewTypeCount() {
            return 2;
        }
    
        //根據position和convertView來建立或複用條目
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            int viewType = getItemViewType(position);
            View view = null;
            switch (viewType) {
            case ITEMTYPE_APP:
                AppInfoViewHolder appHolder = null;
                if(convertView == null){
                    appHolder = new AppInfoViewHolder();
                }else{
                    appHolder = (AppInfoViewHolder) view.getTag();
                }
                appHolder.setViewData(infos.get(position));
                view = appHolder.getView();
                break;
            case ITEMTYPE_MORE:
                if(convertView == null){
                    LoadMoreViewHolder moreHolder = new LoadMoreViewHolder();
                    moreHolder.setOnLoadMoreListener(new OnLoadMoreExecute(){
                        @Override
                        public void loadMore(LoadMoreViewHolder holder){
                            asyncLoadMoreData(holder);
                        }
                    });
                    view = moreHolder.getView();
                }else{
                    view = convertView;
                }
                break;
            }
            return view;
        }
    
        private void asyncLoadMoreData(LoadMoreViewHolder holder){
            holder.showLoading();
            new Thread(){
                @Override
                public void run() {
                    final List<AppInfo> newData = new AppInfoDao.getPageData(2);
                    UIHelper.runOnUiThread(new Runnable(){
                        @Override
                        public void run() {
                            if(newData == null){
                                Toast.makeText(AppHelper.getContext(), "獲取失敗,稍後重試。", Toast.LENGTH_SHORT).show();
                            }else if(newData.size() == 0){
                                Toast.makeText(AppHelper.getContext(), "沒數據了,稍後重試。", Toast.LENGTH_SHORT).show();
                            }else{
                                infos.addAll(newData);
                                notifyDataSetChanged();
                            }
                            holder.showLoadMore();
                        }
                    });
                }
            }.start();
        }
    }條目類型對應的值範圍是:0 ~ getViewTypeCount()-1getViewTypeCount()getViewTypeCount()

  ListView能夠添加多種類型的顯示條目,常見的有頂部的輪播圖片,頂部下拉刷新,以及底部的加載更多等等。藉助ViewHolder來管理ListView要顯示的條目,代碼更容易集中,能夠針對不一樣的條目設計不一樣的Holder類。code

相關文章
相關標籤/搜索