android二级菜单ui,Android UI 之实现多级树形列表TreeView示例

所谓TreeView就是在Windows中常见的多级列表树,在Android中系统只默认提供了ListView和ExpandableListView两种列表,最多只支持到二级列表的实现,所以如果想要实现三级和更多层次的列表,就需要我们自己来做一些处理了。

其实这个效果很久以前就有人想办法实现了,但是实现的效果有一些问题,我的实现思路主要也是来自于网络,但是在其基础上修正了逻辑上的一些错误,做了一些优化。

先来看一下效果:

6179820e40c1f01d0bf1ffc684734fdc.png

然后大体说一下思路:

其实这里实现的多级列表只是一个视觉效果,我们看到的分级效果是由于每行的缩进不同造成的。比如在上面的效果中,山东省和广东省是级别最高的层次,山东省下的青岛市作为山东省的子项,我们增加他的左缩进,这样看起来就有了层次感了。其他的层次也是同理。

也就是说,我们只用了一个ListView,工作的重点就在于不断变化ListView显示的数据,根据用户的操作,将数据修改为用户想要看到的数据内容,并根据每个数据项的不同,在显示效果上做不同的缩进处理,最终呈现出一个TreeView的效果。

具体的实现思路参考下面的项目结构和具体代码:

e9e6912847bfc5649593728b25bb0fa6.png

Element.Java:

package com.example.androidtreeviewdemo.treeview;

/**

* Element类

* @author carrey

*

*/

public class Element {

/** 文字内容 */

private String contentText;

/** 在tree中的层级 */

private int level;

/** 元素的id */

private int id;

/** 父元素的id */

private int parendId;

/** 是否有子元素 */

private boolean hasChildren;

/** item是否展开 */

private boolean isExpanded;

/** 表示该节点没有父元素,也就是level为0的节点 */

public static final int NO_PARENT = -1;

/** 表示该元素位于最顶层的层级 */

public static final int TOP_LEVEL = 0;

public Element(String contentText, int level, int id, int parendId,

boolean hasChildren, boolean isExpanded) {

super();

this.contentText = contentText;

this.level = level;

this.id = id;

this.parendId = parendId;

this.hasChildren = hasChildren;

this.isExpanded = isExpanded;

}

public boolean isExpanded() {

return isExpanded;

}

public void setExpanded(boolean isExpanded) {

this.isExpanded = isExpanded;

}

public String getContentText() {

return contentText;

}

public void setContentText(String contentText) {

this.contentText = contentText;

}

public int getLevel() {

return level;

}

public void setLevel(int level) {

this.level = level;

}

public int getId() {

return id;

}

public void setId(int id) {

this.id = id;

}

public int getParendId() {

return parendId;

}

public void setParendId(int parendId) {

this.parendId = parendId;

}

public boolean isHasChildren() {

return hasChildren;

}

public void setHasChildren(boolean hasChildren) {

this.hasChildren = hasChildren;

}

}

TreeViewAdapter.java:

package com.example.androidtreeviewdemo.treeview;

import java.util.ArrayList;

import com.example.androidtreeviewdemo.R;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;

import android.widget.BaseAdapter;

import android.widget.ImageView;

import android.widget.TextView;

/**

* TreeViewAdapter

* @author carrey

*

*/

public class TreeViewAdapter extends BaseAdapter {

/** 元素数据源 */

private ArrayList elementsData;

/** 树中元素 */

private ArrayList elements;

/** LayoutInflater */

private LayoutInflater inflater;

/** item的行首缩进基数 */

private int indentionBase;

public TreeViewAdapter(ArrayList elements, ArrayList elementsData, LayoutInflater inflater) {

this.elements = elements;

this.elementsData = elementsData;

this.inflater = inflater;

indentionBase = 50;

}

public ArrayList getElements() {

return elements;

}

public ArrayList getElementsData() {

return elementsData;

}

@Override

public int getCount() {

return elements.size();

}

@Override

public Object getItem(int position) {

return elements.get(position);

}

@Override

public long getItemId(int position) {

return position;

}

@Override

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

ViewHolder holder = null;

if (convertView == null) {

holder = new ViewHolder();

convertView = inflater.inflate(R.layout.treeview_item, null);

holder.disclosureImg = (ImageView) convertView.findViewById(R.id.disclosureImg);

holder.contentText = (TextView) convertView.findViewById(R.id.contentText);

convertView.setTag(holder);

} else {

holder = (ViewHolder) convertView.getTag();

}

Element element = elements.get(position);

int level = element.getLevel();

holder.disclosureImg.setPadding(

indentionBase * (level + 1),

holder.disclosureImg.getPaddingTop(),

holder.disclosureImg.getPaddingRight(),

holder.disclosureImg.getPaddingBottom());

holder.contentText.setText(element.getContentText());

if (element.isHasChildren() && !element.isExpanded()) {

holder.disclosureImg.setImageResource(R.drawable.close);

//这里要主动设置一下icon可见,因为convertView有可能是重用了"设置了不可见"的view,下同。

holder.disclosureImg.setVisibility(View.VISIBLE);

} else if (element.isHasChildren() && element.isExpanded()) {

holder.disclosureImg.setImageResource(R.drawable.open);

holder.disclosureImg.setVisibility(View.VISIBLE);

} else if (!element.isHasChildren()) {

holder.disclosureImg.setImageResource(R.drawable.close);

holder.disclosureImg.setVisibility(View.INVISIBLE);

}

return convertView;

}

/**

* 优化Holder

* @author carrey

*

*/

static class ViewHolder{

ImageView disclosureImg;

TextView contentText;

}

}

TreeViewItemClickListener.java:

package com.example.androidtreeviewdemo.treeview;

import java.util.ArrayList;

import android.view.View;

import android.widget.AdapterView;

import android.widget.AdapterView.OnItemClickListener;

/**

* TreeView item点击事件

* @author carrey

*

*/

public class TreeViewItemClickListener implements OnItemClickListener {

/** adapter */

private TreeViewAdapter treeViewAdapter;

public TreeViewItemClickListener(TreeViewAdapter treeViewAdapter) {

this.treeViewAdapter = treeViewAdapter;

}

@Override

public void onItemClick(AdapterView> parent, View view, int position,

long id) {

//点击的item代表的元素

Element element = (Element) treeViewAdapter.getItem(position);

//树中的元素

ArrayList elements = treeViewAdapter.getElements();

//元素的数据源

ArrayList elementsData = treeViewAdapter.getElementsData();

//点击没有子项的item直接返回

if (!element.isHasChildren()) {

return;

}

if (element.isExpanded()) {

element.setExpanded(false);

//删除节点内部对应子节点数据,包括子节点的子节点...

ArrayList elementsToDel = new ArrayList();

for (int i = position + 1; i < elements.size(); i++) {

if (element.getLevel() >= elements.get(i).getLevel())

break;

elementsToDel.add(elements.get(i));

}

elements.removeAll(elementsToDel);

treeViewAdapter.notifyDataSetChanged();

} else {

element.setExpanded(true);

//从数据源中提取子节点数据添加进树,注意这里只是添加了下一级子节点,为了简化逻辑

int i = 1;//注意这里的计数器放在for外面才能保证计数有效

for (Element e : elementsData) {

if (e.getParendId() == element.getId()) {

e.setExpanded(false);

elements.add(position + i, e);

i ++;

}

}

treeViewAdapter.notifyDataSetChanged();

}

}

}

MainActivity.java:

package com.example.androidtreeviewdemo;

import java.util.ArrayList;

import com.example.androidtreeviewdemo.treeview.Element;

import com.example.androidtreeviewdemo.treeview.TreeViewAdapter;

import com.example.androidtreeviewdemo.treeview.TreeViewItemClickListener;

import android.os.Bundle;

import android.app.Activity;

import android.content.Context;

import android.view.LayoutInflater;

import android.view.Menu;

import android.widget.ListView;

public class MainActivity extends Activity {

/** 树中的元素集合 */

private ArrayList elements;

/** 数据源元素集合 */

private ArrayList elementsData;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);

init();

ListView treeview = (ListView) findViewById(R.id.treeview);

TreeViewAdapter treeViewAdapter = new TreeViewAdapter(

elements, elementsData, inflater);

TreeViewItemClickListener treeViewItemClickListener = new TreeViewItemClickListener(treeViewAdapter);

treeview.setAdapter(treeViewAdapter);

treeview.setOnItemClickListener(treeViewItemClickListener);

}

private void init() {

elements = new ArrayList();

elementsData = new ArrayList();

//添加节点 -- 节点名称,节点level,节点id,父节点id,是否有子节点,是否展开

//添加最外层节点

Element e1 = new Element("山东省", Element.TOP_LEVEL, 0, Element.NO_PARENT, true, false);

//添加第一层节点

Element e2 = new Element("青岛市", Element.TOP_LEVEL + 1, 1, e1.getId(), true, false);

//添加第二层节点

Element e3 = new Element("市南区", Element.TOP_LEVEL + 2, 2, e2.getId(), true, false);

//添加第三层节点

Element e4 = new Element("香港中路", Element.TOP_LEVEL + 3, 3, e3.getId(), false, false);

//添加第一层节点

Element e5 = new Element("烟台市", Element.TOP_LEVEL + 1, 4, e1.getId(), true, false);

//添加第二层节点

Element e6 = new Element("芝罘区", Element.TOP_LEVEL + 2, 5, e5.getId(), true, false);

//添加第三层节点

Element e7 = new Element("凤凰台街道", Element.TOP_LEVEL + 3, 6, e6.getId(), false, false);

//添加第一层节点

Element e8 = new Element("威海市", Element.TOP_LEVEL + 1, 7, e1.getId(), false, false);

//添加最外层节点

Element e9 = new Element("广东省", Element.TOP_LEVEL, 8, Element.NO_PARENT, true, false);

//添加第一层节点

Element e10 = new Element("深圳市", Element.TOP_LEVEL + 1, 9, e9.getId(), true, false);

//添加第二层节点

Element e11 = new Element("南山区", Element.TOP_LEVEL + 2, 10, e10.getId(), true, false);

//添加第三层节点

Element e12 = new Element("深南大道", Element.TOP_LEVEL + 3, 11, e11.getId(), true, false);

//添加第四层节点

Element e13 = new Element("10000号", Element.TOP_LEVEL + 4, 12, e12.getId(), false, false);

//添加初始树元素

elements.add(e1);

elements.add(e9);

//创建数据源

elementsData.add(e1);

elementsData.add(e2);

elementsData.add(e3);

elementsData.add(e4);

elementsData.add(e5);

elementsData.add(e6);

elementsData.add(e7);

elementsData.add(e8);

elementsData.add(e9);

elementsData.add(e10);

elementsData.add(e11);

elementsData.add(e12);

elementsData.add(e13);

}

@Override

public boolean onCreateOptionsMenu(Menu menu) {

// Inflate the menu; this adds items to the action bar if it is present.

getMenuInflater().inflate(R.menu.activity_main, menu);

return true;

}

}

treeview_item.xml:

android:layout_width="match_parent"

android:layout_height="match_parent" >

android:id="@+id/disclosureImg"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_centerVertical="true"

android:layout_alignParentLeft="true"/>

android:id="@+id/contentText"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_centerVertical="true"

android:layout_toRightOf="@id/disclosureImg"/>

activity_main.xml:

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

tools:context=".MainActivity" >

android:id="@+id/treeview"

android:layout_width="match_parent"

android:layout_height="match_parent"/>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值