转载请标明出处!
先放上效果图
整体用法和PullToRefreshListView差不多,但有些细节是它独有的,而且貌似还有个bug需要注意。下面进入正题:
主要有三步:1、布局文件;2、Activity;3、Adapter。
1、布局文件:
<com.handmark.pulltorefresh.library.PullToRefreshExpandableListView
xmlns:ptr="http://schemas.android.com/apk/res-auto"
android:id="@+id/epLv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/head_cont"
android:divider="@null"
ptr:ptrShowIndicator="false" //将一级菜单头部的图标去掉
ptr:ptrMode="both"/> //设置刷新的方式
<!--ptr:ptrHeaderBackground="@android:color/darker_gray"-->//设置刷新时提示部分的背景颜色
<!--ptr:ptrHeaderTextColor="@android:color/white"-->//设置刷新时提示部分的字体颜色
<!--ptr:ptrAnimationStyle="rotate"-->//设置刷新时提示部分的动画风格
2、Activity:
2.1、需继承自ExpandableListActivity
public class MyBillActivity extends ExpandableListActivity {}
2.2、声明必要的变量
/**
* 现金流水列表
*/
private PullToRefreshExpandableListView mPtrExpandableLv = null;
/**
* 一级菜单数据源
*/
private List<String> mParents = null;
/**
* 二级菜单数据源
*/
private Map<String, List<BillEntity.CommissionHistoryList.BillInfo>> mChildren = null;
/**
* 适配器
*/
private BillAdapter mAdapter = null;
2.3、初始化PullToRefreshExpandableListView及对其进行基本的设置
mPtrExpandableLv = (PullToRefreshExpandableListView) findViewById(R.id.epLv);
mPtrExpandableLv.getRefreshableView().setGroupIndicator(null);//将一级菜单头部的图标去掉
// 设置列表下拉刷新时的加载提示
this.mPtrExpandableLv.getLoadingLayoutProxy(true, false).setPullLabel("下拉刷新...");
this.mPtrExpandableLv.getLoadingLayoutProxy(true, false).setRefreshingLabel("正在刷新...");
this.mPtrExpandableLv.getLoadingLayoutProxy(true, false).setReleaseLabel("松开刷新...");
// 设置列表上拉加载时的加载提示
this.mPtrExpandableLv.getLoadingLayoutProxy(false, true).setPullLabel("上拉加载...");
this.mPtrExpandableLv.getLoadingLayoutProxy(false, true).setRefreshingLabel("正在加载...");
this.mPtrExpandableLv.getLoadingLayoutProxy(false, true).setReleaseLabel("松开加载更多...");
2.4、设置刷新监听
// 刷新时
mPtrExpandableLv.setOnRefreshListener(newPullToRefreshBase.OnRefreshListener<ExpandableListView>() {
@Override
public void onRefresh(PullToRefreshBase<ExpandableListView> refreshView) {
//下拉时执行的操作
if (PullToRefreshBase.Mode.PULL_FROM_START == refreshView.getCurrentMode()) {
HttpHelper.GetDataListInfo(
"CommissionHistory",
0,
"{'userid':" + "'" + mUserId + "'" + "}",
mHandler,
HANDLER_GET_BILL_INFO);
//上拉时执行的操作
} else if (PullToRefreshBase.Mode.PULL_FROM_END == refreshView.getCurrentMode()) {
int count = 0;
//将拿到的数据的总数拿出来
for (String s : mParents) {
count += mChildren.get(s).size();
}
//获取加载更多Index参数
int index = UIOperationUtility.calculateIndex(count);
HttpHelper.GetDataListInfo(
"CommissionHistory",
index,
"{'userid':" + "'" + mUserId + "'" + "}",
mHandler,
HANDLER_ADD_BILL_INFO);
}
}
});
2.5、配置Adapter。 注意:是用Activity配置上Adapter
/**
* UI异步处理对象
*/
class InnerHandler extends Handler {
@Override
public void handleMessage(Message msg) {
//下拉刷新时
//当拿到现金流水数据后
if (msg.what == HANDLER_GET_BILL_INFO) {
String json = (String) msg.obj;
//拿取一级菜单的数据(现金流水日期)
mParents = HttpResolveUtility.resolveParentDate(json);
//拿取二级菜单的数据(现金流水具体数据)
mChildren = HttpResolveUtility.resolveBillInfo(json);
//显示数据
mAdapter = new BillAdapter(mParents, mChildren, MyBillActivity.this);
MyBillActivity.this.setListAdapter(mAdapter);//注意此处是用Activity配置上Adapter
//设置二级菜单默认打开
int groupCount = mPtrExpandableLv.getRefreshableView().getCount();
for (int i=0; i<groupCount; i++) {
mPtrExpandableLv.getRefreshableView().expandGroup(i);
};
//停止下拉刷新动画
mPtrExpandableLv.onRefreshComplete();
//上拉加载时
} else if (msg.what == HANDLER_ADD_BILL_INFO) {
String json = (String) msg.obj;
//拿取新加载的一级菜单数据
List<String> addedParents = HttpResolveUtility.resolveParentDate(json);
//遍历新拿到的数据,如果不包含于原来的一级菜单数据源,那么将它加进去
for (String str : addedParents) {
if (!mParents.contains(str)) {
mParents.add(str);
}
}
//拿取新加载的二级菜单数据
Map<String, List<BillEntity.CommissionHistoryList.BillInfo>> addedChildren = HttpResolveUtility.resolveBillInfo(json);
//将新拿到的数据里的键值对都拿出来
Set<Map.Entry<String, List<BillEntity.CommissionHistoryList.BillInfo>>> sets = addedChildren.entrySet();
//迭代每一个键值对
Iterator<Map.Entry<String, List<BillEntity.CommissionHistoryList.BillInfo>>> iterator = sets.iterator();
while (iterator.hasNext()) {
Map.Entry<String, List<BillEntity.CommissionHistoryList.BillInfo>> entry = iterator.next();
//如果本来的二级菜单的Map不包含这条键值对的Key,直接将这个键值对放入Map
if (!mChildren.containsKey(entry.getKey())) {
mChildren.put(entry.getKey(), entry.getValue());
}
//如果本来的二级菜单的Map包含这条键值对的Key,那么将这条键值对的value(List集合)追加到原本已有键值对的value后面
if (mChildren.containsKey(entry.getKey())) {
mChildren.get(entry.getKey()).addAll(entry.getValue());
}
}
//加载更多(方法内部就是notifyDataSetChanged())
mAdapter.update(mParents, mChildren);
//二级菜单默认打开
int groupCount = mPtrExpandableLv.getRefreshableView().getCount();
for (int i = 0; i < groupCount; i++) {
mPtrExpandableLv.getRefreshableView().expandGroup(i);
}
//停止上拉刷新动画
mPtrExpandableLv.onRefreshComplete();
} else {
Toast.makeText(MyBillActivity.this, getString(R.string.http_connect_timeout), Toast.LENGTH_SHORT).show();
}
}
}
3、Adapter。注意:它的getChildrenCount(int groupPosition)方法貌似是有BUG的,用时它会自动调用不合法的参数,我是加了个判断将其规避。
public class BillAdapter extends BaseExpandableListAdapter {//需继承自BaseExpandableListAdapter
/**
* 一级菜单数据源
*/
List<String> parents = null;
/**
* 二级菜单数据源
*/
Map<String, List<BillEntity.CommissionHistoryList.BillInfo>> map = null;
/**
* 上下文对象
*/
Context context = null;
/**
* 适配器构造方法
*
* @param parents
* @param map
* @param context
*/
public BillAdapter(List<String> parents, Map<String, List<BillEntity.CommissionHistoryList.BillInfo>> map,
Context context) {
super();
this.parents = parents;
this.map = map;
this.context = context;
}
@Override
public int getGroupCount() {
return parents.size();
}
@Override
public int getChildrenCount(int groupPosition) {
//规避框架自动调用不合法参数的错误
if(groupPosition>=parents.size()){
return 0;
}
String key = parents.get(groupPosition);
int size = map.get(key).size();
return size;
}
@Override
public Object getGroup(int groupPosition) {
return parents.get(groupPosition);
}
@Override
public Object getChild(int groupPosition, int childPosition) {
String key = parents.get(groupPosition);
return (map.get(key).get(childPosition));
}
@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
@Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
@Override
public boolean hasStableIds() {
return true;
}
/**
* 编写一级菜单的视图
*
* @param groupPosition
* @param isExpanded
* @param convertView
* @param parent
* @return
*/
@Override
public View getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.item_bill_list_head, null);
}
TextView tv = (TextView) convertView
.findViewById(R.id.bill_date);
tv.setText(parents.get(groupPosition));
return convertView;
}
/**
* 编写二级菜单的视图
*
* @param groupPosition
* @param childPosition
* @param isLastChild
* @param convertView
* @param parent
* @return
*/
@Override
public View getChildView(int groupPosition, int childPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
String key = parents.get(groupPosition);
BillEntity.CommissionHistoryList.BillInfo info = map.get(key).get(childPosition);
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.item_bill_list_cont, null);
}
TextView tvBillName = (TextView) convertView
.findViewById(R.id.bill_name);
tvBillName.setText("订单" + " " + info.getName());
String amount = info.getAmount();
TextView tvMoney = (TextView) convertView
.findViewById(R.id.bill_money);
if (amount.charAt(0) == '-') {
tvMoney.setText(amount);
} else {
tvMoney.setText("+" + amount);
}
;
TextView tvCode = (TextView) convertView
.findViewById(R.id.bill_code);
tvCode.setText(info.getCode());
TextView tvBillSource = (TextView) convertView
.findViewById(R.id.bill_source);
tvBillSource.setText(info.getOpReason());
return convertView;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
// TODO Auto-generated method stub
return true;
}
/**
* 列表加载更多列表加载更多
* @param parents 更改后的一级数据源
* @param map 更改后的二级数据源
*/
public void update(List<String> parents, Map<String, List<BillEntity.CommissionHistoryList.BillInfo>> map) {
this.parents = parents;
this.map = map;
notifyDataSetChanged();
}
}