专栏首页everhad模板代码 - 列表和下拉刷新

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

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

  手机应用一个常见的界面模式就是:顶部的ActionBar + TabStrip导航,中间的ListView,可以下拉刷新或者是底部的加载更多。通常ListView都需要是显示多种类型的条目。

ActionBar-ViewPager-Fragment

  • 自定义一个带有ActionBar的主题:这样既可以获得ActionBar效果,又可以自己调整ActionBar的显示,如背景和字体等。下面主要是重新指定了tab_indicator。
 //在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设置属性:
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。(以后上图。。。)

ListView显示多种类型的条目

  ListView支持显示多种类型的条目,并且可以同时复用不同条目的view。假设我们使用ListView显示一个下载应用的列表界面,在ListView的底部显示“加载更多”这样的按钮,那么就是让ListView同时显示2种类型的条目。   ListView的getView方法正是我们为ListView提供要显示条目的地方,为了便于为普通的条目对应的view对象添加更多的控制,可以定义ViewHolder来组合View,并负责它的创建和状态控制。

  • 为显示的“应用信息”列表条目定义AppInfoViewHolder,它包含一个name和icon,布局文件item_appinfo是简单的ImageView和TextView,其ViewHolder定义如下:
 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;

s   LoadMoreViewHolder提供加载更多加载中两种界面,当数据加载失败或者没有更多数据时,可以使用Toast进行界面提示,当然也可以动态改变“加载更多”按钮的显示文本。   上面的LoadMoreViewHolder显示了使用ViewHolder来管理每个列表条目对应的View是非常方便的,这样可以让ListView的每个条目的创建、状态修改的代码都集中在一个类中,如果不是使用ViewHolder来组合View,那么对View状态的修改的代码就很容易分散地复杂起来。

  • 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();
    }
}

  ListView可以添加多种类型的显示条目,常见的有顶部的轮播图片,顶部下拉刷新,以及底部的加载更多等等。借助ViewHolder来管理ListView要显示的条目,代码更容易集中,可以针对不同的条目设计不同的Holder类。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • android自定义控件一站式入门

    Android系统提供了一系列UI相关的类来帮助我们构造app的界面,以及完成交互的处理。 一般的,所有可以在窗口中被展示的UI对象类型,最终都是继承自Vie...

    用户1172465
  • android自定义控件一站式入门

    TODO: 待整理 自定义控件 Android系统提供了一系列UI相关的类来帮助我们构造app的界面,以及完成交互的处理。 一般的,所有可以在窗口中被展示的U...

    用户1172465
  • App开发:模拟服务器数据接口 - MockApi

    为了方便app开发过程中,不受服务器接口的限制,便于客户端功能的快速测试,可以在客户端实现一个模拟服务器数据接口的MockApi模块。本篇文章就尝试为使用gra...

    用户1172465
  • 学界 | 学习顶级玩家Replay,人工智能学会了星际争霸的「大局观」

    选自arXiv 机器之心编译 参与:李泽南 学会了哥的运营,剩下的就是 A 了——「F91」孙一峰。 神经网络是机器学习的一个重要分支,近年来随着深度学习的兴起...

    机器之心
  • 聊聊BinaryLogClient的connect

    mysql-binlog-connector-java-0.20.1/src/main/java/com/github/shyiko/mysql/binlog/...

    codecraft
  • 【原创】自己动手写一个服务网关

    Java高级架构
  • 自己动手写一个服务网关

    如图所示,在不使用网关的情况下,我们的服务是直接暴露给服务调用方。当调用方增多,势必需要添加定制化访问权限、校验等逻辑。当添加API网关后,再第三方调用端和服...

    java进阶架构师
  • 聊聊BinaryLogClient的connect

    mysql-binlog-connector-java-0.20.1/src/main/java/com/github/shyiko/mysql/binlog/...

    codecraft
  • Spring【AOP模块】就这么简单

    到目前为止,已经简单学习了Spring的Core模块….于是我们就开启了Spring的AOP模块了…在讲解AOP模块之前,首先我们来讲解一下cglib代理、以及...

    乔戈里
  • Android中的序列化:Parcelable和Serializable

    用户1205080

扫码关注云+社区

领取腾讯云代金券