自己像之前购物车列表的也都做过,不过那时候都是用了ListView+ListView嵌套解决,RecyclerView还没出来,编辑全选等逻辑的时候一大堆的逻辑、点击事件,导致自己以后看这些代码也都很吃力,现在又碰到啦,想着就两个字:杜绝!😂
就直接拿淘宝的我的订单了,订单列表+每个订单中商品列表:
思考
- 方案一:淘宝是咋实现的,无论从性能还是效果都是杠杠的,可宝宝我的确不知道啊。😢
- 方案二:ListView+ListView嵌套、RecyclerView+RecyclerView嵌套(这种没尝试过),或者组合嵌套本宝宝都一律不想用,都不知道哪一天活着啥时候就出现不可预知的问题。据查证,ListView嵌套的话,在数据量多的情况下,页面可能会出现崩溃,但是我以前做的列表现在崩溃没崩溃我就不知道了。🙀
- 方案三:RecyclerView很强大,可以有多种不同的布局,最近很多介绍
VLayout布局框架
可以适配多种不同布局,但是我也仔细研究了下,用RecyclerView也可以,不过要将你返回的数据格式重新组装成适用RecyclerView的模型数据,我是考虑到万一产品哪天说我想来个联动编辑操作,那就完完了,所以这种方案也不做考虑吧,如果是公司新开的一些项目,或者引入框架影响比较小的项目,我可能会考虑用第三方的框架。 - 方案四:ExpandableListView:树形菜单展开收起用的比较多,在这里仔细考虑了下似乎是可以尝试的选择,毕竟我也不知道人家牛逼的是怎么实现的啊,总要交个功能出来吧。
实现
ExpandableListView用法大家应该都会,就是要注意几点的地方:
- 始终保持展开:
private void expandListView() {
for (int i = 0; i < mAdapter.getGroupCount(); i++) {
mListView.expandGroup(i);
}
}
- 禁止group的展开收起事件:
mExpandableListView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
@Override
public boolean onGroupClick(ExpandableListView expandableListView, View view, int i, long l) {
// 始终返回true
return true;
}
});
- 底部按钮部分的显示,只能放在childView中处理,作为childView的一部分,在显示最后一个childView的时候显示该view,其他情况都隐藏,这点处理还是有点坑爹的,毕竟人家ExpandableListView用在这里的确有点牵强。
getChildView()部分代码:
@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
ChildHolder holder = null;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.item_order_content, parent, false);
holder = new ChildHolder(convertView);
convertView.setTag(holder);
} else {
holder = (ChildHolder) convertView.getTag();
}
// getChildView方法中isLastChild可以来判断是否是最后一个childView显示
if (isLastChild) {
holder.orderBottomLl.setVisibility(View.VISIBLE);
OrderEntity order = (OrderEntity) getGroup(groupPosition);
holder.setButtons(order);
formatBottomPrice(holder.orderBottomPriceTv, order);
} else {
holder.orderBottomLl.setVisibility(View.GONE);
}
// 省略部分代码
......
return convertView;
}
效果
最终效果实现也都👌了,不过其实我想要说的不是这里,是底部按钮的处理,这个在以前都是通过订单的状态来判断,在哪些订单状态下显示哪些按钮,基本上可以说是固定的,只要通过订单状态来判断显示与隐藏即可,但是如果服务器端跟你说底部按钮需要动态返回呢。听到的第一反映就是NO!NO!NO!第一想法是那我启不是要不断的动态添加按钮,删除按钮,这界面能扛的住么。所以说啊,事情不是绝对的,不要不思考就予以否定,解决方案还是有的。
动态按钮处理
服务器返回格式:Map<key, value>,key是唯一的,value是按钮文字;
- 封装一个操作按钮实体类:
public static class OperatorButton implements Comparable<OperatorButton> {
public String buttonKey;
public String buttonValue;
// 顺序:ui界面中按钮从左到右的顺序
public int sort;
// 按钮的样式,可以添加你自己需要的...
public int textColor;
public int bgResource;
// 为每种按钮定义点击事件的ID
public int clickId;
}
- 解析json的时候根据不同的key,创建操作按钮类,添加到list中;
- 排序list集合,
Collections.sort(list);
; - 在adapter中循环list,当然事先放三个按钮(因为我的UI界面最多只有三个),依次从左到右取出按钮显示,设置,剩余按钮隐藏;
/**
* 底部按钮处理
* @param entity
*/
public void setButtons(final OrderEntity entity) {
List<OrderEntity.OperatorButton> list = entity.operatorList;
// 操作按钮list是空的,直接隐藏底部view
if (ListUtils.isEmpty(list)) {
buttonsLl.setVisibility(View.GONE);
return;
}
// 显示底部view,但是事先隐藏三个按钮
buttonsLl.setVisibility(View.VISIBLE);
btnOneTv.setVisibility(View.GONE);
btnTwoTv.setVisibility(View.GONE);
btnThreeTv.setVisibility(View.GONE);
for (int i = 0; i < list.size(); i++) {
final OrderEntity.OperatorButton bean = list.get(i);
// 为了避免服务器返回超过3个以上的按钮,还是做下判断,以免数组越界,而且有可能返回不在ui上显示的状态,我就判断了下按钮文字是否为空
if (i < buttons.size() && !StringUtils.isNull(bean.buttonValue)) {
TextView txt = buttons.get(i);
txt.setVisibility(View.VISIBLE);
txt.setText(bean.buttonValue);
if (bean.textColor != 0) {
txt.setTextColor(mContext.getResources().getColor(bean.textColor));
}
if (bean.bgResource != 0) {
txt.setBackgroundResource(bean.bgResource);
}
txt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// mListener是自定义的点击事件接口,外部activity可以实现
if (mListener != null) {
mListener.onClick(bean.clickId, entity);
}
}
});
}
}
}
}
😂这是我暂时能想到的比较顺的处理方式,当然还有其他方式,比如我的同事就提供了一种,让按钮实现一个接口,这个接口专门处理根据key来动态设置按钮的样式等,但是我当时想这样的话我可能要自定义按钮,里面根据key来完成处理,也可以相对麻烦了些。
最后,这只是我自己处理的一种方式,还有其他方式的大家可以一起交流下,一个人的思维有限,一起交流就会有更多不同的方案。