Android学习笔记二十七之ExpandableListView可折叠列表和StackView栈视图

Android学习笔记二十七之ExpandableListView可折叠列表和StackView栈视图

ExpandableListView可折叠列表

  这一节我们介绍第三个用适配器的控件,ExpandableListView可折叠列表。这个控件可以实现我们在QQ中非常常见好友分组功能,ExpandableListView是ListView的子类,用法跟ListView差不多,下面我们来学习这个控件的基本使用:

常用属性:

  • android:childDivider:指定各组内子类表项之间的分隔条,图片不会完全显示,分离子列表项的是一条直线
  • android:childIndicator:显示在子列表旁边的Drawable对象,可以是一个图像
  • android:childIndicatorEnd:子列表项指示符的结束约束位置
  • android:childIndicatorLeft:子列表项指示符的左边约束位置
  • android:childIndicatorRight:子列表项指示符的右边约束位置
  • android:childIndicatorStart:子列表项指示符的开始约束位置
  • android:groupIndicator:显示在组列表旁边的Drawable对象,可以是一个图像
  • android:indicatorEnd:组列表项指示器的结束约束位置
  • android:indicatorLeft:组列表项指示器的左边约束位置
  • android:indicatorRight:组列表项指示器的右边约束位置
  • android:indicatorStart:组列表项指示器的开始约束位置

实现ExpandableAdapter的三种方式:

  1. 自定义类继承BaseExpandableListAdpter实现ExpandableAdapter。
  2. 使用SimpleExpandableListAdpater将两个List集合包装成ExpandableAdapter
  3. 使用simpleCursorTreeAdapter将Cursor中的数据包装成SimpleCuroTreeAdapter

在这里,我们使用的是第一种方式,自定义一个类,实现BaseExpandableListAdapter,下面看具体实现:

布局代码:

item_group

<?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_group_name"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginBottom="10dp"
    android:layout_marginLeft="28dp"
    android:layout_marginTop="10dp"
    android:padding="8dp"
    android:text="张三"
    android:textColor="#000000"
    android:textSize="16sp" />

</LinearLayout>

item_child

<?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:gravity="center"
android:orientation="horizontal">

<ImageView
    android:id="@+id/iv_child_icon"
    android:layout_width="40dp"
    android:layout_height="40dp"
    android:layout_marginBottom="8dp"
    android:layout_marginLeft="8dp"
    android:layout_marginTop="8dp"
    android:padding="2dp"
    android:src="@mipmap/ic_launcher" />

<TextView
    android:id="@+id/tv_child_name"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginBottom="8dp"
    android:layout_marginLeft="5dp"
    android:layout_marginTop="8dp"
    android:text="子节点"
    android:textColor="#330000"
    android:textSize="12sp" />

</LinearLayout>

activity_main布局

<?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"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.expandablelistviewdemo.MainActivity">

<ExpandableListView
    android:id="@+id/ex_list"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:childDivider="#E02D2F" />
</RelativeLayout>

自定义适配器代码:

package com.example.expandablelistviewdemo;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.List;

/**
 * Created by Devin on 2016/7/12.
 */
public class CustomAdapter extends BaseExpandableListAdapter {

private List<Group> groupList;
private List<List<Child>> childList;
private Context mContext;

public CustomAdapter(Context mContext, List<Group> groupList, List<List<Child>> childList) {
    this.mContext = mContext;
    this.groupList = groupList;
    this.childList = childList;
}

/**
 * Gets the number of groups.
 *
 * @return
 */
@Override
public int getGroupCount() {
    return groupList.size();
}

/**
 * Gets the number of children in a specified group.
 *
 * @param i
 * @return
 */
@Override
public int getChildrenCount(int i) {
    return childList.get(i).size();
}

/**
 * Gets the data associated with the given group
 *
 * @param i
 * @return
 */
@Override
public Object getGroup(int i) {
    return groupList.get(i);
}

/**
 * Gets the data associated with the given child within the given group.
 *
 * @param i
 * @param i1
 * @return
 */
@Override
public Object getChild(int i, int i1) {
    return childList.get(i).get(i1);
}

/**
 * Gets the ID for the group at the given position.
 *
 * @param i
 * @return
 */
@Override
public long getGroupId(int i) {
    return i;
}

/**
 * Gets the ID for the given child within the given group.
 *
 * @param i
 * @param i1
 * @return
 */
@Override
public long getChildId(int i, int i1) {
    return i1;
}

/**
 * Indicates whether the child and group IDs are stable across changes to the underlying data.
 *
 * @return
 */
@Override
public boolean hasStableIds() {
    return false;
}

/**
 * Gets a View that displays the given group
 *
 * @param i
 * @param b
 * @param view
 * @param viewGroup
 * @return
 */
@Override
public View getGroupView(int i, boolean b, View view, ViewGroup viewGroup) {
    GroupViewHolder groupViewHolder = null;
    if (view == null) {
        view = LayoutInflater.from(mContext).inflate(R.layout.item_group, viewGroup, false);
        groupViewHolder = new GroupViewHolder();
        groupViewHolder.tv_group_name = (TextView) view.findViewById(R.id.tv_group_name);
        view.setTag(groupViewHolder);
    } else {
        groupViewHolder = (GroupViewHolder) view.getTag();
    }
    groupViewHolder.tv_group_name.setText(groupList.get(i).getGroupName());
    return view;
}

/**
 * Gets a View that displays the data for the given child within the given group.
 *
 * @param i
 * @param i1
 * @param b
 * @param view
 * @param viewGroup
 * @return
 */
@Override
public View getChildView(int i, int i1, boolean b, View view, ViewGroup viewGroup) {
    ChildViewHolder childViewHolder = null;
    if (view == null) {
        view = LayoutInflater.from(mContext).inflate(R.layout.item_child, viewGroup, false);
        childViewHolder = new ChildViewHolder();
        childViewHolder.iv_child_icon = (ImageView) view.findViewById(R.id.iv_child_icon);
        childViewHolder.tv_child_name = (TextView) view.findViewById(R.id.tv_child_name);
        view.setTag(childViewHolder);
    } else {
        childViewHolder = (ChildViewHolder) view.getTag();
    }
    childViewHolder.iv_child_icon.setImageResource(R.mipmap.ic_launcher);
    childViewHolder.tv_child_name.setText(childList.get(i).get(i1).getChildName());
    return view;
}

/**
 * 这个方法需要返回true,不然不能实现子节点的点击事件
 * Whether the child at the specified position is selectable.
 *
 * @param i
 * @param i1
 * @return
 */
@Override
public boolean isChildSelectable(int i, int i1) {
    return true;
}

private static class GroupViewHolder {
    TextView tv_group_name;
}

private static class ChildViewHolder {
    ImageView iv_child_icon;
    TextView tv_child_name;
}
}

两个普通javaBean代码:

package com.example.expandablelistviewdemo;

/**
 * Created by Devin on 2016/7/12.
 */
public class Group {
private String groupName;

public Group() {
}

public Group(String groupName) {
    this.groupName = groupName;
}

public String getGroupName() {
    return groupName;
}

public void setGroupName(String groupName) {
    this.groupName = groupName;
}
}
package com.example.expandablelistviewdemo;

/**
 * Created by Devin on 2016/7/12.
 */
public class Child {
private String childName;

public Child() {
}

public Child(String childName) {
    this.childName = childName;
}

public String getChildName() {
    return childName;
}

public void setChildName(String childName) {
    this.childName = childName;
}
}

最后是activity代码:

package com.example.expandablelistviewdemo;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ExpandableListView;
import android.widget.Toast;

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

public class MainActivity extends AppCompatActivity {
private List<Group> groupList;
private List<List<Child>> childList;
private ExpandableListView ex_list;
private CustomAdapter customAdapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    ex_list = (ExpandableListView) findViewById(R.id.ex_list);
    initData();
    customAdapter = new CustomAdapter(this, groupList, childList);
    ex_list.setAdapter(customAdapter);
    //子节点的点击事件
    ex_list.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
        @Override
        public boolean onChildClick(ExpandableListView expandableListView, View view, int i, int i1, long l) {
            Toast.makeText(MainActivity.this, "你点击的是:" + childList.get(i).get(i1).getChildName(), Toast.LENGTH_SHORT).show();
            return true;
        }
    });
}

private void initData() {
    groupList = new ArrayList<>();
    childList = new ArrayList<>();

    groupList.add(new Group("载货汽车"));
    groupList.add(new Group("越野汽车"));
    groupList.add(new Group("自卸汽车"));
    groupList.add(new Group("专用汽车"));
    groupList.add(new Group("客车"));
    groupList.add(new Group("牵引车"));
    groupList.add(new Group("轿车"));
    groupList.add(new Group("半挂车"));

    List<Child> child1 = new ArrayList<>();
    child1.add(new Child("微型货车"));
    child1.add(new Child("轻型货车"));
    child1.add(new Child("中型货车"));
    child1.add(new Child("重型货车"));
    childList.add(child1);

    List<Child> child2 = new ArrayList<>();
    child2.add(new Child("轻型越野车"));
    child2.add(new Child("中型越野车"));
    child2.add(new Child("重型越野车"));
    child2.add(new Child("超重型越野车"));
    childList.add(child2);

    List<Child> child3 = new ArrayList<>();
    child3.add(new Child("轻型自卸车"));
    child3.add(new Child("中型自卸车"));
    child3.add(new Child("重型自卸车"));
    child3.add(new Child("矿用自卸车"));
    childList.add(child3);

    List<Child> child4 = new ArrayList<>();
    child4.add(new Child("箱式汽车"));
    child4.add(new Child("罐式汽车"));
    child4.add(new Child("起重举升车"));
    child4.add(new Child("仓栅式车"));
    child4.add(new Child("特种结构车"));
    child4.add(new Child("专用自卸车"));
    childList.add(child4);

    List<Child> child5 = new ArrayList<>();
    child5.add(new Child("微型客车"));
    child5.add(new Child("轻型客车"));
    child5.add(new Child("中型客车"));
    child5.add(new Child("大型客车"));
    child5.add(new Child("特大型客车"));
    childList.add(child5);

    List<Child> child6 = new ArrayList<>();
    child6.add(new Child("半挂牵引车"));
    child6.add(new Child("全挂牵引车"));
    childList.add(child6);

    List<Child> child7 = new ArrayList<>();
    child7.add(new Child("微型轿车"));
    child7.add(new Child("普通级轿车"));
    child7.add(new Child("中级轿车"));
    child7.add(new Child("中高级轿车"));
    child7.add(new Child("高级轿车"));
    childList.add(child7);

    List<Child> child8 = new ArrayList<>();
    child8.add(new Child("轻型半挂车"));
    child8.add(new Child("中型半挂车"));
    child8.add(new Child("重型半挂车"));
    child8.add(new Child("超重半挂车"));
    childList.add(child8);
}
}

最终实现效果图:

ExpandableListView控件就简单介绍到这里,这里只是基本的实现,有需求的可以扩展。

照例附上国内镜像API

下面我们学习另外一个控件StackView栈视图

StackView栈视图

  stackView是一个将一组View逐个展示给用户的控件,它是一组view的集合,这些view一个压着一个,view之间可以进行随意切换。下面我们通过实例了解StackView的使用方法

布局文件代码:

<?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="horizontal">

<StackView
    android:id="@+id/sk"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:loopViews="true" />

<LinearLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <Button
        android:id="@+id/btn_previous"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="前一张" />

    <Button
        android:id="@+id/btn_next"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="后一张" />

</LinearLayout>

</LinearLayout>

Activity代码:

package com.example.expandablelistviewdemo;

import android.content.Context;
import android.graphics.Color;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.StackView;

/**
 * Created by Devin on 2016/7/12.
 */
public class StackViewActivity extends AppCompatActivity {
private StackView sk;
private Button btn_previous;
private Button btn_next;
private int[] mColors = {Color.BLUE, Color.CYAN, Color.GRAY, Color.GREEN, Color.RED};

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_stackview);
    sk = (StackView) findViewById(R.id.sk);
    btn_next = (Button) findViewById(R.id.btn_next);
    btn_previous = (Button) findViewById(R.id.btn_previous);
    ColorAdapter adapter = new ColorAdapter(getApplicationContext(), mColors);
    sk.setAdapter(adapter);
    btn_previous.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            sk.showPrevious();
        }
    });
    btn_next.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            sk.showNext();
        }
    });
}

/**
 * 自定义适配器
 */
private class ColorAdapter extends BaseAdapter {

    private Context mContext;

    private int[] mColors;

    public ColorAdapter(Context context, int[] colors) {
        mContext = context;
        mColors = colors;
    }

    public int getCount() {
        return mColors == null ? 0 : mColors.length;
    }

    public Object getItem(int position) {
        return mColors == null ? null : mColors[position];
    }

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

    public View getView(int position, View view, ViewGroup parent) {
        LinearLayout.LayoutParams colorLayoutParams = new LinearLayout.LayoutParams(400, 400);

        LinearLayout colorLayout = new LinearLayout(mContext);
        colorLayout.setBackgroundColor(mColors[position]);
        colorLayout.setLayoutParams(colorLayoutParams);

        return colorLayout;
    }
}
}

最后实现效果图

可以通过手势拖拽切换,也可以点击按钮切换。StackView就简单介绍到这里,有需求的同学可以扩展,可以实现比较好的效果。StackView是androidAPI3.0以后的。

附上国内镜像API

下一节我们介绍一下Dialog控件

时间: 2024-08-02 06:57:45

Android学习笔记二十七之ExpandableListView可折叠列表和StackView栈视图的相关文章

Android学习笔记二十四之ListView列表视图二

Android学习笔记二十四之ListView列表视图二 前面一篇我们介绍了常用的几种适配器的简单实现和ListView的简单使用,这一篇中,我们介绍一下ListView的优化和一些其它的问题. ListView优化方法一 在ListView中,我们最常用的就是自定义Adapter,在我们自定义Adapter中,需要实现两个比较重要的方法getCount()和getView(),前者是负责计算ListView的总Item数,后者是生成Item,有多少个Item就会调用getView()方法多少次

Android学习笔记二十九之SwipeRefreshLayout、RecyclerView和CardView

Android学习笔记二十九之SwipeRefreshLayout.RecyclerView和CardView 前面我们介绍了AlertDialog和几个常用的Dialog,ProgressDialog进度条提示框.DatePickerDialog日期选择对话框和TimePickerDialog时间选择对话框.这一节我们介绍几个新的API控件SwipeRefreshLayout.RecyclerView和CardView,这几个API控件都是google在Android5.0推出的.下面我们来学

Android学习笔记(十七)——使用意图调用内置应用程序

使用意图调用内置应用程序 1.创建一个新的Android项目并命名为Intents,在main.xml文件中添加两个Button: <Button android:id="@+id/btn_webbrowser" android:layout_width="fill_parent" android:layout_height="wrap_content" android:onClick="onClickWebBrowser&quo

angular学习笔记(二十七)-$http(5)-使用$http构建RESTful架构

在angular中有一个特别为RESTful架构而定制的服务,是在$http的基础上进行了封装. 但是为了学习,我们先看看用直接$http是如何构建RESTful架构的: 假设有一个银行卡的列表.需要的功能有: 可以通过id来获取用户123的指定id的卡     'GET'  'card/user/123/id' 可以获取用户123的所有的银行卡             'GET'  'card/user/123' 可以更新用户123的指定id的卡                'POST' '

Android学习笔记二

17. 在ContentProvider中定义的getType()方法是定义URI的内容类型. 18. SQLiteDatabase类中的insert/delete/update/query方法其实也挺好用的,我在EquipmentProvider类中做了实现 19. Android专门有个单元测试项目(Android Test Project),在这个项目中,可以新建一个继承AndroidTestCase类的具体测试类来单元测试某个功能.我新建了一个AndroidTestProject项目,在

Android学习笔记二十之Toast吐司、Notification通知、PopupWindow弹出窗

Android学习笔记二十之Toast吐司.Notification通知.PopupWindow弹出窗 Toast吐司 Toast吐司是我们经常用到的一个控件,Toast是AndroidOS用来显示消息的一种机制,它与Dialog不同,Toast不会获取到焦点,通常显示一段时间之后就会自动消失,下面我们来介绍Toast的几种常用方式: 第一种,默认显示方式,也是最常用的方式: Toast.makeText(MainActivity.this, "这是默认的显示方式", Toast.LE

【Unity 3D】学习笔记二十七:unity游戏脚本(七)

使用C#编写游戏脚本 在前面提到,unity支持三种语言编写脚本:js,C#,boo.入门的时候建议只用js,因为js比较简单易懂,语法也不是很严格.但后来晋级的时候推荐使用C#,因为它比较符合unity的编程思想,执行效率更高.下面总结下怎么使用C#编写脚本. 继承MonoBehaviour类 在unity中,任何一个脚本,包括上述三种语言都需要去继承MonoBehaviour这个类.为什么我们之前写JS代码的时候没有继承咧?因为在创建JS代码的时候,系统会将其类名与继承关系隐藏起来. 在pr

Android学习笔记二十五之ListView多布局实现

Android学习笔记二十五之ListView多布局实现 这一节是介绍ListView这个控件的最后一节,实现一个Item的多布局.像我们经常在用的各种即时通讯工具,QQ.微信等,假设他们的会话界面是ListView实现的,那么ListView就有多种Item布局,这一节,我们就来实现一个ListView的多种Item. 要实现ListView里面有多种Item,就要重写适配器的两个方法getViewTypeCount()和getItemViewType(int position),第一个方法是

Android学习笔记二-Linear Layout

1.LinearLayout是子view均为单方向的,即均为水平或垂直方向的布局.你可以用android:orientation属性来 定义layout方向 所有子view都是一个挨着一个的,所以一个垂直列表,不管它本身多宽,同时只能有一行.若是水平列表,则都等高. 2.LayoutWeight 用来操控各个子view的相对比例,,即各个子元素对空间的使用权重 Weight并非网上很多文章所叙述的那样(文章都过于片面),weight是指某个组件在布局中[剩余空间]中的显示权重,那么所谓的剩余空间