android多级树形列表

});

} catch (IllegalArgumentException e) {

e.printStackTrace();

} catch (IllegalAccessException e) {

e.printStackTrace();

}

treeLv.setAdapter(adapter);

}

private void initDatas() {

mDatas.add(new MyNodeBean(1, 0, “中国古代”));

mDatas.add(new MyNodeBean(2, 1, “唐朝”));

mDatas.add(new MyNodeBean(3, 1, “宋朝”));

mDatas.add(new MyNodeBean(4, 1, “明朝”));

mDatas.add(new MyNodeBean(5, 2, “李世民”));

mDatas.add(new MyNodeBean(6, 2, “李白”));

mDatas.add(new MyNodeBean(7, 3, “赵匡胤”));

mDatas.add(new MyNodeBean(8, 3, “苏轼”));

mDatas.add(new MyNodeBean(9, 4, “朱元璋”));

mDatas.add(new MyNodeBean(10, 4, “唐伯虎”));

mDatas.add(new MyNodeBean(11, 4, “文征明”));

mDatas.add(new MyNodeBean(12, 7, “赵建立”));

mDatas.add(new MyNodeBean(13, 8, “苏东东”));

mDatas.add(new MyNodeBean(14, 10, “秋香”));

}

}

Adapter

这个adapter是继承了自己的定义的一个TreeListViewAdapter,核心实现都是在TreeListViewAdapter这个里面

package com.example.customtreeviewdemo;

import java.util.List;

import android.content.Context;

import android.view.View;

import android.view.ViewGroup;

import android.widget.CheckBox;

import android.widget.CompoundButton;

import android.widget.CompoundButton.OnCheckedChangeListener;

import android.widget.ImageView;

import android.widget.ListView;

import android.widget.TextView;

import com.example.customtreeviewdemo.tree.Node;

import com.example.customtreeviewdemo.tree.TreeListViewAdapter;

public class MyTreeListViewAdapter extends TreeListViewAdapter {

public MyTreeListViewAdapter(ListView mTree, Context context,

List datas, int defaultExpandLevel,boolean isHide)

throws IllegalArgumentException, IllegalAccessException {

super(mTree, context, datas, defaultExpandLevel,isHide);

}

@SuppressWarnings(“unchecked”)

@Override

public View getConvertView(Node node, int position, View convertView,

ViewGroup parent) {

ViewHolder viewHolder = null;

if (convertView == null)

{

convertView = mInflater.inflate(R.layout.list_item, parent, false);

viewHolder = new ViewHolder();

viewHolder.icon = (ImageView) convertView

.findViewById(R.id.id_treenode_icon);

viewHolder.label = (TextView) convertView

.findViewById(R.id.id_treenode_name);

viewHolder.checkBox = (CheckBox)convertView.findViewById(R.id.id_treeNode_check);

convertView.setTag(viewHolder);

} else

{

viewHolder = (ViewHolder) convertView.getTag();

}

if (node.getIcon() == -1)

{

viewHolder.icon.setVisibility(View.INVISIBLE);

} else

{

viewHolder.icon.setVisibility(View.VISIBLE);

viewHolder.icon.setImageResource(node.getIcon());

}

if(node.isHideChecked()){

viewHolder.checkBox.setVisibility(View.GONE);

}else{

viewHolder.checkBox.setVisibility(View.VISIBLE);

setCheckBoxBg(viewHolder.checkBox,node.isChecked());

}

viewHolder.label.setText(node.getName());

return convertView;

}

private final class ViewHolder

{

ImageView icon;

TextView label;

CheckBox checkBox;

}

/**

  • checkbox是否显示

  • @param cb

  • @param isChecked

*/

private void setCheckBoxBg(CheckBox cb,boolean isChecked){

if(isChecked){

cb.setBackgroundResource(R.drawable.check_box_bg_check);

}else{

cb.setBackgroundResource(R.drawable.check_box_bg);

}

}

}

自定义TreeListViewAdapter  这个是整个树形结构的一个适配器,这里面主要是实现对Node节点的操作 点击,选中改变 更新等

package com.example.customtreeviewdemo.tree;

import java.util.ArrayList;

import java.util.List;

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;

/**

  • tree适配器

  • @param

*/

public abstract class TreeListViewAdapter extends BaseAdapter {

protected Context mContext;

/**

  • 存储所有可见的Node

*/

protected List mNodes;

protected LayoutInflater mInflater;

/**

  • 存储所有的Node

*/

protected List mAllNodes;

/**

  • 点击的回调接口

*/

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 checkedNodes);

}

public void setOnTreeNodeClickListener(

OnTreeNodeClickListener onTreeNodeClickListener) {

this.onTreeNodeClickListener = onTreeNodeClickListener;

}

/**

  • @param mTree

  • @param context

  • @param datas

  • @param defaultExpandLevel

  •        默认展开几级树
    
  • @throws IllegalArgumentException

  • @throws IllegalAccessException

*/

public TreeListViewAdapter(ListView mTree, Context context, List datas,

int defaultExpandLevel, boolean isHide)

throws IllegalArgumentException, IllegalAccessException {

mContext = context;

/**

  • 对所有的Node进行排序

*/

mAllNodes = TreeHelper

.getSortedNodes(datas, defaultExpandLevel, isHide);

/**

  • 过滤出可见的Node

*/

mNodes = TreeHelper.filterVisibleNode(mAllNodes);

mInflater = LayoutInflater.from(context);

/**

  • 设置节点点击时,可以展开以及关闭;并且将ItemClick事件继续往外公布

*/

mTree.setOnItemClickListener(new OnItemClickListener() {

@Override

public void onItemClick(AdapterView<?> parent, View view,

int position, long id) {

expandOrCollapse(position);

if (onTreeNodeClickListener != null) {

onTreeNodeClickListener.onClick(mNodes.get(position),

position);

}

}

});

}

/**

  • 相应ListView的点击事件 展开或关闭某节点

  • @param position

*/

public void expandOrCollapse(int position) {

Node n = mNodes.get(position);

if (n != null)// 排除传入参数错误异常

{

if (!n.isLeaf()) {

n.setExpand(!n.isExpand());

mNodes = TreeHelper.filterVisibleNode(mAllNodes);

notifyDataSetChanged();// 刷新视图

}

}

}

@Override

public int getCount() {

return mNodes.size();

}

@Override

public Object getItem(int position) {

return mNodes.get(position);

}

@Override

public long getItemId(int position) {

return position;

}

@Override

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

final Node node = mNodes.get(position);

convertView = getConvertView(node, position, convertView, parent);

// 设置内边距

convertView.setPadding(node.getLevel() * 30, 3, 3, 3);

if (!node.isHideChecked()) {

//获取各个节点所在的父布局

RelativeLayout myView = (RelativeLayout) convertView;

//父布局下的CheckBox

CheckBox cb = (CheckBox) myView.getChildAt(1);

cb.setOnCheckedChangeListener(new OnCheckedChangeListener(){

@Override

public void onCheckedChanged(CompoundButton buttonView,

boolean isChecked) {

TreeHelper.setNodeChecked(node, isChecked);

List checkedNodes = new ArrayList();

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();

}

}

node 模型类

package com.example.customtreeviewdemo.bean;

public class MyNodeBean {

/**

  • 节点Id

*/

private int id;

/**

  • 节点父id

*/

private int pId;

/**

  • 节点name

*/

private String name;

/**

*/

private String desc;

/**

  • 节点名字长度

*/

private long length;

public MyNodeBean(int id, int pId, String name) {

super();

this.id = id;

this.pId = pId;

this.name = name;

}

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 String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getDesc() {

return desc;

}

public void setDesc(String desc) {

this.desc = desc;

}

public long getLength() {

return length;

}

public void setLength(long length) {

this.length = length;

}

}

TreeHelper这个也是核心操作类,主要功能是将业务数据和节点数据进行匹配

package com.example.customtreeviewdemo.tree;

import java.lang.reflect.Field;

import java.util.ArrayList;

import java.util.List;

import com.example.customtreeviewdemo.R;

public class TreeHelper {

/**

  • 根据所有节点获取可见节点

  • @param allNodes

  • @return

*/

public static List filterVisibleNode(List allNodes) {

List visibleNodes = new ArrayList();

for (Node node : allNodes) {

// 如果为根节点,或者上层目录为展开状态

if (node.isRoot() || node.isParentExpand()) {

setNodeIcon(node);

visibleNodes.add(node);

}

}

return visibleNodes;

}

/**

  • 获取排序的所有节点

  • @param datas

  • @param defaultExpandLevel

  • @return

  • @throws IllegalArgumentException

  • @throws IllegalAccessException

*/

public static List getSortedNodes(List datas,

int defaultExpandLevel, boolean isHide)

throws IllegalAccessException, IllegalArgumentException {

List sortedNodes = new ArrayList();

// 将用户数据转化为List

List nodes = convertData2Nodes(datas, isHide);

// 拿到根节点

List rootNodes = getRootNodes(nodes);

// 排序以及设置Node间关系

for (Node node : rootNodes) {

addNode(sortedNodes, node, defaultExpandLevel, 1);

}

return sortedNodes;

}

/**

  • 把一个节点上的所有的内容都挂上去

*/

private static void addNode(List 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);

}

}

/**

  • 获取所有的根节点

  • @param nodes

  • @return

*/
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

最后说一下我的学习路线

其实很简单就下面这张图,含概了Android所有需要学的知识点,一共8大板块:

  1. 架构师筑基必备技能
  2. Android框架体系架构(高级UI+FrameWork源码)
  3. 360°Androidapp全方位性能调优
  4. 设计思想解读开源框架
  5. NDK模块开发
  6. 移动架构师专题项目实战环节
  7. 移动架构师不可不学习微信小程序
  8. 混合开发的flutter

Android学习的资料

我呢,把上面八大板块的分支都系统的做了一份学习系统的资料和视频,大概就下面这些,我就不全部写出来了,不然太长了影响大家的阅读。

330页PDF Android学习核心笔记(内含上面8大板块)

Android学习的系统对应视频

总结

我希望通过我自己的学习方法来帮助大家去提升技术:

  • 1、多看书、看源码和做项目,平时多种总结

  • 2、不能停留在一些基本api的使用上,应该往更深层次的方向去研究,比如activity、view的内部运行机制,比如Android内存优化,比如aidl,比如JNI等,并不仅仅停留在会用,而要通过阅读源码,理解其实现原理

  • 3、同时对架构是有一定要求的,架构是抽象的,但是设计模式是具体的,所以一定要加强下设计模式的学习

  • 4、android的方向也很多,高级UI,移动架构师,数据结构与算法和音视频FFMpeg解码,如果你对其中一项比较感兴趣,就大胆的进阶吧!

希望大家多多点赞,转发,评论加关注,你们的支持就是我继续下去的动力!加油!

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

src=“https://img-blog.csdnimg.cn/img_convert/54d82705fcb991d269fac710c808e54b.jpeg” />

最后说一下我的学习路线

其实很简单就下面这张图,含概了Android所有需要学的知识点,一共8大板块:

  1. 架构师筑基必备技能
  2. Android框架体系架构(高级UI+FrameWork源码)
  3. 360°Androidapp全方位性能调优
  4. 设计思想解读开源框架
  5. NDK模块开发
  6. 移动架构师专题项目实战环节
  7. 移动架构师不可不学习微信小程序
  8. 混合开发的flutter

[外链图片转存中…(img-ANqmB102-1712552091682)]

Android学习的资料

我呢,把上面八大板块的分支都系统的做了一份学习系统的资料和视频,大概就下面这些,我就不全部写出来了,不然太长了影响大家的阅读。

330页PDF Android学习核心笔记(内含上面8大板块)

[外链图片转存中…(img-9aGLBWfy-1712552091682)]

Android学习的系统对应视频

总结

我希望通过我自己的学习方法来帮助大家去提升技术:

  • 1、多看书、看源码和做项目,平时多种总结

  • 2、不能停留在一些基本api的使用上,应该往更深层次的方向去研究,比如activity、view的内部运行机制,比如Android内存优化,比如aidl,比如JNI等,并不仅仅停留在会用,而要通过阅读源码,理解其实现原理

  • 3、同时对架构是有一定要求的,架构是抽象的,但是设计模式是具体的,所以一定要加强下设计模式的学习

  • 4、android的方向也很多,高级UI,移动架构师,数据结构与算法和音视频FFMpeg解码,如果你对其中一项比较感兴趣,就大胆的进阶吧!

希望大家多多点赞,转发,评论加关注,你们的支持就是我继续下去的动力!加油!

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 30
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android ListView 可以通过自定义适配器来实现多级树形列表。具体步骤如下: 1. 定义每个节点的数据模型,包括节点名称、节点ID、父节点ID等信息。 2. 自定义适配器,继承自 BaseAdapter,重写 getView() 方法,在该方法中根据节点的深度来确定每个节点的缩进距离,并根据节点状态显示不同的图标。 3. 在 Activity 的 onCreate() 方法中初始化树形数据,使用适配器将数据绑定到 ListView 上。 4. 在适配器中实现节点的展开和折叠功能,可以通过设置节点的可见性来实现。 5. 在 ListView 的 OnItemClickListener 中监听每个节点的点击事件,根据节点状态来判断是展开还是折叠。 示例代码如下: 1. 定义节点数据模型 ```java public class TreeNode { private int nodeId; private int parentId; private String nodeName; // 省略 getter 和 setter 方法 } ``` 2. 自定义适配器 ```java public class TreeAdapter extends BaseAdapter { private List<TreeNode> nodes; private LayoutInflater inflater; public TreeAdapter(Context context, List<TreeNode> nodes) { this.nodes = nodes; inflater = LayoutInflater.from(context); } @Override public int getCount() { return nodes.size(); } @Override public Object getItem(int position) { return nodes.get(position); } @Override public long getItemId(int position) { return nodes.get(position).getNodeId(); } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; if (convertView == null) { convertView = inflater.inflate(R.layout.tree_item, null); holder = new ViewHolder(); holder.icon = convertView.findViewById(R.id.icon); holder.name = convertView.findViewById(R.id.name); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } TreeNode node = nodes.get(position); holder.name.setText(node.getNodeName()); int level = getLevel(node); holder.icon.setPadding(30 * (level + 1), holder.icon.getPaddingTop(), holder.icon.getPaddingRight(), holder.icon.getPaddingBottom()); if (hasChildren(node)) { holder.icon.setImageResource(node.isExpanded() ? R.drawable.icon_minus : R.drawable.icon_plus); } else { holder.icon.setImageResource(R.drawable.icon_node); } return convertView; } private int getLevel(TreeNode node) { int level = 0; while (node.getParentId() != 0) { level++; node = findNodeById(node.getParentId()); } return level; } private boolean hasChildren(TreeNode node) { for (TreeNode n : nodes) { if (n.getParentId() == node.getNodeId()) { return true; } } return false; } private TreeNode findNodeById(int nodeId) { for (TreeNode node : nodes) { if (node.getNodeId() == nodeId) { return node; } } return null; } static class ViewHolder { ImageView icon; TextView name; } } ``` 3. 初始化树形数据 ```java private void initTreeData() { nodes = new ArrayList<>(); nodes.add(new TreeNode(1, 0, "Node 1")); nodes.add(new TreeNode(2, 0, "Node 2")); nodes.add(new TreeNode(3, 1, "Node 1-1")); nodes.add(new TreeNode(4, 1, "Node 1-2")); nodes.add(new TreeNode(5, 3, "Node 1-1-1")); nodes.add(new TreeNode(6, 3, "Node 1-1-2")); nodes.add(new TreeNode(7, 4, "Node 1-2-1")); nodes.add(new TreeNode(8, 2, "Node 2-1")); nodes.add(new TreeNode(9, 2, "Node 2-2")); } ``` 4. 实现节点展开和折叠功能 ```java private void toggleNode(int position) { TreeNode node = nodes.get(position); if (node.isExpanded()) { collapseNode(node); } else { expandNode(node); } notifyDataSetChanged(); } private void expandNode(TreeNode node) { node.setExpanded(true); for (TreeNode n : nodes) { if (n.getParentId() == node.getNodeId()) { n.setVisible(true); } } } private void collapseNode(TreeNode node) { node.setExpanded(false); for (TreeNode n : nodes) { if (n.getParentId() == node.getNodeId()) { n.setVisible(false); collapseNode(n); } } } ``` 5. 监听节点点击事件 ```java listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { toggleNode(position); } }); ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值