没有办法,米公设计的一个UI是stickyheaderlist(头部停留)和分页加载数据功能的整合,笔者原以为是米工自己拍着脑袋想出来的,还想进一步讨论一下,后来才发现支付宝也是这么做的,那好吧,做呗。
先上Demo完成效果图(有点简陋,但是这样代码却也更清晰了)
下面分别介绍一下StickyHeaderListView(这么长!后面都简写成StickyLV好了)和分页加载:
一、StickyLV(头部停留listview)
其实这个没什么好说的,因为是开源组件,github上都有介绍和demo,这里就简单的讲一下几个关键的地方吧
a.StickyLV的对应的Adapter要继承StickyListHeadersAdapter接口,并实现其中的getHeaderView和getHeaderId方法,前者和普通的Adapter的getView方法一样,需要注意的是后者,只有在返回的int值和上一个返回值不同时,才会显示HeaderView,同时,要将返回值的计算式关联到position上。
b.同样在StickyLV对应的Adapter中,尽管为StickyLV添加了HeaderView,但是getCount()返回的仍然是内容列表项的数量,而不包括HeaderView的数量。
二、分页加载更多数据
a.首先分页加载通常出现在服务器数据请求中,因为一次性加载过多的数据可能会带来不好的用户体验,及不要的性能开销。所以通过分页加载来平滑加载过程。
b.分页数据加载事件由listview触发,主要通过重写onScrollStateChanged方法来实现。
c.最后定义一个OnLoadingMoreListener接口,在其中定义一个加载数据的方法OnLoadingMore。并将接口作为参数由外部调用进行初始化动作,这就是所谓的代理或者说监听者模式。
d.最后还有footerView的定义、添加及隐藏。
主要实现代码
StickyListAdapter:
package com.wly.sticky_pagelist;
import java.util.ArrayList;
import android.content.Context;
import android.graphics.Color;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import com.emilsjolander.components.stickylistheaders.StickyListHeadersAdapter;
public class StickyListAdapter extends BaseAdapter implements StickyListHeadersAdapter {
private ArrayList<String> list;
private Context mContext;
public void init(Context context,ArrayList<String> list) {
this.list = list;
this.mContext = context;
mContext = context;
}
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int position) {
return list.get(position);
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView itemView = new TextView(mContext);
itemView.setText("Item:" + position);
itemView.setTextSize(20);
return itemView;
}
@Override
public View getHeaderView(int position, View convertView, ViewGroup parent) {
TextView headView = new TextView(mContext);
headView.setText("Head:" + (position/10));
headView.setTextSize(24);
headView.setTextColor(new Color().RED);
return headView;
}
/**
* 决定header出现的时机,如果当前的headerid和前一个headerid不同时,就会显示
*/
@Override
public long getHeaderId(int position) {
return position/10 + 0x1234;
}
}
在导入的StickyListHeadersListView中定义接口OnLoadingMoreListener
/**
* 加载更多数据回调接口
*
*/
public interface OnLoadingMoreLinstener {
/**
* 加载更多数据回调方法,由组件自身触发
*/
void OnLoadingMore();
}
并修改StickyListHeadersListView的mOnScrollListener接口对象的onScrollStateChanged方法,如下:
public OnScrollListener mOnScrollListener = new OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
Log.e("parent","onScrollStateChanged");
if (mOnScrollListenerDelegate != null) {
mOnScrollListenerDelegate.onScrollStateChanged(view,
scrollState);
}
// 滑到底部后自动加载,判断listview已经停止滚动并且最后可视的条目等于adapter的条目
if (scrollState == OnScrollListener.SCROLL_STATE_FLING) {
} else if (scrollState == OnScrollListener.SCROLL_STATE_TOUCH_SCROLL
|| scrollState == OnScrollListener.SCROLL_STATE_IDLE) {
if (getLastVisiblePosition() == (getCount() - 1)) {
Log.e("Sticky","--拖动到最后--");
if(loadMoreListener != null) {
loadMoreListener.OnLoadingMore();
}
}
}
}
最后,界面MainActivity
package com.wly.sticky_pagelist;
import java.util.ArrayList;
public class MainActivity extends Activity implements OnHeaderClickListener,AdapterView.OnItemClickListener
,OnLoadingMoreLinstener {
private LayoutInflater inflater;
ArrayList<String> list;
StickyListAdapter adapter;
StickyListHeadersListView stickyLV;
private RelativeLayout moredata;
private View progressBarView;
private TextView progressBarTextView;
private AnimationDrawable loadingAnimation; //加载更多,动画
private boolean isLoading = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
list = new ArrayList<String>();
for(int i=1;i<=15;i++) {
list.add(i + "");
}
adapter = new StickyListAdapter();
adapter.init(this, list);
inflater = LayoutInflater.from(this);
moredata = (RelativeLayout)inflater.inflate(R.layout.moredata, null);
stickyLV = (StickyListHeadersListView)this.findViewById(R.id.stickyList);
progressBarView = (View) moredata.findViewById(R.id.loadmore_foot_progressbar);
progressBarTextView = (TextView) moredata.findViewById(R.id.loadmore_foot_text);
loadingAnimation = (AnimationDrawable) progressBarView.getBackground();
stickyLV.addFooterView(moredata);
stickyLV.setAdapter(adapter);
stickyLV.setOnItemClickListener(this);
stickyLV.setOnHeaderClickListener(this);
stickyLV.setLoadingMoreListener(this);
}
public void loadingFinished() {
if (null != loadingAnimation && loadingAnimation.isRunning()) {
loadingAnimation.stop();
}
progressBarView.setVisibility(View.INVISIBLE);
progressBarTextView.setVisibility(View.INVISIBLE);
isLoading = false;
adapter.notifyDataSetChanged();
}
@Override
public void OnLoadingMore() {
progressBarView.setVisibility(View.VISIBLE);
progressBarTextView.setVisibility(View.VISIBLE);
loadingAnimation.start();
if(!isLoading) {
isLoading = true;
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
for(int i=0;i<5;i++) {
list.add((Math.random() * 40) + "");
}
loadingFinished();
}
},1200);
}
}
@Override
public void onHeaderClick(StickyListHeadersListView l, View header,
int itemPosition, long headerId, boolean currentlySticky) {
Toast.makeText(this, "header:" + headerId, Toast.LENGTH_SHORT).show();
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
Toast.makeText(this, "item:" + position, Toast.LENGTH_SHORT).show();
}
}
参考文档:https://github.com/emilsjolander/StickyListHeaders
完整工程下载:http://download.csdn.net/detail/u011638883/7062457
O啦~~~
装载请保留出处:http://blog.csdn.net/u011638883/article/details/21316779
谢谢!!