继上一篇ListView显示柱状图,并解决滚动时内容重复的问题之后,针对于有分组的数据,应该如何处理呢?数据结构在第一篇文章中请查看NameValue类中的getNameValues()方法,里面放有name,value,filter。使用filter字段对数据结构进行分组
思路:
1. 拿到这样的一个数据结构,想到的第一件事,就是将数据进行重组,然后在使用Adapter绑定到ListView中。
2. 获取的数据不固定,那么在重组数据时需要有大量消耗时间问题,此时线程应该出现了。
那么好,接下来就按照以上思路走吧,等碰到问题在分析,一下代码是在前篇博客基础上做的修改,有不太明白的朋友可以先看上一篇博文ListView显示柱状图,并解决滚动时内容重复的问题
1. 创建Layout文件,这是启动页start_layout_activity.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ScrollView android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/sv">
<LinearLayout android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:id="@+id/outerLinear"></LinearLayout>
</ScrollView>
</LinearLayout>
2. 修改activity_main.xml文件[注:这是上面博文的启动页,稍作修改]
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" >
<TextView android:layout_width="match_parent"
android:layout_height="25dip"
android:text="123"
android:background="@color/chart_bg"
android:id="@+id/tvTitle"
android:gravity="center_vertical"/>
<ListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</ListView>
</LinearLayout>
此时注意这个文件中的ListView,具体问题稍作解释
3. 将数据分组
/**
* 获取集合中的所有分组数据
* @param options 原始的数据集合
* @return 具体的分组数据
*/
private ArrayList<String> getTypes(ArrayList<NameValue> options){
ArrayList<String> type = new ArrayList<String>();
for (int i = 0; i < options.size(); i++) {
if(!type.contains(options.get(i).filter)){
type.add(options.get(i).filter);
}
}
return type;
}
/**
* 组装数据结构
* @param options
* @return
*/
private HashMap<String,ArrayList<NameValue>> getValues(ArrayList<NameValue> options){
ArrayList<String> typeList = getTypes(options);
HashMap<String,ArrayList<NameValue>> vd = new HashMap<String, ArrayList<NameValue>>();
for (int i = 0; i < typeList.size(); i++) {
ArrayList<NameValue> nameValues = new ArrayList<NameValue>();
for (int j = 0; j < options.size(); j++) {
if(typeList.get(i) == options.get(j).filter){
nameValues.add(options.get(j));
}
vd.put(typeList.get(i), nameValues);
}
}
return vd;
}
4. 添加Thread和Handler
Handler handle = new Handler()
{
public void handleMessage(Message msg) {
if(msg != null)
{
HashMap<String,Object> vd =(HashMap<String,Object>)msg.obj;
Log.i("个数", String.valueOf(vd.size()));
// ScrollView view = (ScrollView)findViewById(R.id.sv);
LinearLayout view = (LinearLayout)findViewById(R.id.outerLinear);
ArrayList<String> strType = (ArrayList<String>)vd.get("types");
HashMap<String,ArrayList<NameValue>> values =(HashMap<String,ArrayList<NameValue>>)vd.get("mList");
for (String str : strType) {
View v = LayoutInflater.from(MainActivity.this).inflate(R.layout.activity_main,null,false);
ListView listView =(ListView)v.findViewById(R.id.listView);
TextView title = (TextView)v.findViewById(R.id.tvTitle);
ArrayList<NameValue> valuesList = values.get(str);
MyAdapter sim = new MyAdapter(MainActivity.this, valuesList,width);
listView.setAdapter(sim);
title.setText(str);
view.addView(v);
}
}
};
};
class myThread extends Thread{
@Override
public void run() {
HashMap<String,Object> vd = new HashMap<String, Object>();
vd.put("types", getTypes(values));
vd.put("mList", getValues(values));
System.out.print(vd.size());
Message msg = new Message();
msg.obj = vd;
handle.sendMessage(msg);
}
}
5. 修改MainActivity中的onCreate()方法
ArrayList<NameValue> values;
int width;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.start_layout_activity);
// ListView listView = (ListView)findViewById(R.id.listView);
values = NameValue.getNameValues();
// //width:当前设备的宽度
width = this.getWindowManager().getDefaultDisplay().getWidth();
// MyAdapter mydapter = new MyAdapter(MainActivity.this, values, width);
// listView.setAdapter(mydapter);
new myThread().start();
}
此时,运行下看下结果
不知此时有没有注意到什么,里面listView的高度不正确,原因是在ListView外层套了ScrollView,两个都带滚动条,然后listView中的高度android:layout_height=”match_parent”根本没发挥作用,那此时需要设置ListView的实际高度来确定,所以需要onMeasure方法。
什么时候调用onMeasure方法
当控件的父元素正要放置该控件时调用.父元素会问子控件一个问题,“你想要用多大地方啊?”,然后传入两个参数——widthMeasureSpec和heightMeasureSpec.
这两个参数指明控件可获得的空间以及关于这个空间描述的元数据.
更好的方法是你传递View的高度和宽度到setMeasuredDimension方法里,这样可以直接告诉父控件,需要多大地方放置子控件.
此时我们需要去掉ListView的滚动条
6. 重写ListView,我们创建类UnscrollableListView
public class UnscrollableListView extends ListView {
public UnscrollableListView(Context context) {
super(context);
}
public UnscrollableListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public UnscrollableListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
heightMeasureSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
7. 修改activity_main.xml文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" >
<TextView android:layout_width="match_parent"
android:layout_height="25dip"
android:text="123"
android:background="@color/chart_bg"
android:id="@+id/tvTitle"
android:gravity="center_vertical"/>
<com.example.listviewdemo.view.UnscrollableListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</com.example.listviewdemo.view.UnscrollableListView>
</LinearLayout>
完成后截图