`

expand

 
阅读更多

[Android]界面的布局-ExpandableListView


http://ysl-paradise.blogspot.com/2011/05/listview-ii.html


1.可展开的ListView

在這一篇中,我們來看看如何自定义一个两层结构的ListView。如下图所示:

[Android]界面的布局-ExpandableListView
当点击People Names,就显示对应的子列表,如下图:

[Android]界面的布局-ExpandableListView
如何可以做到上面的效果呢?首先我们自定义一个MyExpandableListAdapter.它继承自BaseExpandableListAdpter.

    public class MyExpandableListAdapter extends BaseExpandableListAdapter {
        // Sample data set.  children[i] contains the children (String[]) for groups[i].
        private String[] groups = { "People Names", "Dog Names", "Cat Names", "Fish Names" };
        private String[][] children = {
                { "Arnold", "Barry", "Chuck", "David" },
                { "Ace", "Bandit", "Cha-Cha", "Deuce" },
                { "Fluffy", "Snuggles" },
                { "Goldy", "Bubbles" }
        };
      
        public Object getChild(int groupPosition, int childPosition) {
            return children[groupPosition][childPosition];
        }
      
        public long getChildId(int groupPosition, int childPosition) {
            return childPosition;
        }
      
        public int getChildrenCount(int groupPosition) {
            return children[groupPosition].length;
        }

        public TextView getGenericView() {
            // Layout parameters for the ExpandableListView
            AbsListView.LayoutParams lp = new AbsListView.LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT, 64);

            TextView textView = new TextView(TestExpandableListActivity.this);
            textView.setLayoutParams(lp);
            // Center the text vertically
            textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
            // Set the text starting position
            textView.setPadding(60, 0, 0, 0); //第一层的textview,距离上下左右边界的距离。
            return textView;
        }
      
        public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
                View convertView, ViewGroup parent) {
            TextView textView = getGenericView();
            textView.setText(getChild(groupPosition, childPosition).toString());
            return textView;
        }
      
        public Object getGroup(int groupPosition) {
            return groups[groupPosition];
        }
      
        public int getGroupCount() {
            return groups.length;
        }
      
        public long getGroupId(int groupPosition) {
            return groupPosition;
        }

      
        public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
                ViewGroup parent) {
            TextView textView = getGenericView();
            textView.setText(getGroup(groupPosition).toString());
            return textView;
        }
      
        public boolean isChildSelectable(int groupPosition, int childPosition) {
            Toast.makeText(TestExpandableListActivity.this, getChild(groupPosition, childPosition).toString(), Toast.LENGTH_LONG).show();
            return true;
        }

        public boolean hasStableIds() {
            return true;
        }

    }

接着,新建一个工程,在主Activity里加入下面代码:
public class TestExpandableListActivity extends ExpandableListActivity  {
    ExpandableListAdapter mAdapter;
  
  
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //setContentView(R.layout.main);
        //set up our adapter
        mAdapter = new MyExpandableListAdapter();
        setListAdapter(mAdapter);
        registerForContextMenu(getExpandableListView());       
    }
}

上面的源代码在你本机c:\Program Files\Android\android-sdk\samples\android-10_1\ApiDemos\src\com\example\android\apis\view\ExpandableList1.java

里可以找到。

2. 自定义ExpandableListView的显示

上面的可展开的ListView黑乎乎的,且间隔很大。如何修改它的Layout呢?

2.1 修改父界面。效果如下图:

[Android]界面的布局-ExpandableListView

新建一个xml文件,用来显示父界面。xml内容如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent" android:orientation="horizontal"
    android:layout_height="wrap_content" android:background="#ccc"
    android:gravity="left|center_vertical" android:minHeight="40dip"
    android:paddingRight="20dip" android:paddingLeft="10dip">  
  
    <TextView android:id="@+id/txtGroupName"
            android:layout_height="wrap_content"
            android:layout_width="0dip"
            android:layout_weight="1"
            android:textSize="20dip"
            android:textColor="#000"  
            android:paddingLeft="3dip"      
            android:singleLine="true" />
  
</LinearLayout>

其实只有一个textview控件,用来显示A,B,C,D。。。左边的展开折叠按钮时系统提供的。现在就先不修改它了。

用这个xml文件,主要是想设置奇偶行的颜色,这样使用起来比较清楚。不然背景是黑乎乎一片,使用起来不是那么舒服。

源代码里只需要修改一个函数。如下:
public View getGroupView(int groupPosition, boolean isExpanded,
                View convertView, ViewGroup parent) {
            String strGroup = mCategoryList.get(groupPosition);  //自己取得要显示内容。mCategoryList其实就是一个List<String>里面存放了26个字母而已。
            //设置Layout
            LayoutInflater inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            LinearLayout ll = (LinearLayout)inflater.inflate(R.layout.artistlist_group, null);
            TextView tv = (TextView)ll.findViewById(R.id.txtGroupName);
            tv.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
            // 设置字符开始的位置,如果不够大的话,字符就和左边的展开/折叠图标重叠了。自己可以改改数字,看看效果就明白了。
            tv.setPadding(60, 0, 0, 0);
            // 设置显示的内容
            tv.setText(strGroup);
            // 设置奇偶行的背景交错
            ll.setBackgroundColor(groupPosition % 2 == 0 ? Color.argb(250, 255, 255, 255) : Color.argb(250, 229, 229, 229));
            return ll;
        }

2.2 修改展开后的子界面。效果如下图:

[Android]界面的布局-ExpandableListView

其实和上面未展开前的父界面差不多,是不是?

新建一个xml文件,用来显示子界面。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent" android:orientation="horizontal"
    android:layout_height="wrap_content" android:background="#fff"
    android:gravity="left|center_vertical" android:minHeight="40dip"
    android:paddingRight="20dip" android:paddingLeft="10dip">
  
  
    <TextView android:id="@+id/txtArtistName"
            android:layout_height="wrap_content"
            android:layout_width="0dip"
            android:layout_weight="1"
            android:textSize="16dip"
            android:textColor="#000"  
            android:paddingLeft="3dip"      
            android:singleLine="true" />  
          
    <ImageView android:id="@+id/imgArtist"
        android:src="@drawable/arrow_right_rest"
        android:paddingRight="5dip"
        android:layout_width="24dip"
        android:layout_height="24dip"      
        android:contentDescription="@string/artist" />
</LinearLayout>

从上面可以看出,textview用来显示文字,图片就是右边的那个箭头符号。

源代码如下:
public View getChildView(int groupPosition, int childPosition,
               boolean isLastChild, View convertView, ViewGroup parent) {
           //取得要展开的子条目的内容
           String strArtistName = mArtistList.get(groupPosition).get(childPosition); //mArtistList其实就是一个List<List<String>>
           //设置界面
           LayoutInflater inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
           LinearLayout ll = (LinearLayout)inflater.inflate(R.layout.artistlist_row, null);
           TextView tv = (TextView)ll.findViewById(R.id.txtArtistName);
           //设置内容
           tv.setText((childPosition + 1) + "." + strArtistName);
           //设置奇偶行。因为父界面也是奇偶行分割的,为了和父条目的颜色呼应,所以这里要判断一下父条目的颜色。
           //即父条目为灰色,那么第一个子条目应该是白色。如果两个都是灰色,就连成一片了。
           if(groupPosition % 2 == 0)
               ll.setBackgroundColor(childPosition % 2 == 0 ? Color.argb(250, 229, 229, 229) : Color.argb(250, 255, 255, 255));
           else
               ll.setBackgroundColor(childPosition % 2 == 0 ? Color.argb(250, 255, 255, 255) : Color.argb(250, 229, 229, 229));
           return ll;
       }

这样就完成了自定义展开前和展开后的效果了。

3. 点击某个父条目时,如何收起其他已经展开的条目?

当我们点击某个父条目时,如果这个条目本身是没有展开的,我们需要做两个动作:

1.折叠其他已经展开的条目(为什么?实际应用中需要。不需要的话可以忽略此步)

2. 展开这个条目

然而在实现过程中,总是出现异常。

03-15 17:18:13.090: ERROR/AndroidRuntime(16202): FATAL EXCEPTION: main

03-15 17:18:13.090: ERROR/AndroidRuntime(16202): java.lang.IndexOutOfBoundsException: Invalid index 1, size is 0

真是头晕啊。不知道哪里越界了呢?怎么会size为0呢?跟了好久都不知道为何。看了这篇博文,http://qtcstation.com/2011/03/working-with-the-expandablelistview-part-1/

终于明白了。我也是将折叠其他条目写在onGroupClicl里了.改写在onGroupExpand就没事了。唉唉。
private ExpandableListView.OnGroupExpandListener mGroupExpandListener = new ExpandableListView.OnGroupExpandListener() {
     
       public void onGroupExpand(int groupPosition) {
           int len = mAdapter.getGroupCount();
           for(int i=0; i<len; i++)
               if(i != groupPosition)
                   mExpandListView.collapseGroup(i);          
       }
   };
 
   private ExpandableListView.OnGroupClickListener mGroupClickListener = new ExpandableListView.OnGroupClickListener() {
     
       public boolean onGroupClick(ExpandableListView parent, View v,
               int groupPosition, long id) {
           //collapseAllExpanded();            就是在这里折叠条目出错了。千万不能写在这里。写到onGroupExpand里。
           startSearch(groupPosition); //自己写的动态从网上搜索要显示的子条目。改成自己的函数即可。
           return false;
       }
   };

4. 旋转时如何让展开的条目保持展开状态并显示它的子条目?

当我们由横屏转竖屏,或竖屏转横屏时,App会有个重新初始化的过程。这时候不做任何处理的话,展开的条目就会丢失它的子条目。这样的显示效果显然是不友好的。旋转后如何保持刚才的内容呢?

下面这篇文章非常有用。

http://stackoverflow.com/questions/4184556/save-and-restore-expanded-collapsed-state-of-an-expandablelistactivity

我们需要用一个数组来记住已经展开的group的id。在onSaveInstanceState函数中记住展开的id。在onRestoreInstanceState函数中恢复这些id,将它们展开。

还要在onStart中检查是否有展开的id,如果有的话,展开这些id。

在onStop中记得储存这些展开的id。
private long[] mExpandedIds; //save expanded group id

@Override
protected void onStart() {
    super.onStart();
    if(this.mExpandedIds != null)
        restoreExpandedState(mExpandedIds);
}
  
@Override
protected void onStop() {
    super.onStop();
    mExpandedIds = getExpandedIds();
}  

@Override
protected void onSaveInstanceState(Bundle outState)
{
    super.onSaveInstanceState(outState);
    this.mExpandedIds = getExpandedIds();
    outState.putLongArray("ExpandedIds", this.mExpandedIds);
}

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState)
{
    super.onRestoreInstanceState(savedInstanceState);
    long[] expandedIds = savedInstanceState.getLongArray("ExpandedIds");
    if(expandedIds != null)
        restoreExpandedState(expandedIds);
}
//取得所有展开的group的id
private long[] getExpandedIds() {
    if(mAdapter != null)
    {
        int length = mAdapter.getGroupCount();
        ArrayList<Long> expandedIds = new ArrayList<Long>();
        for(int i=0; i<length; i++)
        {
            //判断这个group是否展开。如果展开,就记下来
            if(mExpandListView.isGroupExpanded(i))
            {
                expandedIds.add(mAdapter.getGroupId(i));
            }
        }
        return toLongArray(expandedIds);
    }
    else
        return null;
}
//恢复到展开状态
private void restoreExpandedState(long[] expandedIds)
{
    this.mExpandedIds = expandedIds;
    if(mExpandedIds != null)
    {  
        if(mAdapter != null)
        {
            for(int i=0; i<mAdapter.getGroupCount(); i++)
            {
                long id=mAdapter.getGroupId(i);                  
                if(inArray(expandedIds, id))
                {
                    startSearch((int)id); //自己写的动态寻找对应的子条目的函数。改成自己的函数即可。
                    //如果这个group已经是展开的,那么折叠它,再展开。否则显示的子条目内容在旋转前后不一样。
                    if(!mExpandListView.expandGroup((int)id))
                    {  
                        mExpandListView.collapseGroup((int)id);
                        mExpandListView.expandGroup((int)id);
                    }
                }
            }
        }
    }
}

private static boolean inArray(long[] array, long element) {
    for (long l : array) {
        if (l == element) {
            return true;
        }
    }
    return false;
}

private static long[] toLongArray(List<Long> list)  {
    long[] ret = new long[list.size()];
    int i = 0;
    for (Long e : list)
        ret[i++] = e.longValue();
    return ret;
}




分享到:
评论

相关推荐

    expand 系统自带解压工具

    标题中的“expand”是Windows操作系统中内置的一个命令行工具,用于展开或解压缩文件。这个工具在系统维护、软件安装和修复过程中非常有用,尤其是在没有图形界面解压工具的情况下。让我们深入了解一下`expand`命令...

    前端开源库-markdown-it-expand-tabs

    Markdown-it-Expand-Tabs是一个专为Markdown解析器Markdown-it设计的插件,其主要功能是处理代码块(code blocks)中的前导制表符。在Markdown格式中,代码块通常通过将文本缩进四个空格或者一个制表符来表示。然而...

    DS918+_6.2.3-25426_UEFI_GPT_EXPAND.zip

    标题“DS918+_6.2.3-25426_UEFI_GPT_EXPAND.zip”指的是群晖(Synology)DS918+型号网络附加存储(NAS)设备的一个系统固件更新包。这个更新版本为6.2.3,编号25426,表明这是该设备在某个时间点的软件升级,旨在...

    JQuery Expand扩展条Demo

    **jQuery Expand扩展条Demo详解** 在网页开发中,我们经常需要处理内容的展开与收起,以优化用户体验,节省页面空间。这就是`JQuery Expand`扩展条的作用所在。`JQuery Expand`是一种基于jQuery库的插件,它允许...

    鼠标悬浮 浮动放大 expand 效果

    【标题】:“鼠标悬浮浮動放大expand效果” 在网页设计中,鼠标悬浮效果是一种常见的交互设计手法,可以提升用户体验,使用户更容易理解页面元素的功能。"鼠标悬浮浮動放大expand效果"指的是当用户将鼠标光标悬停在...

    IOS应用源码之可伸展折叠的控件Expand .zip

    本文将深入探讨“Expand”这个特定的源码实现,它为iOS开发者提供了一种优雅的方式,来实现自定义控件的展开与折叠效果。 首先,我们要理解“Expand”源码的核心概念——层次视图(Hierarchy View)。这种视图允许...

    前端开源库-css-shorthand-expand

    `css-shorthand-expand`是一个开源库,专注于将这些CSS的简写属性展开为它们的完整形式,从而帮助开发者更好地理解和调试CSS代码。 标题“前端开源库-css-shorthand-expand”指出了这个项目的核心——这是一个面向...

    Android代码-ExpandTable

    在Android开发中,"ExpandTable"是一个常见的需求,特别是在构建类似58同城这样的信息分类列表时,用户可能需要点击一个条目来展开更多的详细信息。这个项目实现了这种点击展开的效果,利用了Android的基础布局组件`...

    Laravel开发-laravel_expand

    在本文中,我们将深入探讨Laravel框架中的错误处理与错误代码管理,这在"laravel_expand"项目中扮演着至关重要的角色。Laravel是PHP世界里一个优雅且强大的Web应用开发框架,它提供了丰富的工具和功能,使得错误处理...

    c语言函数调用关系图自动生成方法之使用egypt和gcc的-fdump-rtl-expand生成Graphviz

    本文将详细介绍如何利用egypt工具和GCC编译器的-fdump-rtl-expand选项生成Graphviz图形,以便直观地展示函数间的调用关系。 首先,让我们了解egypt。埃及(Egypt)是一个开源项目,它提供了一个用于分析和可视化...

    LABVIEW 资源,AES128加密子VI:Expand Key

    LABVIEW 资源,AES128加密子VI:Expand Key

    jquery插件SelectExpand,让select可以自定义输入

    扩展html中的select元素,基于jquery,兼容IE6、chrome,firefox 主要是看着一些select插件不兼容ie6所以自己写了个 开源的,大家可以一起完善下 https://github.com/zhenzhonghouse/SelectExpand

    expand-word.zip_expand Word

    "expand-word.zip_expand Word"这个压缩包文件,显然为我们提供了一个用Java实现文字扩展效果的实例。这样的功能在图形用户界面(GUI)应用、游戏开发或者文本处理软件中十分常见,比如在动画效果、动态展示文字等...

    expand.exe

    expand.exe 找到的一个方便大家下载 希望能帮到大家的忙

    expand.png

    expand.pngexpand.pngexpand.pngexpand.pngexpand.pngexpand.png1

    expand命令分析[整理].pdf

    expand 命令分析 expand 命令是 ANSYS 软件中的一种命令,用于对有限元分析模型进行拓展生成更大的显示图表。该命令可以根据实际模型拓展生成更大的模型,以满足不同的分析需求。 expand 命令的基本语法为:`/...

    pyr_reduce pyr_expand

    在图像处理领域,`pyr_reduce` 和 `pyr_expand` 是两个非常重要的函数,它们主要用于构建和解构多分辨率金字塔。多分辨率金字塔是图像处理中的一个基础概念,广泛应用于图像分析、图像缩放、图像编码和图像融合等多...

    anti_expand.rar_同心圆环展开

    而"Expand.ncb"、"Expand.opt"、"Expand.plg"是Visual Studio的相关配置和状态文件,它们帮助开发者跟踪和优化项目。"Debug"文件夹则包含了调试版本的程序,方便开发者找出和修复潜在的错误。 同心圆环展开的反变换...

    C# MVC4 easyui datagrid expand row

    标题“C# MVC4 easyui datagrid expand row”表明我们要讨论的重点是利用EasyUI的数据网格组件实现一个可展开行的功能,这对于展示层次结构数据或需要额外详细信息的表格特别有用。 首先,让我们了解C# MVC4。ASP...

    image_expand.rar_图像扩展_图像扩展MATLAB

    在这个“image_expand.rar”压缩包中,包含了一个名为“image_expand.m”的MATLAB代码文件,专门用于实现图像扩展功能。 MATLAB是一款强大的数学计算软件,尤其在图像处理方面提供了丰富的函数库。在这个特定的案例...

Global site tag (gtag.js) - Google Analytics