Beta 1.0 中国家用电器研究院旗下新媒体 | 家电数码互动评测第一平台
查看: 1189|回复: 0

【烙印教室】Android提高之多级树形菜单的实现

[复制链接]

Always_Online

  • TA的每日心情
    奋斗
    2016-3-5 21:07
  • 签到天数: 503 天

    [LV.9]以坛为家II




    【烙印教室】Android提高之多级树形菜单的实现 [复制链接]
    1189 0
    打印 上一主题 下一主题
    2015-6-13 19:10:21
    在Android里要实现树形菜单,都是用ExpandableList(也有高手自己继承ListView或者LinearLayout来做),但是ExpandableList一般只能实现2级树形菜单......本文也依然使用ExpandableList,但是要实现的是3级树形菜单。本文程序运行效果图:

    当用BaseExpandableListAdapter来实现二级树形菜单时,父项(getGroupView())和子项(getChildView())都是使用TextView。当要实现三级树形菜单时,子项(getChildView())就必须使用ExpandableList了.......另外还要定义结构体来方便调用三级树形的数据,二级树形菜单可以用如下:

    static public class TreeNode{
                    Object parent;
                    List childs=new ArrayList();
            }
    复制代码
    三级树形菜单可以用如下,子项是二级树形菜单的结构体:

    static public class SuperTreeNode {
                    Object parent;
                    //二级树形菜单的结构体
                    List[tr] childs = new ArrayList[tr]();
            }
    复制代码
    实现三级树形菜单有两点要注意的:1、第二级也是个树形菜单,因此必须在第二级项目展开/回收时设置足够的空间来完全显示二级树形菜单;2、在实现三级树形菜单时,发现菜单的方法都是用不了(如OnChildClickListener、OnGroupClickListener等),因此要获得选中的数据就必须在外部定义好回调函数,然后在第二级生成二级树形菜单时回调这个外部函数。PS:本文在解决No.2关键点的时候,只能取得第三级选中的序号.....而第一,第二级依然无法获取其序号。main.xml源码如下:

    <linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
            androidrientation="vertical" android:layout_width="fill_parent"
            android:layout_height="fill_parent">
            <linearlayout android:id="@+id/LinearLayout01"
                    android:layout_width="wrap_content" android:layout_height="wrap_content">
                    <button android:layout_height="wrap_content" android:text="两层结构"
                            android:layout_width="160dip" android:id="@+id/btnNormal">
                    <button android:layout_height="wrap_content" android:text="三层结构"
                            android:layout_width="160dip" android:id="@+id/btnSuper">

            <expandablelistview android:id="@+id/ExpandableListView01"
                    android:layout_width="fill_parent" android:layout_height="fill_parent">

    复制代码
    testExpandableList.java是主类,调用其他工具类,源码如下:
    package com.testExpandableList;


    import java.util.List;
    import android.app.Activity;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    import android.widget.ExpandableListView;
    import android.widget.ExpandableListView.OnChildClickListener;
    import android.widget.Toast;

    public class testExpandableList extends Activity {
        /** Called when the activity is first created. */
            ExpandableListView expandableList;
            TreeViewAdapter adapter;
            SuperTreeViewAdapter superAdapter;
            Button btnNormal,btnSuper;
        // Sample data set.  children contains the children (String[]) for groups.
        public String[] groups = { "xxxx好友", "xxxx同学", "xxxxx女人"};
        public String[][]  child= {
                { "A君", "B君", "C君", "D君" },
                { "同学甲", "同学乙", "同学丙"},
                { "御姐", "萝莉" }
        };

        public String[] parent = { "xxxx好友", "xxxx同学"};
        public String[][][]  child_grandson= {
                        {{"A君"},
                                {"AA","AAA"}},
                        {{"B君"},
                                {"BBB","BBBB","BBBBB"}},
                        {{"C君"},
                                {"CCC","CCCC"}},
                        {{"D君"},
                                {"DDD","DDDD","DDDDD"}},
        };

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            this.setTitle("ExpandableListView练习----hellogv");
            btnNormal=(Button)this.findViewById(R.id.btnNormal);
            btnNormal.setOnClickListener(new ClickEvent());
            btnSuper=(Button)this.findViewById(R.id.btnSuper);
            btnSuper.setOnClickListener(new ClickEvent());
            adapter=new TreeViewAdapter(this,TreeViewAdapter.PaddingLeft>>1);
            superAdapter=new SuperTreeViewAdapter(this,stvClickEvent);
            expandableList=(ExpandableListView) testExpandableList.this.findViewById(R.id.ExpandableListView01);
        }

        class ClickEvent implements View.OnClickListener{

                    @Override
                    public void onClick(View v) {
                            adapter.RemoveAll();
                            adapter.notifyDataSetChanged();
                            superAdapter.RemoveAll();
                            superAdapter.notifyDataSetChanged();

                            if(v==btnNormal)
                            {
                            List[tr] treeNode = adapter.GetTreeNode();
                            for(int i=0;i<groups.length;i++)
                            {
                                    TreeViewAdapter.TreeNode node=new TreeViewAdapter.TreeNode();
                                    node.parent=groups;
                                    for(int ii=0;ii<child.length;ii++)
                                    {
                                            node.childs.add(child[ii]);
                                    }
                                    treeNode.add(node);
                            }

                            adapter.UpdateTreeNode(treeNode);     
                            expandableList.setAdapter(adapter);
                            expandableList.setOnChildClickListener(new OnChildClickListener(){

                                            @Override
                                            public boolean onChildClick(ExpandableListView arg0, View arg1,
                                                            int parent, int children, long arg4) {

                                                    String str="parent id:"+String.valueOf(parent)+",children id:"+String.valueOf(children);
                                                    Toast.makeText(testExpandableList.this, str, 300).show();
                                                    return false;
                                            }
                            });
                            }
                            else if(v==btnSuper){
                                    List superTreeNode = superAdapter.GetTreeNode();
                            for(int i=0;i<parent.length;i++) 第一层
                            {
                                    SuperTreeViewAdapter.SuperTreeNode superNode=new SuperTreeViewAdapter.SuperTreeNode();
                                    superNode.parent=parent;

                                    //第二层
                                    for(int ii=0;ii<child_grandson.length;ii++)
                                {
                                        TreeViewAdapter.TreeNode node=new TreeViewAdapter.TreeNode();
                                        node.parent=child_grandson[ii][0][0];//第二级菜单的标题

                                        for(int iii=0;iii<child_grandson[ii][1].length;iii++) 第三级菜单
                                        {
                                                node.childs.add(child_grandson[ii][1][iii]);
                                        }
                                        superNode.childs.add(node);
                                }
                                    superTreeNode.add(superNode);

                            }
                            superAdapter.UpdateTreeNode(superTreeNode);
                            expandableList.setAdapter(superAdapter);
                            }
                    }
        }

        /**
         * 三级树形菜单的事件不再可用,本函数由三级树形菜单的子项(二级菜单)进行回调
         */
        OnChildClickListener stvClickEvent=new OnChildClickListener(){

                    @Override
                    public boolean onChildClick(ExpandableListView parent,
                                    View v, int groupPosition, int childPosition,
                                    long id) {
                            String str="parent id:"+String.valueOf(groupPosition)+",children id:"+String.valueOf(childPosition);
                            Toast.makeText(testExpandableList.this, str, 300).show();

                            return false;
                    }

        };
    }
    复制代码
    TreeViewAdapter.java是实现二级树形菜单的工具类,源码如下:
    package com.testExpandableList;

    import java.util.ArrayList;
    import java.util.List;
    import android.content.Context;
    import android.util.Log;
    import android.view.Gravity;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.AbsListView;
    import android.widget.BaseExpandableListAdapter;
    import android.widget.TextView;


    public class TreeViewAdapter extends BaseExpandableListAdapter{
            public static final int ItemHeight=48;//每项的高度
            public static final int PaddingLeft=36;//每项的高度
            private int myPaddingLeft=0;//如果是由SuperTreeView调用,则作为子项需要往右移

            static public class TreeNode{
                    Object parent;
                    List childs=new ArrayList();
            }

            List[tr] treeNodes = new ArrayList[tr]();
            Context parentContext;

            public TreeViewAdapter(Context view,int myPaddingLeft)
            {
                    parentContext=view;
                    this.myPaddingLeft=myPaddingLeft;
            }

            public List[tr] GetTreeNode()
            {
                    return treeNodes;
            }

            public void UpdateTreeNode(List[tr] nodes)
            {
                    treeNodes=nodes;
            }

            public void RemoveAll()
            {
                    treeNodes.clear();
            }

            public Object getChild(int groupPosition, int childPosition) {
                    return treeNodes.get(groupPosition).childs.get(childPosition);
            }

            public int getChildrenCount(int groupPosition) {
                    return treeNodes.get(groupPosition).childs.size();
            }

            static public TextView getTextView(Context context) {
                    AbsListView.LayoutParams lp = new AbsListView.LayoutParams(
                                    ViewGroup.LayoutParams.FILL_PARENT, ItemHeight);

                    TextView textView = new TextView(context);
                    textView.setLayoutParams(lp);
                    textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
                    return textView;
            }

            public View getChildView(int groupPosition, int childPosition,
                            boolean isLastChild, View convertView, ViewGroup parent) {
                    TextView textView = getTextView(this.parentContext);
                    textView.setText(getChild(groupPosition, childPosition).toString());
                    textView.setPadding(myPaddingLeft+PaddingLeft, 0, 0, 0);
                    return textView;
            }

            public View getGroupView(int groupPosition, boolean isExpanded,
                            View convertView, ViewGroup parent) {
                    TextView textView = getTextView(this.parentContext);
                    textView.setText(getGroup(groupPosition).toString());
                    textView.setPadding(myPaddingLeft+(PaddingLeft>>1), 0, 0, 0);
                    return textView;
            }

            public long getChildId(int groupPosition, int childPosition) {
                    return childPosition;
            }

            public Object getGroup(int groupPosition) {
                    return treeNodes.get(groupPosition).parent;
            }

            public int getGroupCount() {
                    return treeNodes.size();
            }

            public long getGroupId(int groupPosition) {
                    return groupPosition;
            }

            public boolean isChildSelectable(int groupPosition, int childPosition) {
                    return true;
            }

            public boolean hasStableIds() {
                    return true;
            }
    }
    复制代码
    SuperTreeViewAdapter.java是实现三级树形菜单的工具类,会用到TreeViewAdapter.java,源码如下:
    package com.testExpandableList;

    import java.util.ArrayList;
    import java.util.List;
    import com.testExpandableList.TreeViewAdapter.TreeNode;
    import android.content.Context;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.AbsListView;
    import android.widget.BaseExpandableListAdapter;
    import android.widget.ExpandableListView;
    import android.widget.ExpandableListView.OnChildClickListener;
    import android.widget.ExpandableListView.OnGroupCollapseListener;
    import android.widget.ExpandableListView.OnGroupExpandListener;
    import android.widget.TextView;

    public class SuperTreeViewAdapter extends BaseExpandableListAdapter {

            static public class SuperTreeNode {
                    Object parent;
                    //二级树形菜单的结构体
                    List[tr] childs = new ArrayList[tr]();
            }

            private List superTreeNodes = new ArrayList();
            private Context parentContext;
            private OnChildClickListener stvClickEvent;//外部回调函数

            public SuperTreeViewAdapter(Context view,OnChildClickListener stvClickEvent) {
                    parentContext = view;
                    this.stvClickEvent=stvClickEvent;
            }

            public List GetTreeNode() {
                    return superTreeNodes;
            }

            public void UpdateTreeNode(List node) {
                    superTreeNodes = node;
            }

            public void RemoveAll()
            {
                    superTreeNodes.clear();
            }

            public Object getChild(int groupPosition, int childPosition) {
                    return superTreeNodes.get(groupPosition).childs.get(childPosition);
            }

            public int getChildrenCount(int groupPosition) {
                    return superTreeNodes.get(groupPosition).childs.size();
            }

            public ExpandableListView getExpandableListView() {
                    AbsListView.LayoutParams lp = new AbsListView.LayoutParams(
                                    ViewGroup.LayoutParams.FILL_PARENT, TreeViewAdapter.ItemHeight);
                    ExpandableListView superTreeView = new ExpandableListView(parentContext);
                    superTreeView.setLayoutParams(lp);
                    return superTreeView;
            }

            /**
             * 三层树结构中的第二层是一个ExpandableListView
             */        
            public View getChildView(int groupPosition, int childPosition,
                            boolean isLastChild, View convertView, ViewGroup parent) {
                    // 是
                    final ExpandableListView treeView = getExpandableListView();
                    final TreeViewAdapter treeViewAdapter = new TreeViewAdapter(this.parentContext,0);
                    List[tr] tmp = treeViewAdapter.GetTreeNode();//临时变量取得TreeViewAdapter的TreeNode集合,可为空
                    final TreeNode treeNode=(TreeNode) getChild(groupPosition, childPosition);
                    tmp.add(treeNode);
                    treeViewAdapter.UpdateTreeNode(tmp);
                    treeView.setAdapter(treeViewAdapter);

                    //关键点:取得选中的二级树形菜单的父子节点,结果返回给外部回调函数
                    treeView.setOnChildClickListener(this.stvClickEvent);

                    /**
                     * 关键点:第二级菜单展开时通过取得节点数来设置第三级菜单的大小
                     */
                    treeView.setOnGroupExpandListener(new OnGroupExpandListener() {
                            @Override
                            public void onGroupExpand(int groupPosition) {

                                    AbsListView.LayoutParams lp = new AbsListView.LayoutParams(
                                                    ViewGroup.LayoutParams.FILL_PARENT,
                                                    (treeNode.childs.size()+1)*TreeViewAdapter.ItemHeight + 10);
                                    treeView.setLayoutParams(lp);
                            }
                    });

                    /**
                     * 第二级菜单回收时设置为标准Item大小
                     */
                    treeView.setOnGroupCollapseListener(new OnGroupCollapseListener() {
                            @Override
                            public void onGroupCollapse(int groupPosition) {

                                    AbsListView.LayoutParams lp = new AbsListView.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
                                                    TreeViewAdapter.ItemHeight);
                                    treeView.setLayoutParams(lp);
                            }
                    });
                    treeView.setPadding(TreeViewAdapter.PaddingLeft, 0, 0, 0);
                    return treeView;
            }

            /**
             * 三级树结构中的首层是TextView,用于作为title
             */
            public View getGroupView(int groupPosition, boolean isExpanded,
                            View convertView, ViewGroup parent) {
                    TextView textView = TreeViewAdapter.getTextView(this.parentContext);
                    textView.setText(getGroup(groupPosition).toString());
                    textView.setPadding(TreeViewAdapter.PaddingLeft, 0, 0, 0);
                    return textView;
            }

            public long getChildId(int groupPosition, int childPosition) {
                    return childPosition;
            }

            public Object getGroup(int groupPosition) {
                    return superTreeNodes.get(groupPosition).parent;
            }

            public int getGroupCount() {
                    return superTreeNodes.size();
            }

            public long getGroupId(int groupPosition) {
                    return groupPosition;
            }

            public boolean isChildSelectable(int groupPosition, int childPosition) {
                    return true;
            }

            public boolean hasStableIds() {
                    return true;
            }
    }
    复制代码
    总结,使用ExpandableList实现三级树形菜单时有些bug不好解决,而且定义三维数组的时候也要倍加小心......所以尽量把数据化简来使用二级树形菜单。



    免责声明                                                   
    本资源来自互联网,如有侵犯您的版权,请发邮件到765673603@qq.com联系我们将其删除。


    +10
    本版积分规则
    您需要登录后才可以回帖 登录 | 注册

    关闭

    站长推荐上一条 /2 下一条

    返回顶部 返回列表