android--自定义树形
cookqq ›博客列表 ›android

android--自定义树形

2012-11-24 20:23:05.0|分类: android|浏览量: 1690

摘要: 因为项目中需要树形展示好友,所以在网上浏览了一下,没有现成的API ,在网上下载了一个例子,发现有点不如人意,所以我修改了一下,并做记录。 TreeView.java代码: package com.tbx.android.widget; i...

因为项目中需要树形展示好友,所以在网上浏览了一下,没有现成的API ,在网上下载了一个例子,发现有点不如人意,所以我修改了一下,并做记录。

TreeView.java代码:

package com.tbx.android.widget;

import java.util.ArrayList;

/**
 * 类名:TreeView.java
 * 类描述:实现树形结构的view
 * 创建时间:2012-11-23
 */
public class TreeView extends ListView implements OnItemClickListener {
	
    private static String TAG = "TreeView";
    
    List<TreeElement> treeElements = null;// 所有节点集合
    List<TreeElement> currentElements = null;// 当前显示的节点集合
    List<TreeElement> tempElements = null;// 用于临时存储
    
    HashMap<String, List<TreeElement>> deleteMap = new HashMap<String, List<TreeElement>>();
    //用于存储要删除的子节点,以及间接子节点。
    TreeViewAdapter adapter = null;// 用于数据填充
    LastLevelItemClickListener itemClickCallBack;// 用户点击事件回调
 
    public TreeView(final Context context, AttributeSet attrs) {
       super(context, attrs);
       Log.d(TAG, "create with TreeView(Context context, AttributeSet attrs)");
       treeElements = new ArrayList<TreeElement>();
       currentElements = new ArrayList<TreeElement>();
 
       adapter = new TreeViewAdapter(context, currentElements);
       this.setAdapter(adapter);
       itemClickCallBack = new LastLevelItemClickListener() {
           @Override
           public void onLastLevelItemClick(int position,TreeViewAdapter adapter) {
              Log.d(TAG, "last level element "
                     + currentElements.get(position).getTitle()
                     + " is clicked");
           }
       };
       this.setOnItemClickListener(this);
    }
 
    public void initData(Context context, List<TreeElement> treeElements) {
       this.treeElements = treeElements;
       getFirstLevelElements(context);
       adapter.notifyDataSetChanged();
    }
 
    /**
     * 设置点击事件回调接口
     *
     * @param itemClickCallBack
     */
 
    public void setLastLevelItemClickCallBack(LastLevelItemClickListener itemClickCallBack) {
       this.itemClickCallBack = itemClickCallBack;
    }
 
    /**
     * 初始化树形结构列表数据,把第一层级的数据添加到currentElements中
     */
    public void getFirstLevelElements(Context context) {
       Log.d(TAG, "initCurrentElements");
       int size = treeElements.size();
       Log.d(TAG, "tree elements num is: " + size);
       if (currentElements == null) {
           currentElements = new ArrayList<TreeElement>();
       }
       currentElements.clear();
       for (int i = 0; i < size; i++) {
           if (treeElements.get(i).getLevel() == 1) {
              currentElements.add(treeElements.get(i));
              Log.d(TAG, "find a first level element: " + treeElements.get(i));
 
           }
       }
    }
 
    /**
     * 从所有节点集合中获取某父节点的子节点集合
     *
     * @param parentId
     * @return
     */
    private List<TreeElement> getChildElementsFromAllById(String parentId) {
       tempElements = new ArrayList<TreeElement>();
       int size = treeElements.size();
 
       for (int i = 0; i < size; i++) {
    	   String temptParentId = treeElements.get(i).getParentId() ;
    	   if(temptParentId != null){
    		   if (temptParentId.equalsIgnoreCase(parentId)) {
    	              tempElements.add(treeElements.get(i));
    	              Log.d(TAG, "find a child element: " + treeElements.get(i));
    	       }
    	   }
       }
       return tempElements;
    }
 
    /**
     * 从当前显示的节点集合中    , 获取某父节点的子节点集合
     * @param parentId
     * @return
     */
    private List<TreeElement> getChildElementsFromCurrentById(String parentId) {
       Log.d(TAG, "getChildElementsFromCurrentById    parentId: " + parentId);
       if (tempElements == null) {
           tempElements = new ArrayList<TreeElement>();
       } else {
           tempElements.clear();
       }
 
       int size = currentElements.size();
       if(size > 0){
    	   for(TreeElement treeElement : currentElements){
    		   String temp = treeElement.getParentId();
    		   if(temp != null){
                   if (temp.equalsIgnoreCase(parentId)) {
                       tempElements.add(treeElement);
                       Log.d(TAG, "find a child element to delete: " +treeElement);
                    }

        	   }
    	   }
       }
       return tempElements;
    }
 
    /**
     * 删除某父节点的所有子节点集合(包括直接节点和间接节点)
     * @param parentId
     * @return
     */
    private synchronized boolean delAllChildElementsByParentId(String parentId) {
       Log.e(TAG, "delAllChildElementsByParentId: " + parentId);
       
       List<TreeElement> childElments = getChildElementsFromCurrentById(parentId);
       List<TreeElement> treeElementsToDel = deleteMap.get(parentId);
       if (treeElementsToDel == null) {
           treeElementsToDel = new ArrayList<TreeElement>();
           deleteMap.put(parentId, treeElementsToDel);
       } else {
           treeElementsToDel.clear();
       }
       int size = childElments.size();
       Log.e(TAG, "childElments size : " + size);
       TreeElement childElement = null;
       for (int i = 0; i < size; i++) {
           childElement = childElments.get(i);
           //寻找间接节点
           if (childElement.hasChild && childElement.fold) {
              treeElementsToDel.add(childElement);
           }
       }
       size = treeElementsToDel.size();
       Log.e(TAG, "treeElementsToDel size : " + size);
 
       if(size > 0){
    	   //删除间接节点
    	   List<TreeElement> deleteTreeElement = treeElementsToDel;
    	   for(TreeElement element : deleteTreeElement){
    		   delAllChildElementsByParentId(element.getId());
    	   }
       }
       //删除直接节点
       delDirectChildElementsByParentId(parentId);
       return true;
    }
 
    /**
     * 删除某父节点的直接子节点集合
     *
     * @param parentId
     * @return
     */
    private synchronized boolean delDirectChildElementsByParentId(
           String parentId) {
       Log.d(TAG, "delDirectChildElementsByParentId(): " + parentId);
       boolean success = false;
       if (currentElements == null || currentElements.size() == 0) {
           Log.d(TAG, "delChildElementsById() failed,currentElements is null or it's size is 0");
           return success;
       }
       synchronized (currentElements) {
           int size = currentElements.size();
           Log.d(TAG, "begin delete");
           for (int i = size - 1; i >= 0; i--) {
        	  String temp = currentElements.get(i).getParentId(); 
        	  if(temp != null && temp.equalsIgnoreCase(parentId)){
        		  currentElements.get(i).fold = false;// 记得隐藏子节点时把展开状态设为false
                  currentElements.remove(i);
        	  }
           }
        }
       success = true;
       return success;
    }
 
    /**
     * 根据id查下标
     *
     * @param id
     * @return
     */
    @SuppressWarnings("unused")
	private int getElementIndexById(String id) {
       int num = currentElements.size();
       for (int i = 0; i < num; i++) {
           if (currentElements.get(i).getId().equalsIgnoreCase(id)) {
              return i;
           }
       }
       return -1;
    }
    
    @SuppressWarnings("unused")
	private TreeElement getElementById(String id){
    	 int num = currentElements.size();
    	 if( num > 0){
    		 for (int i = 0; i < num; i++) {
                 if (currentElements.get(i).getId().equalsIgnoreCase(id)) {
                    return currentElements.get(i);
                 }
             }
    	 }
         return null;
    }
 
    @Override
    public void onItemClick(AdapterView<?> arg0, View convertView,
           int position, long id) {
       TreeElement element = currentElements.get(position);
       if (element.isHasChild()) {// 当前节点有子节点时只进行数据显示或隐藏等操作
           if (!element.isFold()) {// 当前父节点为未展开状态
              currentElements.addAll(position + 1,this.getChildElementsFromAllById(element.getId()));
           } else if (element.fold) {// 当前父节点为展开状态
              boolean success = this.delAllChildElementsByParentId(element.getId());
              Log.d(TAG, "delete child state: " + success);
              if (!success) {
                  return;
              }
           }
           element.setFold(!element.isFold());// 设置反状态
           adapter.notifyDataSetChanged();// 刷新数据显示
       } else {// 当前节点有子节点时只进行用户自定义操作
           itemClickCallBack.onLastLevelItemClick(position,adapter);
       }
 
    }
 
    /**
     * 自定义内部接口,用于用户点击最终节点时的事件回调
     */
    public interface LastLevelItemClickListener {
       public void onLastLevelItemClick(int position,TreeViewAdapter adapter);
    }
}
TreeElement.java代码:
/**
 * 类名:TreeElement.java
* 类描述:树形结构节点类
 * 创建时间:2012-11-23 16:32
 */
public class TreeElement {
    String id = null;// 当前节点id
    String title = null;// 当前节点文字
    boolean hasParent = false;// 当前节点是否有父节点
    boolean hasChild = false;// 当前节点是否有子节点
    boolean childShow = false;// 如果子节点,字节当当前是否已显示
    String parentId = null;// 父节点id
    int level = -1;// 当前界面层级
    boolean fold = false;// 是否处于展开状态
...
}

TreeViewAdapter.java

package com.tbx.android.adapter;

import java.util.List;

/**
 * 类名:TreeViewAdapter.java
 * 类描述:用于填充数据的类
* 创建时间:2012-11-23 16:32
*/
public class TreeViewAdapter extends BaseAdapter {
 
    class ViewHolder {
       ImageView icon;
       TextView title;
    }
 
    Context context;
    ViewHolder holder;
    LayoutInflater inflater;
 
    List<TreeElement> elements;
 
    public TreeViewAdapter(Context context, List<TreeElement> elements) {
       this.context = context;
       this.elements = elements;
    }
 
    @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) {
       /**
        * ---------------------- get holder------------------------
        */
       if (convertView == null) {
           if (inflater == null) {
              inflater = LayoutInflater.from(context);
           }
           holder = new ViewHolder();
           convertView = inflater
                  .inflate(R.layout.tree_view_item, null);
           holder.icon = (ImageView) convertView
                  .findViewById(R.id.tree_view_item_icon);
           holder.title = (TextView) convertView
                  .findViewById(R.id.tree_view_item_title);
           convertView.setTag(holder);
       } else {
           holder = (ViewHolder) convertView.getTag();
       }
       /**
        * ---------------------- set holder--------------------------
        */
       if (elements.get(position).isHasChild()) {// 有子节点,要显示图标
           if (elements.get(position).isFold()) {
              holder.icon.setImageResource(R.drawable.tree_view_icon_open);
           } else if (!elements.get(position).isFold()) {
              holder.icon.setImageResource(R.drawable.tree_view_icon_close);
           }
           holder.icon.setVisibility(View.VISIBLE);
       } else {// 没有子节点,要隐藏图标
           holder.icon.setImageResource(R.drawable.tree_view_icon_close);
           holder.icon.setVisibility(View.INVISIBLE);
       }
       holder.icon.setPadding(25 * (elements.get(position).getLevel()), 0, 0, 0);// 根据层级设置缩进
       holder.title.setText(elements.get(position).getTitle());
       holder.title.setTextSize(35 - elements.get(position).getLevel() * 5); // 根据层级设置字体大小
 
       return convertView;
    }
}

MainActivity.java

public class MainActivity extends Activity {

	private TreeView lvAddress; //通讯录列表
	private List<TreeElement> lvAddressData = new ArrayList<TreeElement>();
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        lvAddress = (TreeView) findViewById(R.id.frame_listview_address);
    	
		LastLevelItemClickListener itemClickCallBack = new LastLevelItemClickListener() {
			// 创建节点点击事件监听
			@Override
			public void onLastLevelItemClick(int position,
					TreeViewAdapter adapter) {
				TreeElement element = (TreeElement) adapter.getItem(position);
				//然后自己处理
			}
		};
		
		//初始化数据
		initData();
		lvAddress.initData(this, lvAddressData);// 初始化数据
		lvAddress.setLastLevelItemClickCallBack(itemClickCallBack);// 设置节点点击事件监听
        
        
    }

    private void initData() {//测试数据
		 TreeElement root = new TreeElement();
		 root.setId("01");
		 root.setLevel(1);
		 root.setTitle("好友");
		 root.setFold(false);
		 root.setHasChild(true);
		 root.setHasParent(false);
		 root.setParentId(null);
		 lvAddressData.add(root);
		 
		 TreeElement twoLevel = new TreeElement();
		 twoLevel.setId("0101");
		 twoLevel.setLevel(2);
		 twoLevel.setTitle("初中同学");
		 twoLevel.setFold(false);
		 twoLevel.setHasChild(true);
		 twoLevel.setHasParent(true);
		 twoLevel.setParentId("01");
		 lvAddressData.add(twoLevel);
		 
		 
		 TreeElement threeLevel = new TreeElement();
		 threeLevel.setId("010101");
		 threeLevel.setLevel(3);
		 threeLevel.setTitle("发财");
		 threeLevel.setFold(false);
		 threeLevel.setHasChild(false);
		 threeLevel.setHasParent(true);
		 threeLevel.setParentId("0101");
		 lvAddressData.add(threeLevel);
	}

	@Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }
}
tree_view_item.xml布局内容
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:gravity="center_vertical"
    android:orientation="horizontal" >
 
    <ImageView
        android:id="@+id/tree_view_item_icon"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
 
    <TextView
        android:id="@+id/tree_view_item_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:layout_marginLeft="15dip"
         />
 
</LinearLayout>


正在需要这个 email:454564889@qq.com witwiky@qq.com 谢谢博主 你好,源码能分享下吗? 804351681@qq.com 124597202@qq.com 谢谢博主 楼上的全部发送了 378400462@qq.com 楼主好人 博主太效率了,正好研究研究!谢了 还没毕业的做毕业设计,楼主好人,邮箱 409573064@qq.com

引用来自“huangyixun007”的评论

还没毕业的做毕业设计,楼主好人,邮箱 409573064@qq.com

晚上回家给你发吧,在公司电脑上没有那个例子源码 楼主我急需,senlypan @qq.com 项目逼的。。。。感谢楼主

引用来自“Mr-Right”的评论

楼主我急需,senlypan@qq.com 项目逼的。。。。感谢楼主

发送了 526397575@qq.com感谢楼主

引用来自“将联想释放”的评论

526397575@qq.com感谢楼主

发送了 416480549@qq.com 感谢楼主!我需要一份做项目、 楼主 我很急要呢

引用来自“刘应科”的评论

楼主 我很急要呢

给你发送了

引用来自“田保兴”的评论

引用来自“刘应科”的评论

楼主 我很急要呢

给你发送了

OK THK~ 我的需求是 获取网络数据展示架构。在预加载的上面还真不好搞

引用来自“刘应科”的评论

我的需求是 获取网络数据展示架构。在预加载的上面还真不好搞

获取当前的展示页面,判断是否是相应的activity,然后展示 在点击的时候 再填充数据可否?我这边的需求是 显示集团组织架构。比如说 首页显示 3人。 集团董事局 马云 集团执行委员会 陆兆禧 然后点击响应的头衔,在获取网络数据 判断后 再根据数据做二级乃至三级的目录

引用来自“刘应科”的评论

在点击的时候 再填充数据可否?我这边的需求是 显示集团组织架构。比如说 首页显示 3人。 集团董事局 马云 集团执行委员会 陆兆禧 然后点击响应的头衔,在获取网络数据 判断后 再根据数据做二级乃至三级的目录

可以啊,只是数据来了,以后你组织完数据结构后,也要在页面中心加载数据。 O 我写个Handler吧 handler 添加
那个自定义的 Lisener监听不到啊。。。大了断点都不行 LastLevelItemClickListener 写了个监听 onItemclickListener 把你那个TreeView中的吃掉了? 不能滑动吗? 我的数据很多。 但只显示一屏 tom_lyting@hotmail.com 急需, 谢谢楼主·~~ hx_mars@163.com 求源码,感谢! 楼主源码分享一下 656210173@qq.com

一键分享文章

分类列表

  • • struts源码分析
  • • flink
  • • struts
  • • redis
  • • kafka
  • • ubuntu
  • • zookeeper
  • • hadoop
  • • activiti
  • • linux
  • • 成长
  • • NIO
  • • 关键词提取
  • • mysql
  • • android studio
  • • zabbix
  • • 云计算
  • • mahout
  • • jmeter
  • • hive
  • • ActiveMQ
  • • lucene
  • • MongoDB
  • • netty
  • • flume
  • • 我遇到的问题
  • • GRUB
  • • nginx
  • • 大家好的文章
  • • android
  • • tomcat
  • • Python
  • • luke
  • • android源码编译
  • • 安全
  • • MPAndroidChart
  • • swing
  • • POI
  • • powerdesigner
  • • jquery
  • • html
  • • java
  • • eclipse
  • • shell
  • • jvm
  • • highcharts
  • • 设计模式
  • • 列式数据库
  • • spring cloud
  • • docker+node.js+zookeeper构建微服务
版权所有 cookqq 感谢访问 支持开源 京ICP备15030920号
CopyRight 2015-2018 cookqq.com All Right Reserved.