Android树形菜单

在Android里要实现树形菜单,都是用ExpandableList(也有高手自己继承ListView或者LinearLayout来做),但是 ExpandableList一般只能实现2级树形菜单......本文也依然使用ExpandableList,但是要实现的是3级树形菜单。 本文程序运行效果图:

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

 

Object parent;

 

List< Object> childs=newArrayList< Object>();

 

}

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

 

Object parent;

 

//二级树形菜单的结构体

 

List< TreeViewAdapter.TreeNode>childs = new ArrayList< TreeViewAdapter.TreeNode>();

 

}

实现三级树形菜单有两点要注意的:  1、第二级也是个树形菜单,因此必须在第二级项目展开/回收时设置足够的空间来完全显示二级树形菜单;
  2、在实现三级树形菜单时,发现菜单的方法都是用不了(如OnChildClickListener、OnGroupClickListener等),因此要获得选中的数据就必须在外部定义好回调函数,然后在第二级生成二级树形菜单时回调这个外部函数。
< ? xml version = "1.0" encoding = "utf-8" ?>

 

< LinearLayout xmlns:android ="http://schemas.android.com/apk/res/android"

 

android:orientation = "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 >

 

< Button android:layout_height ="wrap_content" android:text = "三层结构"

 

android:layout_width = "160dip"android:id = "@+id/btnSuper" > < / Button >

 

< / LinearLayout >

 

< ExpandableListView android:id ="@+id/ExpandableListView01"

 

android:layout_width ="fill_parent" android:layout_height = "fill_parent" >< / ExpandableListView >

 

 

< / LinearLayout >

 

< ?xml version="1.0"encoding="utf-8"?>

 

 

< LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"

 

android:orientation="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>

 

 

< Button

android:layout_height="wrap_content"

android:text="三层结构"

 

android:layout_width="160dip"

android:id="@+id/btnSuper">

 

< /Button>

 

< /LinearLayout>

 

< ExpandableListView

android:id="@+id/ExpandableListView01"

 

android:layout_width="fill_parent"

android:layout_height="fill_parent">

 

< /ExpandableListView>

 

< /LinearLayout>

 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;

 

importandroid.widget.ExpandableListView.OnChildClickListener;

 

import android.widget.Toast;

 

 

public class testExpandableList extendsActivity {

 

/** Called when the activity is firstcreated. */

 

ExpandableListView expandableList;

 

TreeViewAdapter adapter;

 

SuperTreeViewAdapter superAdapter;

 

Button btnNormal,btnSuper;

 

 

// Sample data set. children[i] containsthe children (String[]) for groups[i].

 

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(BundlesavedInstanceState) {

 

super .onCreate(savedInstanceState);

 

setContentView(R.layout.main);

 

this .setTitle( "ExpandableListView练习----hellogv" );

 

btnNormal=(Button)this.findViewById(R.id.btnNormal);

 

btnNormal.setOnClickListener(newClickEvent());

 

btnSuper=(Button)this .findViewById(R.id.btnSuper);

 

btnSuper.setOnClickListener(newClickEvent());

 

adapter=new TreeViewAdapter( this,TreeViewAdapter.PaddingLeft>> 1 );

 

superAdapter=new SuperTreeViewAdapter( this,stvClickEvent);

 

expandableList=(ExpandableListView) testExpandableList.this

@Override

public void onClick(View v) {

adapter.RemoveAll();

adapter.notifyDataSetChanged();

superAdapter.RemoveAll();

superAdapter.notifyDataSetChanged();

 

if (v==btnNormal)

{

List< TreeViewAdapter.TreeNode>treeNode = adapter.GetTreeNode();

for ( int i= 0 ;i< groups.length;i++)

{

 

TreeViewAdapter.TreeNode node=newTreeViewAdapter.TreeNode();

node.parent=groups[i];

 

for ( int ii= 0 ;ii<child[i].length;ii++)

{

node.childs.add(child[i][ii]);

}

treeNode.add(node);

}

 

adapter.UpdateTreeNode(treeNode);

expandableList.setAdapter(adapter);

expandableList.setOnChildClickListener(newOnChildClickListener(){

 

@Override

public booleanonChildClick(ExpandableListView arg0, View arg1,int parent, int children, longarg4) {

 

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<SuperTreeViewAdapter.SuperTreeNode> superTreeNode =superAdapter.GetTreeNode();

for ( int i= 0 ;i< parent.length;i++) //第一层

{

SuperTreeViewAdapter.SuperTreeNodesuperNode=new SuperTreeViewAdapter.SuperTreeNode();

superNode.parent=parent[i];

//第二层

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=newOnChildClickListener(){

 

@Override

public boolean onChildClick(ExpandableListViewparent,

View v, int groupPosition, intchildPosition,long id) {

 

String str="parent id:"+String.valueOf(groupPosition)+ ",children id:"+String.valueOf(childPosition);

Toast.makeText(testExpandableList.this ,str, 300 ).show();

return false ;

}

 

};

}

 

 

 

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;

importandroid.widget.BaseExpandableListAdapter;

import android.widget.TextView;

 

public class TreeViewAdapter extendsBaseExpandableListAdapter{

public static final int ItemHeight= 48 ; //每项的高度

public static final int PaddingLeft= 36 ;//每项的高度

private int myPaddingLeft= 0 ; //如果是由SuperTreeView调用,则作为子项需要往右移

static public class TreeNode{

Object parent;

List< Object> childs=newArrayList< Object>();

}

 

 

List< TreeNode> treeNodes = newArrayList< TreeNode>();

Context parentContext;

public TreeViewAdapter(Context view, intmyPaddingLeft)

{

 

parentContext=view;

this .myPaddingLeft=myPaddingLeft;

}

 

public List< TreeNode> GetTreeNode(){

return treeNodes;

}

 

public void UpdateTreeNode(List<TreeNode> nodes){

treeNodes=nodes;

}

 

 

public void RemoveAll(){

 

treeNodes.clear();

}

 

public Object getChild( int groupPosition,int childPosition) {

returntreeNodes.get(groupPosition).childs.get(childPosition);

}

 

public int getChildrenCount( intgroupPosition) {

returntreeNodes.get(groupPosition).childs.size();

}

 

static public TextView getTextView(Contextcontext) {

AbsListView.LayoutParams lp = newAbsListView.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( intgroupPosition, 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( intgroupPosition, 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( intgroupPosition, int childPosition) {

return true ;

}

 

public boolean hasStableIds() {

return true ;

}

}

 

 

 

SuperTreeViewAdapter.java是实现三级树形菜单的工具类,会用到TreeViewAdapter.java,源码如下:

 

 

package com.testExpandableList;

 

import java.util.ArrayList;

import java.util.List;

importcom.testExpandableList.TreeViewAdapter.TreeNode;

import android.content.Context;

import android.view.View;

import android.view.ViewGroup;

import android.widget.AbsListView;

importandroid.widget.BaseExpandableListAdapter;

import android.widget.ExpandableListView;

importandroid.widget.ExpandableListView.OnChildClickListener;

importandroid.widget.ExpandableListView.OnGroupCollapseListener;

importandroid.widget.ExpandableListView.OnGroupExpandListener;

import android.widget.TextView;

 

public class SuperTreeViewAdapter extendsBaseExpandableListAdapter {

 

static public class SuperTreeNode {

Object parent;

//二级树形菜单的结构体

List< TreeViewAdapter.TreeNode>childs = new ArrayList< TreeViewAdapter.TreeNode>();

}

 

private List< SuperTreeNode> superTreeNodes= new ArrayList< SuperTreeNode>();

private Context parentContext;

private OnChildClickListener stvClickEvent;//外部回调函数

public SuperTreeViewAdapter(Contextview,OnChildClickListener stvClickEvent) {

parentContext = view;

this .stvClickEvent=stvClickEvent;

}

 

public List< SuperTreeNode>GetTreeNode() {

return superTreeNodes;

}

 

public void UpdateTreeNode(List<SuperTreeNode> node) {

superTreeNodes = node;

}

 

 

public void RemoveAll(){

superTreeNodes.clear();

}

 

public Object getChild( int groupPosition,int childPosition) {

returnsuperTreeNodes.get(groupPosition).childs.get(childPosition);

}

 

public int getChildrenCount( intgroupPosition) {

returnsuperTreeNodes.get(groupPosition).childs.size();

}

 

public ExpandableListViewgetExpandableListView() {

AbsListView.LayoutParams lp = newAbsListView.LayoutParams(

ViewGroup.LayoutParams.FILL_PARENT,TreeViewAdapter.ItemHeight);

ExpandableListView superTreeView = newExpandableListView(parentContext);

superTreeView.setLayoutParams(lp);

return superTreeView;

}

 

/**

 

* 三层树结构中的第二层是一个ExpandableListView

*/

 

public View getChildView( intgroupPosition, int childPosition,

boolean isLastChild, View convertView,ViewGroup parent) {

// 是

final ExpandableListView treeView =getExpandableListView();

final TreeViewAdapter treeViewAdapter = newTreeViewAdapter( this .parentContext, 0 );

List< TreeNode> 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(newOnGroupExpandListener() {

 

@Override

public void onGroupExpand( intgroupPosition) {

AbsListView.LayoutParams lp = newAbsListView.LayoutParams(

ViewGroup.LayoutParams.FILL_PARENT,(treeNode.childs.size()+1)*TreeViewAdapter.ItemHeight + 10 );

 

treeView.setLayoutParams(lp);

}

});

 

/**

* 第二级菜单回收时设置为标准Item大小

*/

 

treeView.setOnGroupCollapseListener(newOnGroupCollapseListener() {

 

 

@Override

public void onGroupCollapse( intgroupPosition) {

 

AbsListView.LayoutParams lp = newAbsListView.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,

TreeViewAdapter.ItemHeight);

treeView.setLayoutParams(lp);

}

});

treeView.setPadding(TreeViewAdapter.PaddingLeft,0 , 0 , 0 );

 

return treeView;

}

 

/**

* 三级树结构中的首层是TextView,用于作为title

*/

 

public View getGroupView( intgroupPosition, 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){

returnsuperTreeNodes.get(groupPosition).parent;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值