在项目开发过程中,遇到了使用listView需要让选中项保持高亮状态(即选中状态保持不变),且数据是二级联动。由于item点击过后瞬间颜色就会恢复原状,视觉上感觉没有选中,此demo中通过改变选中后item的背景色实现预期效果。两张点击前后对比图如下。之前写过一篇文章,数据是使用list<string>类型,现在改为使用数据集合,直接解析json数据作为数据源使用。
底部附demo下载地址
项目比较简单,下面是项目截图:
在此文件中配置了模拟了一条json数据作为数据源,需要的小伙伴根据自己公司的数据样式进行数据集合的调整。
public class MainActivity extends Activity implements SecondListAdapter.onClick {
private ListView listview, listView2;
String makeJson = "[\n" +
" {\n" +
" \"GroupCode\": \"QJL\", \n" +
" \"GroupName\": \"钟点类\", \n" +
" \"ItemList\": [\n" +
" {\n" +
" \"ReMark\": \"商场、企事业单位及宾馆\", \n" +
" \"ItemCode\": \"CBL\", \n" +
" \"AppPic\": \"https://www.hongjimeng.net//UploadFiles/ServiceItemImage/itemCodeCBL.png\", \n" +
" \"ItemName\": \"擦玻璃\"\n" +
" }, \n" +
" {\n" +
" \"ReMark\": \"彻底清洁,让您的家焕然一新\", \n" +
" \"ItemCode\": \"JTQJ\", \n" +
" \"AppPic\": \"https://www.hongjimeng.net//UploadFiles/ServiceItemImage/itemCodeJTQJ.png\", \n" +
" \"ItemName\": \"家庭清洁\"\n" +
" }, \n" +
" {\n" +
" \"ReMark\": \"服务准时,美味卫生,个人家庭厨师\", \n" +
" \"ItemCode\": \"JTZF\", \n" +
" \"AppPic\": \"https://www.hongjimeng.net//UploadFiles/ServiceItemImage/itemCodeJTZF.png\", \n" +
" \"ItemName\": \"家庭做饭\"\n" +
" }, \n" +
" {\n" +
" \"ReMark\": \"地面、顶棚、瓷片清洁\", \n" +
" \"ItemCode\": \"KFQJ\", \n" +
" \"AppPic\": \"https://www.hongjimeng.net//UploadFiles/ServiceItemImage/itemCodeKFQJ.png\", \n" +
" \"ItemName\": \"空房清洁\"\n" +
" }\n" +
" ]\n" +
" }, \n" +
" {\n" +
" \"GroupCode\": \"BYL\", \n" +
" \"GroupName\": \"保养类\", \n" +
" \"ItemList\": [\n" +
" {\n" +
" \"ReMark\": \"保鲜室内风轮,门边条,内部深层清洁保养\", \n" +
" \"ItemCode\": \"BXBY\", \n" +
" \"AppPic\": \"https://www.hongjimeng.net//UploadFiles/ServiceItemImage/itemCodeBXBY.png\", \n" +
" \"ItemName\": \"冰箱保养\"\n" +
" }, \n" +
" {\n" +
" \"ReMark\": \"对厨房餐具、内饰清洗\", \n" +
" \"ItemCode\": \"CFBY\", \n" +
" \"AppPic\": \"https://www.hongjimeng.net//UploadFiles/ServiceItemImage/itemCodeCFBY.png\", \n" +
" \"ItemName\": \"厨房保养\"\n" +
" }, \n" +
" {\n" +
" \"ReMark\": \"对木质地板、石质地板养护\", \n" +
" \"ItemCode\": \"DBBY\", \n" +
" \"AppPic\": \"https://www.hongjimeng.net//UploadFiles/ServiceItemImage/itemCodeDBBY.png\", \n" +
" \"ItemName\": \"地板保养\"\n" +
" }, \n" +
" {\n" +
" \"ReMark\": \"对木质家具清洁、打蜡、抛光养护\", \n" +
" \"ItemCode\": \"JJBY\", \n" +
" \"AppPic\": \"https://www.hongjimeng.net//UploadFiles/ServiceItemImage/itemCodeJJBY.png\", \n" +
" \"ItemName\": \"家具保养\"\n" +
" }, \n" +
" {\n" +
" \"ReMark\": \"清洁、去污、除垢、养护等专业服务\", \n" +
" \"ItemCode\": \"SFQX\", \n" +
" \"AppPic\": \"https://www.hongjimeng.net//UploadFiles/ServiceItemImage/itemCodeSFQX.png\", \n" +
" \"ItemName\": \"沙发保养\"\n" +
" }, \n" +
" {\n" +
" \"ReMark\": \"对卫生间用具消毒\", \n" +
" \"ItemCode\": \"WSJ\", \n" +
" \"AppPic\": \"https://www.hongjimeng.net//UploadFiles/ServiceItemImage/itemCodeWSJ.png\", \n" +
" \"ItemName\": \"卫生间保养\"\n" +
" }, \n" +
" {\n" +
" \"ReMark\": \"洗衣桶内外、下水管道及门胶圈清洗\", \n" +
" \"ItemCode\": \"XYBY\", \n" +
" \"AppPic\": \"https://www.hongjimeng.net//UploadFiles/ServiceItemImage/itemCodeXYBY.png\", \n" +
" \"ItemName\": \"洗衣机保养\"\n" +
" }, \n" +
" {\n" +
" \"ReMark\": \"饮水机清洗,延长使用寿命\", \n" +
" \"ItemCode\": \"YSJX\", \n" +
" \"AppPic\": \"https://www.hongjimeng.net//UploadFiles/ServiceItemImage/itemCodeYSJX.png\", \n" +
" \"ItemName\": \"饮水机清洗\"\n" +
" }\n" +
" ]\n" +
" }, \n" +
" {\n" +
" \"GroupCode\": \"QXL\", \n" +
" \"GroupName\": \"清洗类\", \n" +
" \"ItemList\": [\n" +
" {\n" +
" \"ReMark\": \"对窗帘进行深度清洁、消毒杀菌\", \n" +
" \"ItemCode\": \"CLQX\", \n" +
" \"AppPic\": \"https://www.hongjimeng.net//UploadFiles/ServiceItemImage/itemCodeCLQX.png\", \n" +
" \"ItemName\": \"窗帘清洗\"\n" +
" }, \n" +
" {\n" +
" \"ReMark\": \"对优质地毯杀菌、杀虫\", \n" +
" \"ItemCode\": \"DTQX\", \n" +
" \"AppPic\": \"https://www.hongjimeng.net//UploadFiles/ServiceItemImage/itemCodeDTQX.png\", \n" +
" \"ItemName\": \"地毯清洗\"\n" +
" }\n" +
" ]\n" +
" }, \n" +
" {\n" +
" \"GroupCode\": \"QTL\", \n" +
" \"GroupName\": \"其他类\", \n" +
" \"ItemList\": [\n" +
" {\n" +
" \"ReMark\": \"进行维修服务时收取工时费,更换零件另算\", \n" +
" \"ItemCode\": \"BXWX\", \n" +
" \"AppPic\": \"https://www.hongjimeng.net//UploadFiles/ServiceItemImage/itemCodeBXWX.png\", \n" +
" \"ItemName\": \"冰箱维修\"\n" +
" }, \n" +
" {\n" +
" \"ReMark\": \"软管、马桶、面盆等室外管道的疏通\", \n" +
" \"ItemCode\": \"GDST\", \n" +
" \"AppPic\": \"https://www.hongjimeng.net//UploadFiles/ServiceItemImage/itemCodeGDST.png\", \n" +
" \"ItemName\": \"管道疏通\"\n" +
" }, \n" +
" {\n" +
" \"ReMark\": \"双重清洗,让您和家人一起轻松呼吸\", \n" +
" \"ItemCode\": \"KTWX\", \n" +
" \"AppPic\": \"https://www.hongjimeng.net//UploadFiles/ServiceItemImage/itemCodeKTWX.png\", \n" +
" \"ItemName\": \"空调清洗\"\n" +
" }, \n" +
" {\n" +
" \"ReMark\": \"\", \n" +
" \"ItemCode\": \"MF\", \n" +
" \"AppPic\": \"https://www.hongjimeng.net//UploadFiles/ServiceItemImage/itemCodeMF.png\", \n" +
" \"ItemName\": \"美缝\"\n" +
" }, \n" +
" {\n" +
" \"ReMark\": \"您来提需求,我们来满足\", \n" +
" \"ItemCode\": \"QT\", \n" +
" \"AppPic\": \"https://www.hongjimeng.net//UploadFiles/ServiceItemImage/itemCodeQT.png\", \n" +
" \"ItemName\": \"其它\"\n" +
" }, \n" +
" {\n" +
" \"ReMark\": \"5扇以下按60元/次计算\", \n" +
" \"ItemCode\": \"SCAZ\", \n" +
" \"AppPic\": \"https://www.hongjimeng.net//UploadFiles/ServiceItemImage/itemCodeSCAZ.png\", \n" +
" \"ItemName\": \"纱窗安装\"\n" +
" }, \n" +
" {\n" +
" \"ReMark\": \"除油消毒,让您告别油烟熏呛\", \n" +
" \"ItemCode\": \"YYJ\", \n" +
" \"AppPic\": \"https://www.hongjimeng.net//UploadFiles/ServiceItemImage/itemCodeYYJ.png\", \n" +
" \"ItemName\": \"油烟机清洗\"\n" +
" }\n" +
" ]\n" +
" }\n" +
"]";
SecondListAdapter secondListAdapter;
FirstListAdapter firstListAdapter;
List<FirstDataBeen> firstData = new ArrayList<>();
Context mContext;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContext = MainActivity.this;
listview = (ListView) findViewById(R.id.listview);
listView2 = (ListView) findViewById(R.id.listview2);
firstData = FirstDataBeen.parseList(makeJson);
firstListAdapter = new FirstListAdapter(firstData, mContext);
listview.setAdapter(firstListAdapter);
// 根据实际情况看看是否需要默认选中项,不需要禁掉下面两行即可
boundToSecondData(firstData.get(0).getGroupCode());//默认选中二级列表
firstListAdapter.setCheckPos(0);// 默认选中第一项
listview.setChoiceMode(ListView.CHOICE_MODE_SINGLE);// CHOICE_MODE_SINGLE是单选模式,选择后ListView刷新
listview.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1,
int pos, long id) {
firstListAdapter.setCheckPos(pos);// 更新选择为当前行
boundToSecondData(firstData.get(pos).getGroupCode());//更新二级列表数据
}
});
}
/**
* @Description: 服务列表二级联动
* @author: 青蜂侠
* @data: 2017/9/25 15:41
* @params: groupCode
*/
public void boundToSecondData(String groupCode) {
secondListAdapter = new SecondListAdapter(getItemList(groupCode), mContext);
secondListAdapter.setOnClick(this);
listView2.setAdapter(secondListAdapter);
}
/**
* @Description: 二级列表数据
* @author: 青蜂侠
* @data: 2017/9/25 15:51
* @params: groupCode
*/
public List<SecondDataBeen> getItemList(String groupCode) {
List<SecondDataBeen> serviceItemBeenList = new ArrayList<>();
for (int i = 0; i < firstData.size(); i++) {
if (groupCode.equals(firstData.get(i).getGroupCode())) {
serviceItemBeenList = firstData.get(i).getServiceItem();
}
}
return serviceItemBeenList;
}
/**
* @Description: 二级列表点击事件
* @author: 青蜂侠
* @data: 2017/9/25 16:01
*/
@Override
public void onClick(String itemName, String itemCode) {
Toast.makeText(this, itemName, Toast.LENGTH_SHORT).show();
}
}
下面是两个适配的代码:
一级列表适配器
public class FirstListAdapter extends BaseAdapter {
private LayoutInflater mInflater;
private Context mContext;
List<FirstDataBeen> Datas;
int checkPos = -1;
public FirstListAdapter(List<FirstDataBeen> list, Context context) {
this.Datas = list;
this.mContext = context;
mInflater = LayoutInflater.from(mContext);
}
public void setCheckPos(int isPos) {
checkPos = isPos;
FirstListAdapter.this.notifyDataSetChanged();
}
@Override
public int getCount() {
return Datas.size();
}
@Override
public Object getItem(int position) {
return Datas.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.list_item_frist, null);
holder = new ViewHolder();
holder.firstImg = (ImageView) convertView.findViewById(R.id.item_first_img);
holder.firstName = (TextView) convertView.findViewById(R.id.item_first_name);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
final FirstDataBeen firstDataBeen = Datas.get(position);
holder.firstName.setText(firstDataBeen.getGroupName());
if (position == checkPos) {// 如果当前的行就是ListView中选中的一行,就更改显示样式
convertView.setBackgroundColor(Color.parseColor("#CCCCCC"));// 更改整行的背景色
holder.firstName.setTextColor(Color.parseColor("#14A1F7"));// 更改字体颜色
holder.firstImg.setVisibility(View.VISIBLE);
holder.firstImg.setImageResource(R.drawable.icon_first_left);//改变中图标
} else {
convertView.setBackgroundColor(Color.parseColor("#ffffff"));
holder.firstName.setTextColor(Color.parseColor("#000000"));
holder.firstImg.setVisibility(View.INVISIBLE);
}
//需要在activity中接收点击事件就打开注释就好了
// holder.firstName.setOnClickListener(new View.OnClickListener() {
// @Override
// public void onClick(View v) {
// if (onFirstClick != null) {
// onFirstClick.onFirstClick(firstDataBeen.getGroupName(), firstDataBeen.getGroupCode());
// }
// }
// });
return convertView;
}
public class ViewHolder {
ImageView firstImg;
TextView firstName;
}
private FirstListAdapter.onFirstClick onFirstClick;
public void setOnClick(FirstListAdapter.onFirstClick onClick) {
this.onFirstClick = onClick;
}
public interface onFirstClick {
void onFirstClick(String itemName, String itemCode);
}
}
二级列表适配器
public class SecondListAdapter extends BaseAdapter {
private LayoutInflater mInflater;
private Context mContext;
List<SecondDataBeen> secondDataBeens;
public SecondListAdapter(List<SecondDataBeen> list, Context context) {
this.secondDataBeens = list;
this.mContext = context;
mInflater = LayoutInflater.from(mContext);
}
@Override
public int getCount() {
return secondDataBeens.size();
}
@Override
public Object getItem(int position) {
return secondDataBeens.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.list_item_second, null);
holder = new ViewHolder();
holder.serviceItemRel = (LinearLayout) convertView.findViewById(R.id.service_item_rel);
holder.serviceImg = (ImageView) convertView.findViewById(R.id.service_img);
holder.serviceName = (TextView) convertView.findViewById(R.id.service_name);
holder.serviceReMake = (TextView) convertView.findViewById(R.id.service_remake);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
final SecondDataBeen secondDataBeen = secondDataBeens.get(position);
// holder.serviceImg.setBackgroundResource(R.drawable.icon_second_left);
//需要引用毕加索jar包,项目中带有,可以直接使用
Picasso.with(mContext).load(secondDataBeen.getAppPic().toString().trim()).placeholder(R.drawable.icon_second_left).error(R.drawable.icon_second_left).into(holder.serviceImg);
holder.serviceName.setText(secondDataBeen.getItemName());
holder.serviceReMake.setText(secondDataBeen.getReMark());
holder.serviceItemRel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (onClick != null) {
onClick.onClick(secondDataBeen.getItemName(), secondDataBeen.getItemCode());
}
}
});
return convertView;
}
public class ViewHolder {
LinearLayout serviceItemRel;
ImageView serviceImg;
TextView serviceName;
TextView serviceReMake;
}
private SecondListAdapter.onClick onClick;
public void setOnClick(SecondListAdapter.onClick onClick) {
this.onClick = onClick;
}
public interface onClick {
void onClick(String itemName, String itemCode);
}
}
适配其中自定义了点击接口,根据实际情况可以选择是否使用。