Android ExpandableListView 中完美嵌套 GridView

转载请注明出处: http://blog.csdn.net/like_program/article/details/52549435

在做项目的时候,想在 ExpandableListView 中嵌套一个 GridView,在实现的过程中,遇到了不少坑,所以写篇博客记录一下,也顺便帮助下和我一样的新手。

我一直觉得,再多的文字,再多的代码片段,都不如写个小 Demo 更直观,所以在以后的博客中,我都尽量用小 Demo 来讲解,也给出源码。

先上一张最终效果图:

完美嵌套

打开 Android Studio,我们新建一个 ExpandableListViewTest 项目,在项目中新建两个包(package), 分别命名为 activity 和 adapter,然后将 Android Studio 默认创建的 MainActivity 拖入 activity 包中。

为了让项目运行起来看上去更美观,我们用 Theme 主题,修改 AndroidManifest.xml 中的 application 下的 android:theme 属性,修改为@android:style/Theme, 
修改后的 AndroidManifest.xml 代码如下所示:

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:theme="@android:style/Theme" >
    <activity android:name=".activity.MainActivity" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

修改了主题后,我们再修改下 MainActivity.Java 文件,MainActivity 默认继承自 AppCompatActivity ,我们把 AppCompatActivity 修改为 Activity,让 MainActivity 继承 Activity,这样等会项目才能正常运行。

我们先来写一下布局文件,既然我们想在 ExpandableListView 中嵌套一个 GridView,那么首先我们应该写一个 ExpandableListView

activity_main.xml 代码如下所示:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    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"
    tools:context=".activity.MainActivity">

    <ExpandableListView
        android:id="@+id/expandableList"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:childDivider="@drawable/separator"
        android:divider="@drawable/separator"/>
</RelativeLayout>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

布局文件非常简单,在布局中只放置了一个 ExpandableListView,并设置了各组之间的分割线和各组子项之间的分割线,分割线是一张图片。接下来我们就要在 MainActivity 中实例化 ExpandableListView 的布局,并准备好 ExpandableListView 要显示的数据,然后把数据传入 ExpandableListView 的适配器,这样才能把 ExpandableListView 显示出来。

MainActivity.java 代码如下所示:

package com.example.expandablelistviewtest.activity;

import android.app.Activity;
import android.os.Bundle;
import android.widget.ExpandableListView;

import com.example.expandablelistviewtest.R;
import com.example.expandablelistviewtest.adapter.MyExpandableListViewAdapter;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends Activity {

    private ExpandableListView expandableListView;

    /**
     * 每个分组的名字的集合
     */
    private List<String> groupList;

    /**
     * 每个分组下的每个子项的 GridView 数据集合
     */
    private List<String> itemGridList;

    /**
     * 所有分组的所有子项的 GridView 数据集合
     */
    private List<List<String>> itemList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        expandableListView = (ExpandableListView) findViewById(R.id.expandableList);

        // 分组
        groupList = new ArrayList<>();
        groupList.add("分组1");
        groupList.add("分组2");

        // 每个分组下的每个子项的 GridView 数据集合
        itemGridList = new ArrayList<>();
        for (int i = 0; i < 4; i++) {
            itemGridList.add("电脑" + (i + 1));
        }

        // 所有分组的所有子项的 GridView 数据集合
        itemList = new ArrayList<>();
        itemList.add(itemGridList);
        itemList.add(itemGridList);
        // 创建适配器
        MyExpandableListViewAdapter adapter = new MyExpandableListViewAdapter(MainActivity.this,
                groupList, itemList);
        expandableListView.setAdapter(adapter);
        // 隐藏分组指示器
        expandableListView.setGroupIndicator(null);
        // 默认展开第一组
        expandableListView.expandGroup(0);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63

既然我们要设置 ExpandableListView 适配器,那首先我们要定义一个 ExpandableListView 适配器,在 adapter 包下新建一个 MyExpandableListViewAdapter.java 类,在 ExpandableListView 适配器中,我们将把在 MainActivity 中准备好的数据传入这个适配器,并定义这些数据该怎么显示,因此我们还要创建一个 ExpandableListView 的分组布局文件 和 子项布局文件。不过不要着急,我们先定义好适配器。

MyExpandableListViewAdapter.java 代码如下所示:

package com.example.expandablelistviewtest.adapter;

import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseExpandableListAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.example.expandablelistviewtest.R;

import java.util.List;

/**
 * ExpandableListView 适配器
 */
public class MyExpandableListViewAdapter extends BaseExpandableListAdapter {

    private Context mContext;

    /**
     * 每个分组的名字的集合
     */
    private List<String> groupList;

    /**
     * 所有分组的所有子项的 GridView 数据集合
     */
    private List<List<String>> itemList;

    private GridView gridView;

    public MyExpandableListViewAdapter(Context context, List<String> groupList,
                                       List<List<String>> itemList) {
        mContext = context;
        this.groupList = groupList;
        this.itemList = itemList;
    }

    @Override
    public int getGroupCount() {
        return groupList.size();
    }

    @Override
    public int getChildrenCount(int groupPosition) {
        return itemList.get(groupPosition).size();
    }

    @Override
    public Object getGroup(int groupPosition) {
        return groupList.get(groupPosition);
    }

    @Override
    public Object getChild(int groupPosition, int childPosition) {
        return itemList.get(groupPosition).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 false;
    }

    @Override
    public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup
            parent) {
        if (null == convertView) {
            convertView = View.inflate(mContext, R.layout.expandablelist_group, null);
        }
        ImageView ivGroup = (ImageView) convertView.findViewById(R.id.iv_group);
        TextView tvGroup = (TextView) convertView.findViewById(R.id.tv_group);
        // 如果是展开状态,就显示展开的箭头,否则,显示折叠的箭头
        if (isExpanded) {
            ivGroup.setImageResource(R.drawable.ic_open);
        } else {
            ivGroup.setImageResource(R.drawable.ic_close);
        }
        // 设置分组组名
        tvGroup.setText(groupList.get(groupPosition));
        return convertView;
    }

    @Override
    public View getChildView(final int groupPosition, final int childPosition, boolean isLastChild, View
            convertView, ViewGroup parent) {
        if (null == convertView) {
            convertView = View.inflate(mContext, R.layout.expandablelist_item, null);
        }
        // 因为 convertView 的布局就是一个 GridView,
        // 所以可以向下转型为 GridView
        gridView = (GridView) convertView;
        // 创建 GridView 适配器
        MyGridViewAdapter gridViewAdapter = new MyGridViewAdapter(mContext, itemList.get
                (groupPosition));
        gridView.setAdapter(gridViewAdapter);
        gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Toast.makeText(mContext, "点击了第" + (groupPosition + 1) + "组,第" +
                        (position + 1) + "项", Toast.LENGTH_SHORT).show();
            }
        });
        return convertView;
    }

    @Override
    public boolean isChildSelectable(int groupPosition, int childPosition) {
        return false;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125

我们可以看到,ExpandableListView 的适配器代码看上去很多,但实际上并不复杂,因为大部分代码都是重写父类的方法,这里对 getChildView 的某些代码解释一下:convertView 的布局就是一个 GridView,但是实例化布局后,convertView 是 View 类型,所以 convertView 没有 setAdapter() 方法,需要向下转型为 GridView ,才能调用 setAdapter() 方法,设置适配器。

定义好了 ExpandableListView 的适配器,我们来写一下 ExpandableListView 的分组布局文件 和 子项布局文件。我们先写 ExpandableListView 的分组布局文件,在 layout 文件夹下,新建 expandablelist_group.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="wrap_content"
              android:gravity="center_vertical"
              android:orientation="horizontal">

    <ImageView
        android:id="@+id/iv_group"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:src="@drawable/ic_open"/>

    <TextView
        android:id="@+id/tv_group"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:gravity="center"
        android:text="分组"
        android:textSize="18sp"/>

</LinearLayout>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

我们可以看到,分组布局非常简单,就是一个横向的线性布局,然后依次排列了一个 指示箭头 图片 和一个 分组 名字,我们继续写 ExpandableListView 的子项布局文件,在 layout 文件夹下,新建 expandablelist_item.xml ,代码如下所示:

<?xml version="1.0" encoding="utf-8"?>
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:numColumns="3">

</GridView>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

我们可以看到,子项布局更简单,就是一个有 3 列数据的 GridView。

对了,刚才我们在 ExpandableListView 的适配器中创建了 GridView 的适配器,那我们赶紧去定义一下 GridView 的适配器吧。

在 adapter 包下,新建 MyGridViewAdapter.java ,代码如下所示:

package com.example.expandablelistviewtest.adapter;

import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

import com.example.expandablelistviewtest.R;

import java.util.List;

/**
 * GridView 适配器
 */
public class MyGridViewAdapter extends BaseAdapter {

    private Context mContext;

    /**
     * 每个分组下的每个子项的 GridView 数据集合
     */
    private List<String> itemGridList;

    public MyGridViewAdapter(Context mContext, List<String> itemGridList) {
        this.mContext = mContext;
        this.itemGridList = itemGridList;
    }

    @Override
    public int getCount() {
        return itemGridList.size();
    }

    @Override
    public Object getItem(int position) {
        return itemGridList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (null == convertView) {
            convertView = View.inflate(mContext, R.layout.gridview_item, null);
        }
        TextView tvGridView = (TextView) convertView.findViewById(R.id.tv_gridview);
        tvGridView.setText(itemGridList.get(position));
        return convertView;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54

GridView 的适配器和 ExpandableListView 的适配器一样,逻辑并不复杂,主要就是重写父类的方法,在 getView() 方法中,我们实例化了 GridView 的子项布局,所以,我们也要写一下 GridView 的子项布局文件,在 layout 文件夹中,新建 gridview_item.xml ,代码如下所示:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:orientation="vertical">

    <TextView
        android:id="@+id/tv_gridview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:drawableTop="@drawable/icon_computer"
        android:gravity="center"
        android:text="电脑"/>

</LinearLayout>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

GridView 子项布局只定义了一个带有图片的 TextView。

好了,我们来运行一下,看看效果。

初步运行效果

好像已经成功了,不过貌似有些问题:

  1. 它的每个分组的每个子项里都有一个 GridView,但我们只想在每个分组里只显示一个 GridView 。
  2. 在点击 GridView 中的子项时,我们发现,在同一个分组里,点击不同子项里 GridView 的第一个子项时,都显示的第 N 组第 1 项。
  3. 我们定义的 GridView 有 4 个数据,分别是 电脑 1 ,电脑 2 ,电脑 3 ,电脑 4 。但是它只显示了 3 个。

我们逐一解决这些问题。

首先,我们可以发现,每组都有 4 行数据,也就是说,每组都有 4 个子项,那么如果我们想要在每个分组里只显示一个 GridView ,也就是一个子项,那么我们要先找到我们之前定义过的和 4 相关的数据,经过查找,我们发现,和 4 相关的数据只有一个,就是 itemGridList ,它里面有 4 个数据,找到了它之后,我们再找一下它在哪里被调用了,经过查找,我们发现,在 ExpandableListView 适配器中的 getChildrenCount() 方法中调用了它,有些同学了可能会疑惑,这里调用的是 itemList.get(groupPosition).size(),关 itemGridList 什么事,其实我们之前在 MainActivity 中是这样创建 itemList 的:itemList.add(itemGridList),在这行代码中,itemGridList 被添加到了 itemList 中,那么在 getChildrenCount() 方法中,调用itemList.get(groupPosition) ,得到的就是 itemGridList ,再调用它的 size() 方法,得到的就是 itemGridList 的大小了,也就是 4,知道了这个,我们想在每个分组里只显示一个 GridView,也就好办了,在 getChildrenCount() 方法中,我们直接返回 1,即

@Override
public int getChildrenCount(int groupPosition) {
    return 1;
}
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

再运行一下程序,我们发现,果然每个分组里只显示了一个 GridView 。

每个分组只显示一个 GridView

我们再来看第二个问题,在同一个分组里,点击不同子项里 GridView 的第一个子项时,都显示的第 N 组第 1 项。

我们查看下 ExpandableListView 适配器代码中的 getChildView() 代码中的设置子项监听器代码:

Toast.makeText(mContext, "点击了第" + (groupPosition + 1) + "组,第" +
                        (position + 1) + "项", Toast.LENGTH_SHORT).show();
  • 1
  • 2
  • 1
  • 2

这里使用了两个变量, groupPosition 很容易理解,就是 分组的 id ,position 可能有些同学会迷惑,position 并不是分组的子项 id ,而是 GridView 的子项 id ,弄清了这个,第二个问题也就不难懂了,我们不管点击的是分组下的哪一个子项中的 GridView 的第一项,都显示是 第一项,是因为 position 表示的 GridView 的子项 id ,和 分组下的子项 id 并没有关系。

我们再来看第三个问题,我们定义的 GridView 有 4 个数据,但是它只显示了 3 个。

首先,它只显示 3 个的部分原因是因为我们定义的 GridView 一行只能显示 3 个数据,我们可以查看 expandablelist_item.xml 的代码:android:numColumns="3"

更重要的原因是因为 GridView 的父容器测量模式为 UNSPECIFIED 的时候,GridView 的高度默认为一个 item 的高度,GridView 中源码如下:

if (heightMode == MeasureSpec.UNSPECIFIED) {
    heightSize = mListPadding.top + mListPadding.bottom + childHeight +
            getVerticalFadingEdgeLength() * 2;
}
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

既然是这样的话,我们就重写 GridView 的 onMeasure 方法,自定义高度,在 activity 包中,新建 MyGridView.java ,代码如下:

package com.example.expandablelistviewtest.activity;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.GridView;

/**
 * 自定义 GridView
 */
public class MyGridView extends GridView {

    public MyGridView(Context context) {
        super(context);
    }

    public MyGridView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MyGridView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    /**
     * 重写该方法,达到使 GridView 适应 ExpandableListView 的效果
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasureSpec, expandSpec);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

关于重写 GridView 的 onMeasure 方法的原理分析,可以查看这两篇文章。

android开发游记:ScrollView嵌套ListView,ListView完全展开及makeMeasureSpec测量机制原理分析

详解嵌套ListView、ScrollView布局显示不全的问题

写好了 MyGridView 后,在 MyGridView 上点击右键,选择 Copy Reference,复制 MyGridView 的全路径名,替换 expandablelist_item.xml 中的 GridView 标签。

复制 GridView 全路径名

替换后的 expandablelist_item.xml 代码如下:

<?xml version="1.0" encoding="utf-8"?>
<com.example.expandablelistviewtest.activity.MyGridView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:numColumns="3">

</com.example.expandablelistviewtest.activity.MyGridView>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

重新运行程序,我们发现,GridView 已经完美嵌套在 ExpandableListView 中了。

完美嵌套

源码下载

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页