前言

本文针对自定义组件进行一些分析。还是那句老话“授之于鱼不如授之以渔”。今天要讲的是一个自定义的可以分页的ListView。

网上都讲了些ListView分页的方法,那么为什么我在这里还需要自己写一个呢?

①分页功能是很多时候都需要的;

②网上的很多代码和数据绑定在一起的,要使用的话还需要改些东西,更重要的是代码很啰嗦、很糟糕(当然只是个人风格问题,至少我是这么认为);

③或者是功能太强大而我们仅仅是需要分页功能,但是又不好分离出来。

所以写个分页的listview就很有必要了,尤其是可以直接使用的listview。

效果图

说得再多都是苍白无力的理论,先给个效果图看看吧。

分析

这个组件看上去简单,不过需要处理的细节还是挺多的。首先要明确这个组件是做什么的。简单地讲就是做分页显示或分页加载的。那么需要考虑这两个问题:

1、什么时候需要分页?

那么什么时候需要分页呢,这个答案是很明朗的。当数据数量不能填满一屏的时候那么就不用分页。在这个组件中我是这么来定分页的:首次加载的数量大于一屏显示数量时那么就认为有分页的可能,滑动到底部就需要“more”这个按钮。

2、何时加载分页信息?

至于何时进行分页,这是这个组件的关键。理论上是滑动到listview最底部的时候就需要显示一个“more”按钮,点击后进行分页,但是实际上我们需要做一定的小改动,也就是提前加载,及还没有滑动到最底部就开始加载。这样看来主要的问题就落在了如何判断是否滑动到了最底部。这问题在代码中讨论吧。

代码实现

MoreListView 组件代码:

 /***********************************************************
*@description : This class function is you can load more datas
*
* @create author : kwzhang
* @create date :2013-6-19
* @modify author :
* @modify date :
* @contact: vanezkw@163.com
*
**********************************************************/
package com.example.demo; import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.AbsListView;
import android.widget.Button;
import android.widget.ListAdapter;
import android.widget.ListView; /**
* @author kwzhang
*
*/
public class MoreListView extends ListView { private View mFooter;
private LoadingListener mListener;
private boolean mShowMore = true; /**
* @param context
* @param attrs
*/
public MoreListView(Context context, AttributeSet attrs) {
super(context, attrs);
initFooter(context);
} /**
* @param mListener
* the mListener to set
*/
public void setListener(LoadingListener mListener) {
this.mListener = mListener;
setOnScrollListener(innerOnScrollListener);
} /**
* @return the mShowMore
*/
public boolean isShowMore() {
return mShowMore;
} /**
* @param mShowMore
* the mShowMore to set
*/
public void setShowMore(boolean mShowMore) {
this.mShowMore = mShowMore;
} /**
* @description :TODO
* @author : kwzhang
* @create :2013-6-19
* @param context
* @return :void
*/
protected void initFooter(Context context, View footer) {
if (null == footer) {
Button bt = new Button(context);
bt.setText("More ...");
mFooter = bt;
} else {
mFooter = footer;
}
mFooter.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (getFooterViewsCount() > 0) {
removeFooterView(mFooter);
}
if (null != mListener) {
mListener.loadingMore(MoreListView.this);
}
}
});
addFooterView(mFooter);
} private void initFooter(Context context) {
initFooter(context, null);
} @Override
public void setAdapter(ListAdapter adapter) {
super.setAdapter(adapter);
removeFooterView(mFooter);
} /**
* @param context
* @param attrs
* @param defStyle
*/
public MoreListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initFooter(context);
} /**
* @param context
*/
public MoreListView(Context context) {
super(context);
initFooter(context);
} private OnScrollListener innerOnScrollListener = new OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// mLastVisibleItemIndex+1 == getAdapter().getCount()时说明滑动到最底端。
// mLastVisibleItemIndex+3 是为了在倒数第二个就开始预先加载。不过此方法是采样调用,不一定及时执行。
if (mShowMore) {
int count = getAdapter().getCount();
if ((mVisibleItemCount < count) && ((mLastVisibleItemIndex + 3) >= count) && (getFooterViewsCount() == 0)) {
addFooterView(mFooter);
}
}
} private int mLastVisibleItemIndex;
private int mVisibleItemCount = -1; @Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
mLastVisibleItemIndex = firstVisibleItem + visibleItemCount - 1; mVisibleItemCount = visibleItemCount; }
}; public static interface LoadingListener {
public void loadingMore(View view);
}
}

测试Demo Activity:

 package com.example.demo;

 import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter; public class ActDemo extends Activity implements MoreListView.LoadingListener { private MoreListView listView;
private ArrayAdapter<String> mAdapter; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (MoreListView) findViewById(R.id.listview);
mAdapter = getAdapter();
listView.setAdapter(mAdapter);
listView.setListener(this);
} private ArrayAdapter<String> getAdapter() {
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1);
for (int i = 0; i < 20; i++) {
adapter.add("测试数据" + i);
}
return adapter;
} @Override
public void loadingMore(View view) {
for (int i = 0; i < 10; i++) {
mAdapter.add("新数据" + i);
}
if (mAdapter.getCount() > 60) {
listView.setShowMore(false);
}
}
}

测试Demo XML布局:

<com.example.demo.MoreListView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/listview"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />

从上面的测试demo中可以看出使用起来非常方便。

1、protected void initFooter(Context context, View footer)方法说明一下。这个方法是给外部提供传递view的,这个view就是显示“more”的那个view,传null的话就有个默认的Button。

2、public void setListener(LoadingListener mListener)需要分页的话就必须调用这个方法。点击“more”按钮的时候其实去调用了LoadingListener.loadingMore(View view)方法。你可以根据需要进行实现。

总结

这样的组件就比较简单实用,也没有太复杂的代码,一看就能懂。我们需要的不正是这样简单的代码吗。随便说一下如果你需要更强的的Listview的话可以去看看AmazingListView项目。下拉刷新你可以看看johannilsson-android-pulltorefresh项目

PS:对文中有不解之处欢迎交流,有什么好的建议也可以留言。留下个QQ学习群:196761677。

自定义组件之MoreListView的更多相关文章

  1. Android开发之自定义组件和接口回调

    说到自定义控件不得不提的就是接口回调,在Android开发中接口回调用的还是蛮多的.在这篇博客开始的时候呢,我想聊一下iOS的自定义控件.在iOS中自定义控件的思路是继承自UIView, 在UIVie ...

  2. Android自定义组件

    [参考的原文地址] http://blog.csdn.net/l1028386804/article/details/47101387效果图: 实现方式: 一:自定义一个含有EditText和Butt ...

  3. 自己写的几个android自定义组件

    http://www.see-source.com/androidwidget/list.html 多多指点,尤其是自定义组件的适配问题,希望能有更好的方法

  4. PhoneGap: Android 自定义组件

    Hello Core Demo Plugin Development(组件部署): http://docs.phonegap.com/en/2.0.0/guide_plugin-development ...

  5. android开发之自定义组件

    android开发之自定义组件 一:自定义组件: 我认为,自定义组件就是android给我们提供的的一个空白的可以编辑的图片,它帮助我们实现的我们想要的界面,也就是通过自定义组件我们可以把我们要登入的 ...

  6. HTML5 UI框架Kendo UI Web教程:创建自定义组件(三)

    Kendo UI Web包 含数百个创建HTML5 web app的必备元素,包括UI组件.数据源.验证.一个MVVM框架.主题.模板等.在前面的2篇文章<HTML5 Web app开发工具Ke ...

  7. HTML5 UI框架Kendo UI Web中如何创建自定义组件(二)

    在前面的文章<HTML5 UI框架Kendo UI Web自定义组件(一)>中,对在Kendo UI Web中如何创建自定义组件作出了一些基础讲解,下面将继续前面的内容. 使用一个数据源 ...

  8. HTML5 UI框架Kendo UI Web自定义组件(一)

    Kendo UI Web包含数百个创建HTML5 web app的必备元素,包括UI组件.数据源.验证.一个MVVM框架.主题.模板等.在Kendo UI Web中如何创建自定义组件呢,在下面的文章中 ...

  9. axure复用-自定义组件,母版(模板)

    组件(控件)是用于设计线框图的用户界面元素.在组件(控件)面板中包含有常用的控件库,如按钮.图片.文本框等.从组件面板中拖动一个控件到线框图区域中,就可以添加一个组件.组件可以从一个线框图中被拷贝(C ...

随机推荐

  1. ActiveMQ第二弹:使用Spring JMS与ActiveMQ通讯

    本文章的完整代码可从我的github中下载:https://github.com/huangbowen521/SpringJMSSample.git 上一篇文章中介绍了如何安装和运行ActiveMQ. ...

  2. 记一次在StackOverFlow上问问题的经历

    最近一直在做测试方面的事情,被测的一些功能需要连接到FTP服务器上.而我在做本地测试时为了方便,就使用java写了一个简单的ftp服务器,可以在命令行下直接启动运行. 当时在main函数里是这样写的. ...

  3. 深入浅出OOP(一): 多态和继承(早期绑定/编译时多态)

    在本系列中,我们以CodeProject上比较火的OOP系列博客为主,进行OOP深入浅出展现. 无论作为软件设计的高手.或者菜鸟,对于架构设计而言,均需要多次重构.取舍,以有利于整个软件项目的健康构建 ...

  4. [Python爬虫] 在Windows下安装PhantomJS和CasperJS及入门介绍(上)

    最近在使用Python爬取网页内容时,总是遇到JS临时加载.动态获取网页信息的困难.例如爬取CSDN下载资源评论.搜狐图片中的“原图”等,此时尝试学习Phantomjs和CasperJS来解决这个问题 ...

  5. maven源码分析- mvn.bat分析

    第一次知道MAVEN是在2008年,当时想分析geoserver这个开源项目,发现该项目采用了maven进行项目管理,当时粗略的学习了一下.真正在工作中使用是在09年下半年,个人感觉使用起来还是非常好 ...

  6. hdu 2191 多重背包 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活

    http://acm.hdu.edu.cn/showproblem.php?pid=2191 New~ 欢迎“热爱编程”的高考少年——报考杭州电子科技大学计算机学院关于2015年杭电ACM暑期集训队的 ...

  7. centos下linux运行asp网站搭建配置-mono+nginx

    一.首先安装一些需要的软件包 1.  首先更新CentOS上的软件包:yum –y update. 2.  安装一些需要的库: yum -y install gcc gcc-c++ bison pkg ...

  8. Node初学者入门,一本全面的NodeJS教程(转载)

    分类 JS学习   发布 ourjs  2013-12-02 注意 转载须保留原文链接,译文链接,作者译者等信息.     作者: Manuel Kiessling  翻译: goddyzhao &a ...

  9. 【转】Android布局优化之ViewStub

    ViewStub是Android布局优化中一个很不错的标签/控件,直接继承自View.虽然Android开发人员基本上都听说过,但是真正用的可能不多. ViewStub可以理解成一个非常轻量级的Vie ...

  10. 制作6寸 kindle pdf

    设置word 纸张大小为 90mm*117mm 然后保存为 pdf 就好了.