有人可以告诉如何在Android中实现级别超过2的Treeview吗? 我想用textview和复选框创建一个多级树视图。
答案 0 :(得分:2)
您可以查看我的实施AndroidTreeView。
此this thread也很有用
答案 1 :(得分:1)
您必须扩展两个类才能创建树视图。这是示例代码
package com.example.mytreeview;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ExpandableListView;
import android.widget.SimpleExpandableListAdapter;
public class CustomExpandableListAdapter extends SimpleExpandableListAdapter {
Context context = null;
ExpandableListView topList;
LayoutInflater inflater = null;
HashMap<Integer, ArrayList<String[]>> data;
ArrayList<Map<String, String>> groupData;
ArrayList<List<Map<String, String>>> childData;
List<Map<String, String>> children;
Map<String, String> childMap;
ArrayList<String[]> list;
int listSize;
HashMap<Integer, CustomExpandableListView> elvCache = new HashMap<Integer, CustomExpandableListView>();
public CustomExpandableListAdapter( Context context,
ExpandableListView topList,
HashMap<Integer, ArrayList<String[]>> data,
ArrayList<Map<String, String>> groupData,
ArrayList<List<Map<String, String>>> childData ) {
super(
context,
groupData,
R.layout.grouprow,
new String[] { "name", "_id", "parentId" },
new int[] { R.id.tvLevelName, R.id.tvId, R.id.tvParentId },
childData,
R.layout.childrow,
new String[] { "name", "_id", "parentId" },
new int[] { R.id.tvLevelName, R.id.tvId, R.id.tvParentId }
);
this.context = context;
this.topList = topList;
this.data = data;
inflater = LayoutInflater.from(context);
}
@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
// if there are no child nodes then simply show the single row
HashMap <String, String> levelinfo = (HashMap<String, String>)getChild(groupPosition, childPosition);
Integer levelId = Integer.valueOf(levelinfo.get("_id"));
if (levelinfo.get("hasChild").toString().equalsIgnoreCase("N")) {
View v = super.getChildView(groupPosition, childPosition, isLastChild, convertView, parent);
return v;
}
else
{ // if the node contains child nodes then insert new expandable list
CustomExpandableListView v = null;
v = elvCache.get(levelId);
if (v == null) {
CreateData(levelinfo);
v = new CustomExpandableListView(context, null, android.R.attr.expandableListViewStyle);
v.setRows(groupData.size());
v.setPadding(10, 0, 0, 0);
v.setAdapter(new CustomExpandableListAdapter(context, topList, data, groupData, childData));
v.setOnGroupClickListener(new Level2GroupExpandListener());
elvCache.put(levelId, v);
}
return super.getChildView(groupPosition, childPosition, isLastChild, v, parent);
}
}
@Override
public boolean hasStableIds() {
return true;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
private int CalculateRowCount (ExpandableListView parent ) {
int count = 0;
//dig out the expanded child nodes in tree depth
for (int i = 0; i < parent.getExpandableListAdapter().getGroupCount(); i++) {
count++;
if (parent.isGroupExpanded(i)) {
count += GetFurtherChild(parent,i);
}
}
return count;
}
private int GetFurtherChild (ExpandableListView parent, int index){
int count = parent.getExpandableListAdapter().getChildrenCount(index);
ExpandableListView elv = null;
for (int i=0; i<parent.getExpandableListAdapter().getChildrenCount(index); i++ ) {
try {//check if this is expandable list
elv = (ExpandableListView)parent.getExpandableListAdapter().getChildView(index, i, false, null, parent);
if (elv != null && elv.isGroupExpanded(0)) {
count += GetFurtherChild(elv, 0);
}
} catch (Exception e) {
Log.d("Exception", e.getMessage());
}
}
return count;
}
public void CreateData(HashMap<String, String> nodeData){
// GET ID AND LEVEL OF PARENT NODE, LEVEL OF CHILD WILL BE LEVEL OF PARENT + 1
Integer id = Integer.valueOf(nodeData.get("_id").toString());
Integer level = Integer.valueOf(nodeData.get("level").toString()) + 1;
groupData = new ArrayList<Map<String, String>>();
childData = new ArrayList<List<Map<String, String>>>();
// GET CHILD LIST.
list = data.get(level);
listSize = list.size();
// PARENT NODE DATA IS ALREADY IN NODE DATA HASH MAP
groupData.add(nodeData);
// WE NEED TO CREATE CHILD DATA
children = new ArrayList<Map<String, String>>();
childData.add(children);
for (int i=0; i < listSize; i++) {
// GET THE DETAIL ARRAY
String [] levelDetail = list.get(i);
// IF PARENT NODE ID AND CHILD NODE PARENT ID IS SAME THEN CREATE ENTRY
if ( id == Integer.valueOf(levelDetail[1]) ) {
childMap = new HashMap<String, String>();
children.add(childMap);
childMap.put("_id", levelDetail[0]);
childMap.put("parentId", levelDetail[1]);
childMap.put("name", levelDetail[2]);
childMap.put("hasChild", levelDetail[3]);
childMap.put("level", String.valueOf(level));
}
}
}
class Level2GroupExpandListener implements ExpandableListView.OnGroupClickListener {
@Override
public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
if( parent.isGroupExpanded( groupPosition ) )
parent.collapseGroup( groupPosition );
else
parent.expandGroup( groupPosition );
if( parent instanceof CustomExpandableListView ) {
CustomExpandableListView celv = (CustomExpandableListView)parent;
Integer level = Integer.valueOf(((HashMap<String, String>) parent.getExpandableListAdapter().getGroup(groupPosition)).get("level").toString());
celv.setRows(CalculateRowCount(celv));
celv.requestLayout();
if (level > 1) {
while (((HashMap<String, String>)parent.getExpandableListAdapter().getGroup(0)).get("level").toString().equalsIgnoreCase("1") == false) {
parent = (ExpandableListView)parent.getParent();
celv = (CustomExpandableListView)parent;
celv.setRows(CalculateRowCount(parent));
celv.requestLayout();
}
}
}
topList.requestLayout();
return true;
}
}
您必须扩展两个类才能创建树视图。这是示例代码
package com.example.mytreeview;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ExpandableListView;
import android.widget.SimpleExpandableListAdapter;
public class CustomExpandableListAdapter extends SimpleExpandableListAdapter {
Context context = null;
ExpandableListView topList;
LayoutInflater inflater = null;
HashMap<Integer, ArrayList<String[]>> data;
ArrayList<Map<String, String>> groupData;
ArrayList<List<Map<String, String>>> childData;
List<Map<String, String>> children;
Map<String, String> childMap;
ArrayList<String[]> list;
int listSize;
HashMap<Integer, CustomExpandableListView> elvCache = new HashMap<Integer, CustomExpandableListView>();
public CustomExpandableListAdapter( Context context,
ExpandableListView topList,
HashMap<Integer, ArrayList<String[]>> data,
ArrayList<Map<String, String>> groupData,
ArrayList<List<Map<String, String>>> childData ) {
super(
context,
groupData,
R.layout.grouprow,
new String[] { "name", "_id", "parentId" },
new int[] { R.id.tvLevelName, R.id.tvId, R.id.tvParentId },
childData,
R.layout.childrow,
new String[] { "name", "_id", "parentId" },
new int[] { R.id.tvLevelName, R.id.tvId, R.id.tvParentId }
);
this.context = context;
this.topList = topList;
this.data = data;
inflater = LayoutInflater.from(context);
}
@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
// if there are no child nodes then simply show the single row
HashMap <String, String> levelinfo = (HashMap<String, String>)getChild(groupPosition, childPosition);
Integer levelId = Integer.valueOf(levelinfo.get("_id"));
if (levelinfo.get("hasChild").toString().equalsIgnoreCase("N")) {
View v = super.getChildView(groupPosition, childPosition, isLastChild, convertView, parent);
return v;
}
else
{ // if the node contains child nodes then insert new expandable list
CustomExpandableListView v = null;
v = elvCache.get(levelId);
if (v == null) {
CreateData(levelinfo);
v = new CustomExpandableListView(context, null, android.R.attr.expandableListViewStyle);
v.setRows(groupData.size());
v.setPadding(10, 0, 0, 0);
v.setAdapter(new CustomExpandableListAdapter(context, topList, data, groupData, childData));
v.setOnGroupClickListener(new Level2GroupExpandListener());
elvCache.put(levelId, v);
}
return super.getChildView(groupPosition, childPosition, isLastChild, v, parent);
}
}
@Override
public boolean hasStableIds() {
return true;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
private int CalculateRowCount (ExpandableListView parent ) {
int count = 0;
//dig out the expanded child nodes in tree depth
for (int i = 0; i < parent.getExpandableListAdapter().getGroupCount(); i++) {
count++;
if (parent.isGroupExpanded(i)) {
count += GetFurtherChild(parent,i);
}
}
return count;
}
private int GetFurtherChild (ExpandableListView parent, int index){
int count = parent.getExpandableListAdapter().getChildrenCount(index);
ExpandableListView elv = null;
for (int i=0; i<parent.getExpandableListAdapter().getChildrenCount(index); i++ ) {
try {//check if this is expandable list
elv = (ExpandableListView)parent.getExpandableListAdapter().getChildView(index, i, false, null, parent);
if (elv != null && elv.isGroupExpanded(0)) {
count += GetFurtherChild(elv, 0);
}
} catch (Exception e) {
Log.d("Exception", e.getMessage());
}
}
return count;
}
public void CreateData(HashMap<String, String> nodeData){
// GET ID AND LEVEL OF PARENT NODE, LEVEL OF CHILD WILL BE LEVEL OF PARENT + 1
Integer id = Integer.valueOf(nodeData.get("_id").toString());
Integer level = Integer.valueOf(nodeData.get("level").toString()) + 1;
groupData = new ArrayList<Map<String, String>>();
childData = new ArrayList<List<Map<String, String>>>();
// GET CHILD LIST.
list = data.get(level);
listSize = list.size();
// PARENT NODE DATA IS ALREADY IN NODE DATA HASH MAP
groupData.add(nodeData);
// WE NEED TO CREATE CHILD DATA
children = new ArrayList<Map<String, String>>();
childData.add(children);
for (int i=0; i < listSize; i++) {
// GET THE DETAIL ARRAY
String [] levelDetail = list.get(i);
// IF PARENT NODE ID AND CHILD NODE PARENT ID IS SAME THEN CREATE ENTRY
if ( id == Integer.valueOf(levelDetail[1]) ) {
childMap = new HashMap<String, String>();
children.add(childMap);
childMap.put("_id", levelDetail[0]);
childMap.put("parentId", levelDetail[1]);
childMap.put("name", levelDetail[2]);
childMap.put("hasChild", levelDetail[3]);
childMap.put("level", String.valueOf(level));
}
}
}
class Level2GroupExpandListener implements ExpandableListView.OnGroupClickListener {
@Override
public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
if( parent.isGroupExpanded( groupPosition ) )
parent.collapseGroup( groupPosition );
else
parent.expandGroup( groupPosition );
if( parent instanceof CustomExpandableListView ) {
CustomExpandableListView celv = (CustomExpandableListView)parent;
Integer level = Integer.valueOf(((HashMap<String, String>) parent.getExpandableListAdapter().getGroup(groupPosition)).get("level").toString());
celv.setRows(CalculateRowCount(celv));
celv.requestLayout();
if (level > 1) {
while (((HashMap<String, String>)parent.getExpandableListAdapter().getGroup(0)).get("level").toString().equalsIgnoreCase("1") == false) {
parent = (ExpandableListView)parent.getParent();
celv = (CustomExpandableListView)parent;
celv.setRows(CalculateRowCount(parent));
celv.requestLayout();
}
}
}
topList.requestLayout();
return true;
}
}
}
package com.example.mytreeview;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.View;
import android.widget.ExpandableListView;
public class CustomExpandableListView extends ExpandableListView {
public static int ROW_HEIGHT;
private int rows;
public CustomExpandableListView(Context context, AttributeSet attrs, int defStyle) {
super( context, attrs, defStyle );
if (Main.screenSize == ScreenSize.NARROW)
ROW_HEIGHT = 45;
else
ROW_HEIGHT = 31;
}
public void setRows( int rows ) {
this.rows = rows;
}
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension( getMeasuredWidth(), rows*ROW_HEIGHT);
}
protected void onLayout (boolean changed, int left, int top, int right, int bottom) {
super.onLayout( changed, left,top,right,bottom );
}
private String decodeMeasureSpec( int measureSpec ) {
int mode = View.MeasureSpec.getMode( measureSpec );
String modeString = "<> ";
switch( mode ) {
case View.MeasureSpec.UNSPECIFIED:
modeString = "UNSPECIFIED ";
break;
case View.MeasureSpec.EXACTLY:
modeString = "EXACTLY ";
break;
case View.MeasureSpec.AT_MOST:
modeString = "AT_MOST ";
break;
}
return modeString+Integer.toString( View.MeasureSpec.getSize( measureSpec ) );
}
}
package com.example.mytreeview;
public enum ScreenSize {
NARROW,
WIDE
}
}
package com.example.mytreeview;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.View;
import android.widget.ExpandableListView;
public class CustomExpandableListView extends ExpandableListView {
public static int ROW_HEIGHT;
private int rows;
public CustomExpandableListView(Context context, AttributeSet attrs, int defStyle) {
super( context, attrs, defStyle );
if (Main.screenSize == ScreenSize.NARROW)
ROW_HEIGHT = 45;
else
ROW_HEIGHT = 31;
}
public void setRows( int rows ) {
this.rows = rows;
}
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension( getMeasuredWidth(), rows*ROW_HEIGHT);
}
protected void onLayout (boolean changed, int left, int top, int right, int bottom) {
super.onLayout( changed, left,top,right,bottom );
}
private String decodeMeasureSpec( int measureSpec ) {
int mode = View.MeasureSpec.getMode( measureSpec );
String modeString = "<> ";
switch( mode ) {
case View.MeasureSpec.UNSPECIFIED:
modeString = "UNSPECIFIED ";
break;
case View.MeasureSpec.EXACTLY:
modeString = "EXACTLY ";
break;
case View.MeasureSpec.AT_MOST:
modeString = "AT_MOST ";
break;
}
return modeString+Integer.toString( View.MeasureSpec.getSize( measureSpec ) );
}
}
package com.example.mytreeview;
public enum ScreenSize {
NARROW,
WIDE
}