Android提高十七篇之多级树形菜单的实现
在
Android里要实现树形菜单,都是用ExpandableList(也有高手自己继承ListView或者LinearLayout来做),但是
ExpandableList一般只能实现2级树形菜单......本文也依然使用ExpandableList,但是要实现的是3级树形菜单。
本文程序运行效果图:
当
用BaseExpandableListAdapter来实现二级树形菜单时,父项(getGroupView())和子项
(getChildView())都是使用TextView。当要实现三级树形菜单时,子项(getChildView())就必须使用
ExpandableList了.......另外还要定义结构体来方便调用三级树形的数据,
二级树形菜单可以用如下:
view plaincopy to clipboardprint?
-
static
public
class
TreeNode{
-
Object parent;
-
List<Object> childs=new
ArrayList<Object>();
-
}
三级树形菜单可以用如下,子项是二级树形菜单的结构体:
view plaincopy to clipboardprint?
-
static
public
class
SuperTreeNode {
-
Object parent;
-
-
List<TreeViewAdapter.TreeNode> childs = new
ArrayList<TreeViewAdapter.TreeNode>();
-
}
实现三级树形菜单有两点要注意的:
1、第二级也是个树形菜单,因此必须在第二级项目展开/回收时设置足够的空间来完全显示二级树形菜单;
2、在实现三级树形菜单时,发现菜单的方法都是用不了(如OnChildClickListener、OnGroupClickListener等),因此要获得选中的数据就必须在外部定义好回调函数,然后在第二级生成二级树形菜单时回调这个外部函数。
PS:本文在解决No.2关键点的时候,只能取得第三级选中的序号.....而第一,第二级依然无法获取其序号。
main.xml源码如下:
view plaincopy to clipboardprint?
-
<?
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
>
testExpandableList.java是主类,调用其他工具类,源码如下:
view plaincopy to clipboardprint?
-
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 {
-
-
ExpandableListView expandableList;
-
TreeViewAdapter adapter;
-
SuperTreeViewAdapter superAdapter;
-
Button btnNormal,btnSuper;
-
-
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<TreeViewAdapter.TreeNode> treeNode = adapter.GetTreeNode();
-
for
(
int
i=
0
;i<groups.length;i++)
-
{
-
TreeViewAdapter.TreeNode node=new
TreeViewAdapter.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(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<SuperTreeViewAdapter.SuperTreeNode> superTreeNode = superAdapter.GetTreeNode();
-
for
(
int
i=
0
;i<parent.length;i++)
-
{
-
SuperTreeViewAdapter.SuperTreeNode superNode=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=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是实现二级树形菜单的工具类,源码如下:
view plaincopy to clipboardprint?
-
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
;
-
-
static
public
class
TreeNode{
-
Object parent;
-
List<Object> childs=new
ArrayList<Object>();
-
}
-
-
List<TreeNode> treeNodes = new
ArrayList<TreeNode>();
-
Context parentContext;
-
-
public
TreeViewAdapter(Context view,
int
myPaddingLeft)
-
{
-
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) {
-
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
,源码如下:
view plaincopy to clipboardprint?
-
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<TreeViewAdapter.TreeNode> childs = new
ArrayList<TreeViewAdapter.TreeNode>();
-
}
-
-
private
List<SuperTreeNode> superTreeNodes =
new
ArrayList<SuperTreeNode>();
-
private
Context parentContext;
-
private
OnChildClickListener stvClickEvent;
-
-
public
SuperTreeViewAdapter(Context view,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) {
-
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;
-
}
-
-
-
-
-
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<TreeNode> tmp = treeViewAdapter.GetTreeNode();
-
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);
-
}
-
});
-
-
-
-
-
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;
-
}
-
-
-
-
-
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;
-
}
-
-