android 从xml文件读取数据初始化,并实现无分级的树状菜单的显示

本文详细介绍了如何使用ListView实现树状菜单的显示,并通过封装节点信息的类来管理菜单项,包括节点的标识、文本、是否为父节点、是否为子节点、父节点ID、深度和展开状态。此外,还提供了XML文件解析方法和树状菜单的动态展示逻辑。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1.树状菜单的实现原理(借鉴网上一哥们的代码,同时解决了代码中存在的小问题):

      使用ListView模仿树状菜单,如果某个节点存在父节点,在节点展开的时候就相应的设置与其节点深度有关的缩进距离,具体见代码

      所有的节点信息都封装进,节点类中,类的属性定义了节点的全部信息,对应xml文件中的相应属性

  2.实现代码:

    1封装节点信息的类

/**
 * 
 * @author wx
 *	封装节点属性的类
 */
public class TreeElement {
	//节点的标识id,用来唯一标识节点
	private String id;
	//节点上显示的文本内容
	private String text ;
	//节点是否有父节点
	private boolean hasparent;
	//节点是否有子节点
	private boolean haschild ;
	//父节点的id
	private String parentid;
	//节点的深度
	private int level;
	//节点是否展开
	private boolean expanded;
	
	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getOutlineTitle() {
		return text;
	}

	public void setOutlineTitle(String outlineTitle) {
		this.text = outlineTitle;
	}

	public boolean isMhasParent() {
		return hasparent;
	}

	public void setMhasParent(boolean mhasParent) {
		this.hasparent = mhasParent;
	}

	public boolean hasChild() {
		return haschild;
	}

	public void sethasChild(boolean hasChild) {
		this.haschild = hasChild;
	}

	public String getParent() {
		return parentid;
	}

	public void setParent(String parent) {
		this.parentid = parent;
	}

	public int getLevel() {
		return level;
	}

	public void setLevel(int level) {
		this.level = level;
	}

	public boolean isExpanded() {
		return expanded;
	}

	public void setExpanded(boolean expanded) {
		this.expanded = expanded;
	}
	/**
	 * 带参构造方法
	 * @param id
	 * @param text
	 * @param hasparent
	 * @param haschild
	 * @param parentid
	 * @param level
	 * @param expanded
	 */
	public TreeElement(String id, String text, boolean hasparent,
			boolean haschild, String parentid, int level, boolean expanded) {
		super();
		this.id = id;
		this.text = text;
		this.hasparent = hasparent;
		this.haschild = haschild;
		this.parentid = parentid;
		this.level = level;
		this.expanded = expanded;
	}	

}


2.实现树状菜单显示的类,使用ArrayAdapter动态添加View

public class TreeView extends ListActivity {
	private List<TreeElement> treeSets=new ArrayList<TreeElement>();
	// 第一次加载时要显示在界面上的数据(默认未展开是的数据)
	private ArrayList<TreeElement> elementsShowedOnload = new ArrayList<TreeElement>();
	// 所有要显示的数据
	private ArrayList<TreeElement> allElements = new ArrayList<TreeElement>();
	private TreeViewAdapter treeViewAdapter = null;
	//解析xml文件的类
	private AnalyXml analyXml=new AnalyXml();
	private String treexmlStr="";
	private String mcstype="";
	
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		Bundle bundle = this.getIntent().getExtras();
		treexmlStr=bundle.getString("_responseValue");
		mcstype =  analyXml.attValue(treexmlStr, "/mcs", "type");
		if (mcstype.contains("tree")) {
			initialData(treexmlStr);
		}
		treeViewAdapter = new TreeViewAdapter(this, R.layout.outline,
				elementsShowedOnload);
		setListAdapter(treeViewAdapter);
//		 registerForContextMenu(getListView());
	}

	/**
	 * 初始化要显示的数据
	 */
	private void initialData(String treexmlStr) {
		
		treeSets=analyXml.getTreeElements(treexmlStr);
		for(TreeElement e:treeSets){
			if(!e.isMhasParent()){
				elementsShowedOnload.add(e);
			}
			allElements.add(e);
		}

	}

	/**
	 * 
	 * @author wx
	 * 
	 */
	@SuppressWarnings("rawtypes")
	private class TreeViewAdapter extends ArrayAdapter {
		// adapter构造方法
		@SuppressWarnings("unchecked")
		public TreeViewAdapter(Context context, int textViewResourceId,
				List objects) {
			super(context, textViewResourceId, objects);
			mInflater = LayoutInflater.from(context);
			elements = objects;
			mIconCollapse = BitmapFactory.decodeResource(
					context.getResources(), R.drawable.outline_list_collapse);
			mIconExpand = BitmapFactory.decodeResource(context.getResources(),
					R.drawable.outline_list_expand);
		}

		private LayoutInflater mInflater;
		//节点集合
		private List<TreeElement> elements;
		// 未展开的图片
		private Bitmap mIconCollapse;
		// 展开的图片
		private Bitmap mIconExpand;

		// 方法重写获得要显示的数据的个数
		public int getCount() {
			return elements.size();
		}

		// 方法重写获得位置
		public Object getItem(int position) {
			return position;
		}

		// 方法重写获得位置对应的id
		public long getItemId(int position) {
			return position;
		}

		// 获得View
		public View getView(int position, View convertView, ViewGroup parent) {

			ViewHolder holder;
			if (convertView == null) {

				// 设置要显示的布局,布局里面有一个ImageVIew(树形菜单图片)一个TextView(要显示的数据)
				convertView = mInflater.inflate(R.layout.outline, null);
				holder = new ViewHolder();
				holder.text = (TextView) convertView.findViewById(R.id.text);
				// 这里的icon会被替换为需要显示的展开或者收起的图片
				holder.icon = (ImageView) convertView.findViewById(R.id.icon);
				// View.setTag(Object)方法,可以给View添加一个额外的数据,在使用的时候可以使用getTag()取出来
				convertView.setTag(holder);
			} else {
				holder = (ViewHolder) convertView.getTag();
			}
			holder.icon.setVisibility(View.VISIBLE);

			// 根据位置获得节点
			TreeElement pdfOutlineElement = elements.get(position);
			int level = pdfOutlineElement.getLevel();
			// 获得在treeview中显示在第几层,根据层次设置缩进
			holder.icon.setPadding(25 * (level + 1),
					holder.icon.getPaddingTop(), 0,
					holder.icon.getPaddingBottom());
			holder.text.setText(pdfOutlineElement.getOutlineTitle());
			// 如果该位置节点有有子节点并且节点未展开
			if (pdfOutlineElement.hasChild()
					&& (pdfOutlineElement.isExpanded() == false)) {
				holder.icon.setImageBitmap(mIconCollapse);
				// 如果有子节点,节点展开了
			}
			if (pdfOutlineElement.hasChild()
					&& (pdfOutlineElement.isExpanded() == true)) {
				holder.icon.setImageBitmap(mIconExpand);
				// 如果没有子节点
			} 
			if (!pdfOutlineElement.hasChild()) {
				holder.icon.setImageBitmap(mIconCollapse);
				// 将图标隐藏
				holder.icon.setVisibility(View.INVISIBLE);
			}
			return convertView;
		}

		// 控制一行View显示的内容,图片和文字两项
		class ViewHolder {
			TextView text;
			ImageView icon;

		}
	}

	// 选中事件
	@Override
	protected void onListItemClick(ListView l, View v, int position, long id) {
		super.onListItemClick(l, v, position, id);
		// 如果没有子节点,这里就可以进行点击跳转等相应的操作
		if (!elementsShowedOnload.get(position).hasChild()) {
			Toast.makeText(this,
					elementsShowedOnload.get(position).getOutlineTitle(), 0)
					.show();
			//这里可以处理没有子节点的节点的选中事件

			return;
		}
		// 如果节点处于展开状态
		if (elementsShowedOnload.get(position).isExpanded()) {
			// 将展开张泰设置为false
			elementsShowedOnload.get(position).setExpanded(false);
			TreeElement pdfOutlineElement = elementsShowedOnload
					.get(position);
			ArrayList<TreeElement> temp = new ArrayList<TreeElement>();

			for (int i = position + 1; i < elementsShowedOnload.size(); i++) {
				if (pdfOutlineElement.getLevel() >= elementsShowedOnload.get(i)
						.getLevel()) {
					break;
				}
				temp.add(elementsShowedOnload.get(i));
			}

			elementsShowedOnload.removeAll(temp);
			// 提醒数据改变需要刷新
			treeViewAdapter.notifyDataSetChanged();
			/*
			 * fileExploreAdapter = new TreeViewAdapter(this, R.layout.outline,
			 * mPdfOutlinesCount);
			 */

			// setListAdapter(fileExploreAdapter);

		} else {
			// 如果节点处于关闭状态,设置展开为true
			elementsShowedOnload.get(position).setExpanded(true);
			int level = elementsShowedOnload.get(position).getLevel();
			int nextLevel = level + 1;

			for (TreeElement pdfOutlineElement : allElements) {
				int j = 1;
				if (pdfOutlineElement.getParent().equals(elementsShowedOnload.get(
						position).getId())) {
					pdfOutlineElement.setLevel(nextLevel);
					pdfOutlineElement.setExpanded(false);
					elementsShowedOnload.add(position + j, pdfOutlineElement);
					j++;
				}
			}
			treeViewAdapter.notifyDataSetChanged();
			/*
			 * fileExploreAdapter = new TreeViewAdapter(this, R.layout.outline,
			 * mPdfOutlinesCount);
			 */

			// setListAdapter(fileExploreAdapter);
		}
	}

}


需要注意的是如果oncreate方法中注释掉的代码没有被注释的话,如果要从别的Acitvity跳转到这个ListActivity的话会报异常,(原因没搞懂...)

3.对应ListActivity的layout文件

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:orientation="horizontal" android:layout_width="fill_parent"
	android:layout_height="wrap_content">

	<ImageView android:id="@+id/icon" android:layout_width="wrap_content"
		android:layout_height="fill_parent" android:layout_marginRight="6.0dip"
		android:layout_alignParentTop="true" android:layout_alignParentBottom="true" />
	<TextView android:textAppearance="?android:textAppearanceMedium"
		android:gravity="center_vertical" android:id="@+id/text" android:textColor="#ffffff" 
		android:layout_width="fill_parent" android:layout_height="fill_parent"
		android:singleLine="true" android:layout_toRightOf="@id/icon"
		android:layout_alignParentTop="true" android:layout_alignParentBottom="true" />
</RelativeLayout>


其中imageview为树状菜单展开和缩进的图片,textview为显示的文字,图片放在资源文件中,可自己修改

4.对应的xml文件

<?xml version="1.0" encoding="utf-8" ?>
<mcs type="tree">
    <head>
        <title>消息提示测试</title>
    </head>
	<body>
		<treeview>
			<treeelement id="1" text="编程语言" hasparent="false" haschild="true" parentid="0" level="0" expanded="false" href="xxx" />
			<treeelement id="2" text="JAVA" hasparent="true" haschild="true" parentid="1" level="1" expanded="false" href="xxx" />
			<treeelement id="3" text="C语言" hasparent="true" haschild="false" parentid="1" level="1" expanded="false" href="xxx" />
			<treeelement id="4" text="Thinking in Java" hasparent="true" haschild="true" parentid="2" level="2" expanded="false" href="xxx" />
			<treeelement id="5" text="中文版" hasparent="true" haschild="false" parentid="4" level="3" expanded="false" href="xxx" />
			<treeelement id="6" text="英文版" hasparent="true" haschild="false" parentid="4" level="3" expanded="false" href="xxx" />
			<treeelement id="7" text="开发工具" hasparent="false" haschild="false" parentid="0" level="0" expanded="false" href="xxx" />
		</treeview>
	</body>
</mcs>

代码中使用了parseText,直接解析xml文件的字符串格式,可以根据需求换用解析文件或输入流等方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值