日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

android 树形目录结构的实现(包含源码)

發(fā)布時間:2025/4/5 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android 树形目录结构的实现(包含源码) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.


1.效果如圖 ,老板的需求:

1.各種群按照樹形目錄展開
2.點擊列表可以收縮展開
3.選中后進(jìn)行篩選

2.分析下思路

  • 每個數(shù)據(jù)都應(yīng)該有個根節(jié)點,也就是上級目錄。確定了上級目錄就可以找到當(dāng)前數(shù)據(jù)對應(yīng)的位置。
    2.為避免多重嵌套影響性能,這里的數(shù)據(jù)展示我們用一個列表足矣實現(xiàn)
    3.實現(xiàn)的思路是item向右偏移
  • 3.貼代碼時間

    Node節(jié)點對象的定義 項目中用到了環(huán)信SDK 環(huán)信部分直接忽略吧 QAQ

    import java.io.Serializable; import java.util.ArrayList; import java.util.List;public class Node implements Serializable{/*** 節(jié)點id*/private int id;/*** 父節(jié)點id*/private int pId;/*** 是否展開*/private boolean isExpand = false;private boolean isChecked = false;private boolean isHideChecked = true;/*** 節(jié)點名字*/private String name;/*** 節(jié)點級別*/private int level;/*** 節(jié)點展示圖標(biāo)*/private int icon;/*** 節(jié)點所含的子節(jié)點*/private List<Node> childrenNodes = new ArrayList<Node>();/*** 節(jié)點的父節(jié)點*/private Node parent;/*** 環(huán)信群ID*/private String hxGroupId;public Node() {}public Node(int id, int pId, String name,String hxGroupId) {super();this.id = id;this.pId = pId;this.name = name;this.hxGroupId = hxGroupId;}public String getHxGroupId() {return hxGroupId;}public void setHxGroupId(String hxGroupId) {this.hxGroupId = hxGroupId;}@Overridepublic String toString() {return "Node{" +"id=" + id +", pId=" + pId +", isExpand=" + isExpand +", isChecked=" + isChecked +", isHideChecked=" + isHideChecked +", name='" + name + '\'' +", level=" + level +", icon=" + icon +", childrenNodes=" + childrenNodes +", parent=" + parent +", hxGroupId='" + hxGroupId + '\'' +'}';}public int getId() {return id;}public void setId(int id) {this.id = id;}public int getpId() {return pId;}public void setpId(int pId) {this.pId = pId;}public boolean isExpand() {return isExpand;}/*** 當(dāng)父節(jié)點收起,其子節(jié)點也收起* @param isExpand*/public void setExpand(boolean isExpand) {this.isExpand = isExpand;if (!isExpand) {for (Node node : childrenNodes) {node.setExpand(isExpand);}}}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getLevel() {return parent == null ? 0 : parent.getLevel() + 1;}public void setLevel(int level) {this.level = level;}public int getIcon() {return icon;}public void setIcon(int icon) {this.icon = icon;}public List<Node> getChildrenNodes() {return childrenNodes;}public void setChildrenNodes(List<Node> childrenNodes) {this.childrenNodes = childrenNodes;}public Node getParent() {return parent;}public void setParent(Node parent) {this.parent = parent;}/*** 判斷是否是根節(jié)點* * @return*/public boolean isRoot() {return parent == null;}/*** 判斷是否是葉子節(jié)點* * @return*/public boolean isLeaf() {return childrenNodes.size() == 0;}/*** 判斷父節(jié)點是否展開* * @return*/public boolean isParentExpand(){if (parent == null)return false;return parent.isExpand();}public boolean isChecked() {return isChecked;}public void setChecked(boolean isChecked) {this.isChecked = isChecked;}public boolean isHideChecked() {return isHideChecked;}public void setHideChecked(boolean isHideChecked) {this.isHideChecked = isHideChecked;} }

    幫助類TreeHelper

    import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List;public class TreeHelper {/*** 根據(jù)所有節(jié)點獲取可見節(jié)點* * @param allNodes* @return*/public static List<Node> filterVisibleNode(List<Node> allNodes) {List<Node> visibleNodes = new ArrayList<Node>();for (Node node : allNodes) {// 如果為根節(jié)點,或者上層目錄為展開狀態(tài)if (node.isRoot() || node.isParentExpand()) {setNodeIcon(node);visibleNodes.add(node);}}return visibleNodes;}/*** 獲取排序的所有節(jié)點* * @param datas* @param defaultExpandLevel* @return* @throws IllegalArgumentException* @throws IllegalAccessException*/public static <T> List<Node> getSortedNodes(List<T> datas,int defaultExpandLevel, boolean isHide)throws IllegalAccessException, IllegalArgumentException {List<Node> sortedNodes = new ArrayList<Node>();// 將用戶數(shù)據(jù)轉(zhuǎn)化為List<Node>List<Node> nodes = convertData2Nodes(datas, isHide);// 拿到根節(jié)點List<Node> rootNodes = getRootNodes(nodes);// 排序以及設(shè)置Node間關(guān)系for (Node node : rootNodes) {addNode(sortedNodes, node, defaultExpandLevel, 1);}return sortedNodes;}/*** 把一個節(jié)點上的所有的內(nèi)容都掛上去*/private static void addNode(List<Node> nodes, Node node,int defaultExpandLeval, int currentLevel) {nodes.add(node);if (defaultExpandLeval >= currentLevel) {node.setExpand(true);}if (node.isLeaf())return;for (int i = 0; i < node.getChildrenNodes().size(); i++) {addNode(nodes, node.getChildrenNodes().get(i), defaultExpandLeval,currentLevel + 1);}}/*** 獲取所有的根節(jié)點* * @param nodes* @return*/public static List<Node> getRootNodes(List<Node> nodes) {List<Node> rootNodes = new ArrayList<Node>();for (Node node : nodes) {if (node.isRoot()) {rootNodes.add(node);}}return rootNodes;}/*** 將泛型datas轉(zhuǎn)換為node* * @param datas* @return* @throws IllegalArgumentException* @throws IllegalAccessException*/public static <T> List<Node> convertData2Nodes(List<T> datas, boolean isHide)throws IllegalAccessException, IllegalArgumentException {List<Node> nodes = new ArrayList<Node>();Node node = null;for (T t : datas) {int id = -1;int pId = -1;String name = null;String hxGroupId = null;Class<? extends Object> clazz = t.getClass();Field[] declaredFields = clazz.getDeclaredFields();/*** 與MyNodeBean實體一一對應(yīng)*/for (Field f : declaredFields) {if ("id".equals(f.getName())) {f.setAccessible(true);id = f.getInt(t);}if ("pId".equals(f.getName())) {f.setAccessible(true);pId = f.getInt(t);}if ("name".equals(f.getName())) {f.setAccessible(true);name = (String) f.get(t);}if ("hxGroupId".equals(f.getName())) {f.setAccessible(true);hxGroupId = (String) f.get(t);}if ("desc".equals(f.getName())) {continue;}if ("length".equals(f.getName())) {continue;}if (id == -1 && pId == -1 && name == null&&hxGroupId==null) {break;}}node = new Node(id, pId, name,hxGroupId);node.setHideChecked(isHide);nodes.add(node);}/*** 比較nodes中的所有節(jié)點,分別添加children和parent*/for (int i = 0; i < nodes.size(); i++) {Node n = nodes.get(i);for (int j = i + 1; j < nodes.size(); j++) {Node m = nodes.get(j);if (n.getId() == m.getpId()) {n.getChildrenNodes().add(m);m.setParent(n);} else if (n.getpId() == m.getId()) {n.setParent(m);m.getChildrenNodes().add(n);}}}for (Node n : nodes) {setNodeIcon(n);}return nodes;}/*** 設(shè)置打開,關(guān)閉icon* * @param node*/public static void setNodeIcon(Node node) {if (node.getChildrenNodes().size() > 0 && node.isExpand()) {node.setIcon(R.drawable.arrow_right);} else if (node.getChildrenNodes().size() > 0 && !node.isExpand()) {node.setIcon(R.drawable.arrow_down);} elsenode.setIcon(-1);}public static void setNodeChecked(Node node, boolean isChecked) {// 自己設(shè)置是否選擇node.setChecked(isChecked);/*** 非葉子節(jié)點,子節(jié)點處理*/setChildrenNodeChecked(node, isChecked);/** 父節(jié)點處理 */setParentNodeChecked(node);}/*** 非葉子節(jié)點,子節(jié)點處理*/private static void setChildrenNodeChecked(Node node, boolean isChecked) {node.setChecked(isChecked);if (!node.isLeaf()) {for (Node n : node.getChildrenNodes()) {// 所有子節(jié)點設(shè)置是否選擇setChildrenNodeChecked(n, isChecked);}}}/*** 設(shè)置父節(jié)點選擇* * @param node*/private static void setParentNodeChecked(Node node) {/** 非根節(jié)點 */if (!node.isRoot()) {Node rootNode = node.getParent();boolean isAllChecked = true;for (Node n : rootNode.getChildrenNodes()) {if (!n.isChecked()) {isAllChecked = false;break;}}if (isAllChecked) {rootNode.setChecked(true);} else {rootNode.setChecked(false);}setParentNodeChecked(rootNode);}}}

    適配器TreeListViewAdapter

    import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.BaseAdapter; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.CompoundButton.OnCheckedChangeListener; import android.widget.ListView; import android.widget.RelativeLayout;import java.util.ArrayList; import java.util.List;/*** tree適配器* @param <T>*/ public abstract class TreeListViewAdapter<T> extends BaseAdapter {protected Context mContext;/*** 存儲所有可見的Node*/protected List<Node> mNodes;protected LayoutInflater mInflater;/*** 存儲所有的Node*/protected List<Node> mAllNodes;/*** 點擊的回調(diào)接口*/private OnTreeNodeClickListener onTreeNodeClickListener;public interface OnTreeNodeClickListener {/*** 處理node click事件* @param node* @param position*/void onClick(Node node, int position);/*** 處理checkbox選擇改變事件* @param node* @param position* @param checkedNodes*/void onCheckChange(Node node, int position, List<Node> checkedNodes);}public void setOnTreeNodeClickListener(OnTreeNodeClickListener onTreeNodeClickListener) {this.onTreeNodeClickListener = onTreeNodeClickListener;}/*** * @param mTree* @param context* @param datas* @param defaultExpandLevel* 默認(rèn)展開幾級樹* @throws IllegalArgumentException* @throws IllegalAccessException*/public TreeListViewAdapter(ListView mTree, Context context, List<T> datas,int defaultExpandLevel, boolean isHide)throws IllegalArgumentException, IllegalAccessException {mContext = context;/*** 對所有的Node進(jìn)行排序*/mAllNodes = TreeHelper.getSortedNodes(datas, defaultExpandLevel, isHide);/*** 過濾出可見的Node*/mNodes = TreeHelper.filterVisibleNode(mAllNodes);mInflater = LayoutInflater.from(context);/*** 設(shè)置節(jié)點點擊時,可以展開以及關(guān)閉;并且將ItemClick事件繼續(xù)往外公布*/mTree.setOnItemClickListener(new OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> parent, View view,int position, long id) {expandOrCollapse(position);if (onTreeNodeClickListener != null) {onTreeNodeClickListener.onClick(mNodes.get(position),position);}}});}/*** 相應(yīng)ListView的點擊事件 展開或關(guān)閉某節(jié)點* * @param position*/public void expandOrCollapse(int position) {Node n = mNodes.get(position);if (n != null)// 排除傳入?yún)?shù)錯誤異常{if (!n.isLeaf()) {n.setExpand(!n.isExpand());mNodes = TreeHelper.filterVisibleNode(mAllNodes);notifyDataSetChanged();// 刷新視圖}}}@Overridepublic int getCount() {return mNodes.size();}@Overridepublic Object getItem(int position) {return mNodes.get(position);}@Overridepublic long getItemId(int position) {return position;}@Overridepublic View getView(final int position, View convertView, ViewGroup parent) {final Node node = mNodes.get(position);convertView = getConvertView(node, position, convertView, parent);// 設(shè)置內(nèi)邊距convertView.setPadding(node.getLevel() * 56, 3, 3, 3);if (!node.isHideChecked()) {//獲取各個節(jié)點所在的父布局RelativeLayout myView = (RelativeLayout) convertView;//父布局下的CheckBoxCheckBox cb = (CheckBox) myView.getChildAt(0);//擴充可觸摸的區(qū)域//expandViewTouchDelegate(cb,50,50,50,50);cb.setOnCheckedChangeListener(new OnCheckedChangeListener(){@Overridepublic void onCheckedChanged(CompoundButton buttonView,boolean isChecked) {TreeHelper.setNodeChecked(node, isChecked);List<Node> checkedNodes = new ArrayList<Node>();for(Node n:mAllNodes){if(n.isChecked()){checkedNodes.add(n);}}onTreeNodeClickListener.onCheckChange(node,position,checkedNodes);TreeListViewAdapter.this.notifyDataSetChanged();}});}return convertView;}public abstract View getConvertView(Node node, int position,View convertView, ViewGroup parent);/*** 更新* @param isHide*/public void updateView(boolean isHide){for(Node node:mAllNodes){node.setHideChecked(isHide);}this.notifyDataSetChanged();}

    activity中的主要代碼

    private void initView() {initTreeData();try {adapter = new MyTreeListViewAdapter<>(treeLv, this,mDatas, 0, isHide);adapter.setOnTreeNodeClickListener(new TreeListViewAdapter.OnTreeNodeClickListener() {@Overridepublic void onClick(Node node, int position) {if (node.isLeaf()) {}}@Overridepublic void onCheckChange(Node node, int position,List<Node> checkedNodes) {// TODO Auto-generated method stubcheckedNode = checkedNodes;StringBuffer sb = new StringBuffer();for (Node n : checkedNodes) {sb.append(n.getName()).append(":").append(n.getHxGroupId());}Logger.d("選中的" + sb.toString());}});adapter.updateView(isHide);} catch (IllegalArgumentException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalAccessException e) {// TODO Auto-generated catch blocke.printStackTrace();}treeLv.setAdapter(adapter);}private void initTreeData() {for (ChatGroupEntity.RDataBean bean : countTask.getRData()) {mDatas.add(new MyNodeBean(Integer.valueOf(bean.getGroup_id()), Integer.valueOf(bean.getUp_group_id()), bean.getGroup_code(), bean.getHx_id()));}}

    布局代碼

    <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:layout_width="match_parent"android:focusable="true"android:focusableInTouchMode="true"android:layout_height="match_parent"><include layout="@layout/title_bar_common"/><com.fjrcloud.fuqing.util.customview.ClearEditText android:id="@+id/filter_edit"android:layout_width="match_parent"android:layout_height="30dp"android:focusableInTouchMode="true"android:layout_marginTop="8dip"android:layout_marginLeft="15dp"android:layout_marginRight="15dp"android:gravity="center_vertical"android:layout_marginBottom="8dp"android:paddingLeft="15dp"android:drawablePadding="15dp"android:background="@drawable/shape_search_view"android:drawableLeft="@mipmap/icon_check_name"android:hint="搜索"android:singleLine="true"android:textSize="14sp"/><TextView android:background="#f1f1f1"android:layout_width="match_parent"android:layout_height="@dimen/dp_15"/><ListView android:layout_marginTop="15dp"android:id="@+id/tree_lv"android:layout_width="match_parent"android:layout_height="match_parent"></ListView></LinearLayout>

    OK收工。有什么不懂得可以留言 聯(lián)系我QQ :910689331
    或者微博:Liberation_k

    當(dāng)然 源碼在這哈
    鏈接:http://pan.baidu.com/s/1c0KpS6 密碼:q4xf

    總結(jié)

    以上是生活随笔為你收集整理的android 树形目录结构的实现(包含源码)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 大陆明星乱淫(高h)小说 | 日本中文字幕有码 | 性欧美videossex精品 | 奇米影视久久 | 高跟av| 日本三级大片 | 亚洲精品在线免费播放 | 欧美一区二区三区久久精品 | 亚洲色图影院 | 日日干夜 | 91插插插插插插插 | 久久综合99 | 成人自拍视频在线 | 阿娇全套94张未删图久久 | 日韩一及片 | 日韩电影在线观看一区二区 | 欧美亚洲二区 | 日韩综合在线观看 | 国产美女视频一区二区 | 亚洲第一淫片 | 久久久久久美女 | 亚洲欧美乱综合图片区小说区 | 欧美一区永久视频免费观看 | 日本黄色片段 | 成人激情站 | 亚洲自拍中文 | 日本美女性高潮 | 色香蕉在线视频 | 中文字幕激情小说 | 香蕉视频成人在线观看 | 涩色网站| 日韩精品中文字幕在线观看 | 男生女生操操操 | 久久精品一区二区 | 自拍日韩亚洲一区在线 | 欧美性福利 | 伊人久久亚洲综合 | 中国女人真人一级毛片 | 国产在线无 | 成人无高清96免费 | 久操久操久操 | 521av在线 | 国产网站免费在线观看 | 欧美jizzhd精品欧美18 | 伦理片一区二区三区 | 岛国av在线免费 | 无套内谢少妇毛片 | bt天堂新版中文在线地址 | 91无限观看| 亚洲中文无码av在线 | 久久亚洲中文字幕无码 | 国产日韩网站 | 脱女学生小内内摸了高潮 | 在线免费看mv的网站入口 | 最新中文字幕在线观看 | 成人免费看片网站 | 黄页网站免费观看 | 性久久久久久久久 | 97国产在线视频 | 最新啪啪网站 | 人人干97| 黄黄的网站 | 免费精品视频在线 | 日韩av在线影院 | 国产xx在线观看 | 40一50一60老女人毛片 | 久久久久久久久久网 | 美女视频黄色在线观看 | 激情网站在线观看 | 欧美成人视屏 | 无限国产资源 | 国产原创在线播放 | 成人片黄网站久久久免费 | 九九黄色大片 | 亚洲25p| 国产毛片一区二区三区va在线 | 日韩av一二区 | 97射射| 婷婷伊人网 | 18成人免费观看视频 | 一级黄色性片 | 四川操bbb | 三级色视频 | 欧美福利影院 | 亚洲清纯国产 | 日韩一区二区欧美 | www.日日干 | 久久久久久久久久久久久久免费看 | 国产精品一区一区三区 | 日韩中文字幕在线视频 | 7788色淫网站小说 | 欧美性猛交xxxx黑人猛交 | 欧美福利社 | 久久中文字幕精品 | 妞干网这里只有精品 | 亚洲九九 | 视频一区二区在线播放 | 精品国产乱码久久久久久预案 | 国产欧美一区二区三区鸳鸯浴 |