Android打造一个高性能无限层级显示的树形控件(Android树形控件)

news2024/11/26 19:45:27

Android使用ListView实现一个高性能无限层级显示的树形控件:

最近公司的Android项目里有一个地方需要选择某公司的所有部门,因为手机屏幕有限所以并不能像网页那样显示树状结构,但是如果只是用列表依次显示所有的部门又会让用户很难找到想要找的部门(即使加上搜索功能也很难表现出层级关系),由于系统控件ExpandableListView 只能显示两级,加上数据集的组织比较麻烦,所以就使用ListView来实现如下的树形展示效果。至于为什么使用listview最大的好处就是它自带控件复用功能,我们不用去处理这个复杂的问题。最终效果如下:

Center

分析:

因为要展示的是一个树形结构,所以每一条记录必须拥有一个指向父亲节点的字段。为了体现出层级结构,其实就是增加缩进就可以了。当然说起来很简单,但是做起来的时候会有很多地方值得注意,比如说如何处理展开和收缩,以及跨级展开,收缩,如何得到当前是第几层从而处理缩进等等,再比如说如果数据量比较大的话性能怎么样等等一系列问题。

接下来我们就以层级显示一个公司的所有部门为需求来实现一下,其实只要具有树形结构我们都可以这样做。

实现思路以及使用方法:

首先我们要定义一个抽象类,其中包含必需的字段和方法:

 
  1. /**
  2. * Created by HQOCSHheqing on 2016/8/2.
  3. *
  4. * @description 节点抽象类(泛型T主要是考虑到ID和parentID有可能是int型也有可能是String型
  5. * 即这里可以传入Integer或者String,具体什么类型由子类指定
  6. ,因为这两种类型比较是否相等的方式不同:一个是用 “==”,一个是用 equals() 函数)
  7. */
  8. public abstract class Node<T> {
  9. private int _level = -1;//当前节点的层级,初始值-1 后面会讲到
  10. private List<Node> _childrenList = new ArrayList<>();//所有的孩子节点
  11. private Node _parent;//父亲节点
  12. private int _icon;//图标资源ID
  13. private boolean isExpand = false;//当前状态是否展开
  14. public abstract T get_id();//得到当前节点ID
  15. public abstract T get_parentId();//得到当前节点的父ID
  16. public abstract String get_label();//要显示的内容
  17. public abstract boolean parent(Node dest);//判断当前节点是否是dest的父亲节点
  18. public abstract boolean child(Node dest);//判断当前节点是否是dest的孩子节点
  19. public int get_level() {
  20. if (_level == -1){//如果是 -1 的话就递归获取
  21. //因为是树形结构,所以此处想要得到当前节点的层级
  22. //,必须递归调用,但是递归效率低下,如果每次都递归获取会严重影响性能,所以我们把第一次
  23. //得到的结果保存起来避免每次递归获取
  24. int level = _parent == null ? 1 : _parent.get_level()+1;
  25. _level = level;
  26. return _level;
  27. }
  28. return _level;
  29. }
  30. public void set_level(int _level) {
  31. this._level = _level;
  32. }
  33. public List<Node> get_childrenList() {
  34. return _childrenList;
  35. }
  36. public void set_childrenList(List<Node> _childrenList) {
  37. this._childrenList = _childrenList;
  38. }
  39. public Node get_parent() {
  40. return _parent;
  41. }
  42. public void set_parent(Node _parent) {
  43. this._parent = _parent;
  44. }
  45. public int get_icon() {
  46. return _icon;
  47. }
  48. public void set_icon(int _icon) {
  49. this._icon = _icon;
  50. }
  51. public boolean isExpand() {
  52. return isExpand;
  53. }
  54. public void setIsExpand(boolean isExpand) {
  55. this.isExpand = isExpand;
  56. if (isExpand){
  57. _icon = R.mipmap.collapse;
  58. }else{
  59. _icon = R.mipmap.expand;
  60. }
  61. }
  62. public boolean isRoot(){
  63. return _parent == null;
  64. }
  65. public boolean isLeaf(){
  66. return _childrenList.size() <= 0;
  67. }
  68. }

将我们要树状显示的实体继承此抽象类,我们一部门ID以及parentid为integer型为例:

 
  1. /**
  2. * Created by HQOCSHheqing on 2016/8/2.
  3. *
  4. * @description 部门类(继承Node),此处的泛型Integer是因为ID和parentID都为int
  5. * ,如果为String传入泛型String即可,如果传入String,记得修改<span style="font-family: Arial, Helvetica, sans-serif;">parent和child方法,因为比较相等的方式不同。</span>
  6. */
  7. public class Dept extends Node<Integer>{
  8. private int id;//部门ID
  9. private int parentId;//父亲节点ID
  10. private String name;//部门名称
  11. public Dept() {
  12. }
  13. public Dept(int id, int parentId, String name) {
  14. this.id = id;
  15. this.parentId = parentId;
  16. this.name = name;
  17. }
  18. /**
  19. * 此处返回节点ID
  20. * @return
  21. */
  22. @Override
  23. public Integer get_id() {
  24. return id;
  25. }
  26. /**
  27. * 此处返回父亲节点ID
  28. * @return
  29. */
  30. @Override
  31. public Integer get_parentId() {
  32. return parentId;
  33. }
  34. @Override
  35. public String get_label() {
  36. return name;
  37. }
  38. @Override
  39. public boolean parent(Node dest) {
  40. if (id == ((Integer)dest.get_parentId()).intValue()){
  41. return true;
  42. }
  43. return false;
  44. }
  45. @Override
  46. public boolean child(Node dest) {
  47. if (parentId == ((Integer)dest.get_id()).intValue()){
  48. return true;
  49. }
  50. return false;
  51. }
  52. public int getId() {
  53. return id;
  54. }
  55. public void setId(int id) {
  56. this.id = id;
  57. }
  58. public int getParentId() {
  59. return parentId;
  60. }
  61. public void setParentId(int parentId) {
  62. this.parentId = parentId;
  63. }
  64. public String getName() {
  65. return name;
  66. }
  67. public void setName(String name) {
  68. this.name = name;
  69. }
  70. }

写一个帮助类:主要是整理节点与节点之间的关系,构造森林(有可能构造出多个树)。

 
  1. /**
  2. * Created by HQOCSHheqing on 2016/8/2.
  3. *
  4. * @description 节点帮助类
  5. */
  6. public class NodeHelper {
  7. /**
  8. * 传入所有的要展示的节点数据
  9. * @param nodeList 返回值是所有的根节点
  10. * @return
  11. */
  12. public static List<Node> sortNodes(List<Node> nodeList){
  13. List<Node> rootNodes = new ArrayList<>();
  14. int size = nodeList.size();
  15. Node m;
  16. Node n;
  17. //两个for循环整理出所有数据之间的斧子关系,最后会构造出一个森林(就是可能有多棵树)
  18. for (int i = 0;i < size;i++){
  19. m = nodeList.get(i);
  20. for (int j = i+1;j < size;j++){
  21. n = nodeList.get(j);
  22. if (m.parent(n)){
  23. m.get_childrenList().add(n);
  24. n.set_parent(m);
  25. }else if (m.child(n)){
  26. n.get_childrenList().add(m);
  27. m.set_parent(n);
  28. }
  29. }
  30. }
  31. //找出所有的树根,同事设置相应的图标(后面你会发现其实这里的主要
  32. // 作用是设置叶节点和非叶节点的图标)
  33. for (int i = 0;i < size;i++){
  34. m = nodeList.get(i);
  35. if (m.isRoot()){
  36. rootNodes.add(m);
  37. }
  38. setNodeIcon(m);
  39. }
  40. nodeList.clear();//此时所有的关系已经整理完成了
  41. // ,森林构造完成,可以清空之前的数据,释放内存,提高性能
  42. // ,如果之前的数据还有用的话就不清空
  43. nodeList = rootNodes;//返回所有的根节点
  44. rootNodes = null;
  45. return nodeList;
  46. }
  47. /**
  48. * 设置图标
  49. * @param node
  50. */
  51. private static void setNodeIcon(Node node){
  52. if (!node.isLeaf()){
  53. if (node.isExpand()){
  54. node.set_icon(R.mipmap.collapse);
  55. }else{
  56. node.set_icon(R.mipmap.expand);
  57. }
  58. }else{
  59. node.set_icon(-1);
  60. }
  61. }
  62. }

为ListView构造出一个适配器:这个适配器就是经常用到的适配器的写法:

 
  1. /**
  2. * Created by HQOCSHheqing on 2016/8/3.
  3. *
  4. * @description 适配器类,就是listview最常见的适配器写法
  5. */
  6. public class NodeTreeAdapter extends BaseAdapter{
  7. //大家经常用ArrayList,但是这里为什么要使用LinkedList
  8. // ,后面大家会发现因为这个list会随着用户展开、收缩某一项而频繁的进行增加、删除元素操作,
  9. // 因为ArrayList是数组实现的,频繁的增删性能低下,而LinkedList是链表实现的,对于频繁的增删
  10. //操作性能要比ArrayList好。
  11. private LinkedList<Node> nodeLinkedList;
  12. private LayoutInflater inflater;
  13. private int retract;//缩进值
  14. private Context context;
  15. public NodeTreeAdapter(Context context,ListView listView,LinkedList<Node> linkedList){
  16. inflater = LayoutInflater.from(context);
  17. this.context = context;
  18. nodeLinkedList = linkedList;
  19. listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
  20. @Override
  21. public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
  22. expandOrCollapse(position);
  23. }
  24. });
  25. //缩进值,大家可以将它配置在资源文件中,从而实现适配
  26. retract = (int)(context.getResources().getDisplayMetrics().density*10+0.5f);
  27. }
  28. /**
  29. * 展开或收缩用户点击的条目
  30. * @param position
  31. */
  32. private void expandOrCollapse(int position){
  33. Node node = nodeLinkedList.get(position);
  34. if (node != null && !node.isLeaf()){
  35. boolean old = node.isExpand();
  36. if (old){
  37. List<Node> nodeList = node.get_childrenList();
  38. int size = nodeList.size();
  39. Node tmp = null;
  40. for (int i = 0;i < size;i++){
  41. tmp = nodeList.get(i);
  42. if (tmp.isExpand()){
  43. collapse(tmp,position+1);
  44. }
  45. nodeLinkedList.remove(position+1);
  46. }
  47. }else{
  48. nodeLinkedList.addAll(position + 1, node.get_childrenList());
  49. }
  50. node.setIsExpand(!old);
  51. notifyDataSetChanged();
  52. }
  53. }
  54. /**
  55. * 递归收缩用户点击的条目
  56. * 因为此中实现思路是:当用户展开某一条时,就将该条对应的所有子节点加入到nodeLinkedList
  57. * ,同时控制缩进,当用户收缩某一条时,就将该条所对应的子节点全部删除,而当用户跨级缩进时
  58. * ,就需要递归缩进其所有的孩子节点,这样才能保持整个nodeLinkedList的正确性,同时这种实
  59. * 现方式避免了每次对所有数据进行处理然后插入到一个list,最后显示出来,当数据量一大,就会卡顿,
  60. * 所以这种只改变局部数据的方式性能大大提高。
  61. * @param position
  62. */
  63. private void collapse(Node node,int position){
  64. node.setIsExpand(false);
  65. List<Node> nodes = node.get_childrenList();
  66. int size = nodes.size();
  67. Node tmp = null;
  68. for (int i = 0;i < size;i++){
  69. tmp = nodes.get(i);
  70. if (tmp.isExpand()){
  71. collapse(tmp,position+1);
  72. }
  73. nodeLinkedList.remove(position+1);
  74. }
  75. }
  76. @Override
  77. public int getCount() {
  78. return nodeLinkedList.size();
  79. }
  80. @Override
  81. public Object getItem(int position) {
  82. return nodeLinkedList.get(position);
  83. }
  84. @Override
  85. public long getItemId(int position) {
  86. return position;
  87. }
  88. @Override
  89. public View getView(int position, View convertView, ViewGroup parent) {
  90. final ViewHolder holder;
  91. if (convertView == null){
  92. convertView = inflater.inflate(R.layout.tree_listview_item,null);
  93. holder = new ViewHolder();
  94. holder.imageView = (ImageView)convertView.findViewById(R.id.id_treenode_icon);
  95. holder.label = (TextView)convertView.findViewById(R.id.id_treenode_label);
  96. holder.confirm = (LinearLayout)convertView.findViewById(R.id.id_confirm);
  97. convertView.setTag(holder);
  98. }else{
  99. holder = (ViewHolder)convertView.getTag();
  100. }
  101. Node node = nodeLinkedList.get(position);
  102. holder.label.setText(node.get_label());
  103. if(node.get_icon() == -1){
  104. holder.imageView.setVisibility(View.INVISIBLE);
  105. }else{
  106. holder.imageView.setVisibility(View.VISIBLE);
  107. holder.imageView.setImageResource(node.get_icon());
  108. }
  109. holder.confirm.setTag(position);
  110. holder.confirm.setOnClickListener(new View.OnClickListener() {
  111. @Override
  112. public void onClick(View v) {
  113. Toast.makeText(context,"选中:"+v.getTag(),Toast.LENGTH_SHORT).show();
  114. }
  115. });
  116. convertView.setPadding(node.get_level()*retract,5,5,5);//处理缩进
  117. return convertView;
  118. }
  119. static class ViewHolder{
  120. public ImageView imageView;
  121. public TextView label;
  122. public LinearLayout confirm;
  123. }
  124. }

所有重点都在注释中说明,此处省略。

最后我们来应用一下:

首先创建一个activity:

 
  1. /**
  2. * Created by HQOCSHheqing on 2016/8/4.
  3. *
  4. * @description
  5. */
  6. public class TreeTestActivity extends Activity{
  7. private ListView mListView;
  8. private NodeTreeAdapter mAdapter;
  9. private LinkedList<Node> mLinkedList = new LinkedList<>();
  10. @Override
  11. protected void onCreate(Bundle savedInstanceState) {
  12. super.onCreate(savedInstanceState);
  13. setContentView(R.layout.select_dept_layout);
  14. mListView = (ListView)findViewById(R.id.id_tree);
  15. mAdapter = new NodeTreeAdapter(this,mListView,mLinkedList);
  16. mListView.setAdapter(mAdapter);
  17. initData();
  18. }
  19. private void initData(){
  20. List<Node> data = new ArrayList<>();
  21. addOne(data);
  22. mLinkedList.addAll(NodeHelper.sortNodes(data));
  23. mAdapter.notifyDataSetChanged();
  24. }
  25. private void addOne(List<Node> data){
  26. data.add(new Dept(1, 0, "总公司"));//可以直接注释掉此项,即可构造一个森林
  27. data.add(new Dept(2, 1, "一级部一级部门一级部门一级部门门级部门一级部门级部门一级部门一级部门门级部一级"));
  28. data.add(new Dept(3, 1, "一级部门"));
  29. data.add(new Dept(4, 1, "一级部门"));
  30. data.add(new Dept(222, 5, "二级部门--测试1"));
  31. data.add(new Dept(223, 5, "二级部门--测试2"));
  32. data.add(new Dept(5, 1, "一级部门"));
  33. data.add(new Dept(224, 5, "二级部门--测试3"));
  34. data.add(new Dept(225, 5, "二级部门--测试4"));
  35. data.add(new Dept(6, 1, "一级部门"));
  36. data.add(new Dept(7, 1, "一级部门"));
  37. data.add(new Dept(8, 1, "一级部门"));
  38. data.add(new Dept(9, 1, "一级部门"));
  39. data.add(new Dept(10, 1, "一级部门"));
  40. for (int i = 2;i <= 10;i++){
  41. for (int j = 0;j < 10;j++){
  42. data.add(new Dept(1+(i - 1)*10+j,i, "二级部门"+j));
  43. }
  44. }
  45. for (int i = 0;i < 5;i++){
  46. data.add(new Dept(101+i,11, "三级部门"+i));
  47. }
  48. for (int i = 0;i < 5;i++){
  49. data.add(new Dept(106+i,22, "三级部门"+i));
  50. }
  51. for (int i = 0;i < 5;i++){
  52. data.add(new Dept(111+i,33, "三级部门"+i));
  53. }
  54. for (int i = 0;i < 5;i++){
  55. data.add(new Dept(115+i,44, "三级部门"+i));
  56. }
  57. for (int i = 0;i < 5;i++){
  58. data.add(new Dept(401+i,101, "四级部门"+i));
  59. }
  60. }
  61. }

布局文件:

#select_dept_layout.xml

 
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. android:layout_width="match_parent"
  3. android:layout_height="match_parent">
  4. <ListView
  5. android:id="@+id/id_tree"
  6. android:layout_width="fill_parent"
  7. android:layout_height="fill_parent"
  8. android:divider="#aaa"
  9. android:dividerHeight="1px"/>
  10. </RelativeLayout>

#tree_listview_item.xml

 
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="wrap_content">
  5. <ImageView
  6. android:id="@+id/id_treenode_icon"
  7. android:layout_width="wrap_content"
  8. android:layout_height="wrap_content"
  9. android:layout_centerVertical="true"
  10. android:layout_marginLeft="5dp"
  11. android:layout_marginRight="5dp"
  12. android:src="@mipmap/expand" />
  13. <!--保证整块区域可点,使用户好点击-->
  14. <LinearLayout
  15. android:id="@+id/id_confirm"
  16. android:layout_width="wrap_content"
  17. android:layout_height="match_parent"
  18. android:layout_alignParentRight="true"
  19. android:layout_centerVertical="true"
  20. android:clickable="true"
  21. android:paddingBottom="8dp"
  22. android:paddingLeft="15dp"
  23. android:paddingRight="15dp"
  24. android:paddingTop="8dp">
  25. <ImageView
  26. android:layout_width="25dp"
  27. android:layout_height="25dp"
  28. android:background="@drawable/login_checkbox_selector"
  29. android:scaleType="centerInside" />
  30. </LinearLayout>
  31. <TextView
  32. android:id="@+id/id_treenode_label"
  33. android:layout_width="wrap_content"
  34. android:layout_height="wrap_content"
  35. android:layout_centerVertical="true"
  36. android:layout_toLeftOf="@id/id_confirm"
  37. android:layout_toRightOf="@id/id_treenode_icon"
  38. android:textColor="@android:color/black"
  39. android:textSize="12sp" />
  40. </RelativeLayout>

实现思路:

 
  1. 要实现一个层级显示的控件,但是又不确定有几层,而内置的ExpandableListView又只能显示两级关系,所以只能自己改造已有的控件或者完全自己写,但是再仔细考虑会发现这两种方式都不太好实现,都需要我们自己处理层级,而且完全自己写还有一个致命问题就是复用问题,即使实现了也会有很多bug,想想会让我们无从下手。但是我们换一种思路,要想展示层级关系,不就是父级与子级之间的缩进不同吗,所以我们是否可以通过控制ListView的各个条目的缩进从而达到这个目的,这样我们就不用管复杂的复用问题了,但是怎么才能实现一层一层的展开、收缩呢?不要想的太复杂,换一种思路,其实就是更改ListView的数据集,展开时将要展开的数据放入到数据集中,收缩时从数据集中删除相应数据即可,这样我们每次只处理与用户点击有关的局部数据,而不用每次遍历所有的数据进行筛选,这样性能会大大提高。
  2. 在实现这个功能之前也上网找了资料,其中深受这篇博客(http://blog.csdn.net/lmj623565791/article/details/40212367)的启发,是站在巨人的肩膀上,在此感谢。
  3. 完整源代码:[http://download.csdn.net/detail/hqocshheqing/9601185][http_download.csdn.net_detail_hqocshheqing_9601185]
  4. github地址:[https://github.com/heqinghqocsh/TreeView][https_github.com_heqinghqocsh_TreeView]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1175706.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Weblogic ssrf漏洞复现

文章目录 一、漏洞描述二、漏洞特征1.查看uddiexplorer应用2.漏洞点 三、漏洞复现1.获取容器内网ip2.VULHUB Weblogic SSRF漏洞 docker中 centos6 无法启动的解决办法3.准备payload4.反弹shell 一、漏洞描述 SSRF 服务端请求伪造(Server-Side Request Forgery),是一种由攻击者…

想要制作一本简单的电子画册,应该怎么做?

随着移动互联网的快速发展&#xff0c;越来越多人开始想要制作电子画册并利用电子画册实现营销宣传。0基础如何制作电子画册&#xff0c;教你一个简单制作的方法。 利用FLBOOK在线电子画册制作平台就可轻松制作&#xff0c;比PPT更简单&#xff0c;迅速上手使用。下面是详细的制…

2023年app拉新地推接单平台有哪些?十大地推团队接单平台必备

地推和网推拉新行业在步入2023年以后&#xff0c;有了长足的进步&#xff0c;因此也有很多互联网团队开始转型从事地推app拉新和网推app拉新作业。那么对于地推团队和网推团队而言&#xff0c;应该去哪里接单&#xff1f;换言之&#xff0c;2023年地推团队和网推团队的接单平台…

岩土工程公路隧道监测中智能振弦传感器的应用方案

岩土工程公路隧道监测中智能振弦传感器的应用方案 隧道建设是现代城市发展中不可或缺的一部分。但隧道工程建设与维护过程中需要考虑诸多风险。地质环境复杂&#xff0c;地下水位、地震等因素可能导致隧道构造物的沉降、变形等问题。为此&#xff0c;在隧道建设和运营过程中&a…

钉钉企业微应用开发C#+VUE

钉钉相信很多人都用过或听过&#xff0c;企业OA审批&#xff0c;考勤&#xff0c;沟通方方面面都支持。但是有的需求自定义表单的无法满足&#xff0c;例如带有业务特性的数据来源&#xff0c;可能是内部其他系统&#xff0c;以及数据筛选分析没有那么方便&#xff0c;钉钉官方…

精品小站

今天分享几个精品小站&#xff0c;换换心情&#xff0c;您的在看、转发、点赞 就是对tuonioooo最大的支持&#xff01; xodo在线PDF工具 网址&#xff1a;https://xodo.com/ 一个国外的网站提供免费的PDF转换、在线阅读、编辑和多人协作工具。这个网站支持对PDF进行编辑&…

08 叉积的标准介绍

叉积的标准介绍 基本概念几何解释 这是关于3Blue1Brown "线性代数的本质"的学习笔记。 基本概念 向量 v ⃗ \vec{v} v 叉乘向量 w ⃗ \vec{w} w 的结果大小是这两个向量围成的平行四边形的面积&#xff0c;方向由右手定则确定。 v ⃗ w ⃗ \vec{v}\vec{w} v w - …

爱德华的台灯真的好用?爱德华、书客、好视力护眼台灯对比测评

如今孩子近视的比例越来越大&#xff0c;而且时间越来越提前&#xff0c;一些上小学的孩子开始近视佩戴眼镜。其实造成近视的原因不外乎作业坐姿不标准&#xff0c;学业时间太长缺少户外的运动&#xff0c;也包括可能灯光光源的问题造成对于视力的影响。如果希望孩子有一个较好…

awk精确筛选

awk精确筛选: $(><):用于对比数值 $n~"字符串"代表第n个字段包括某个字符 $n!~"字符串"代表第n个字段不包括某个字符 $n"字符串"代表第n个字段为某个字符 $n!"字符串"代表第n个字段不为某个字符 $NF:最后一个字段 awk -F…

Linux文件系统(操作系统的文件管理)

文章目录 一.内存中的文件管理(文件与进程)二 .Linux系统视角下的计算机外设三.磁盘上的文件管理 参考Linux内核源码版本------linux-2.4.3 一.内存中的文件管理(文件与进程) 操作系统之下,进程是计算机系统执行计算任务的基本单位,进程访问文件执行数据读写之前,操作系统会从…

C++ 代码实例:并查集简单创建工具

文章目录 前言代码仓库代码说明main.cppMakefile 结果总结参考资料作者的话 前言 C 代码实例&#xff1a;并查集简单创建工具。 代码仓库 yezhening/Programming-examples: 编程实例 (github.com)Programming-examples: 编程实例 (gitee.com) 代码 说明 简单地创建并查集注…

MATLAB - Gazebo 联合仿真 —— 使用 UR10 机械臂检测和采摘水果

系列文章目录 文章目录 系列文章目录前言一、设置 Gazebo 仿真环境二、在 Gazebo 中模拟和控制机器人2.1 概述2.2 任务调度器2.3 感知和目标生成系统2.4 运动规划2.5 机械臂和关节控制系统 三、分配用于控制机器人的参数3.1 定义机器人模型和运动规划参数&#xff0c;3.2 定义机…

基于野马算法的无人机航迹规划-附代码

基于野马算法的无人机航迹规划 文章目录 基于野马算法的无人机航迹规划1.野马搜索算法2.无人机飞行环境建模3.无人机航迹规划建模4.实验结果4.1地图创建4.2 航迹规划 5.参考文献6.Matlab代码 摘要&#xff1a;本文主要介绍利用野马算法来优化无人机航迹规划。 1.野马搜索算法 …

基于向量加权平均算法的无人机航迹规划-附代码

基于向量加权平均算法的无人机航迹规划 文章目录 基于向量加权平均算法的无人机航迹规划1.向量加权平均搜索算法2.无人机飞行环境建模3.无人机航迹规划建模4.实验结果4.1地图创建4.2 航迹规划 5.参考文献6.Matlab代码 摘要&#xff1a;本文主要介绍利用向量加权平均算法来优化无…

CSS 滚动捕获 Scroll Snap

CSS 滚动捕获 Scroll Snap CSS 滚动捕获允许开发者通过声明一些位置(或叫作捕获位置)来创建精准控制的滚动体验. 通常来说轮播图就是这种体验的例子, 在轮播图中, 用户只能停在图 A 或者图 B, 而不能停在 A 和 B 的中间. 比如平时用淘宝或小红书, 当你上滑到下一个推荐内容时…

分享90个节日庆典PPT,总有一款适合您

分享90个节日庆典PPT&#xff0c;总有一款适合您 PPT下载链接&#xff1a;百度网盘 请输入提取码 提取码&#xff1a;8888 Python采集代码下载链接&#xff1a;采集代码.zip - 蓝奏云 学习知识费力气&#xff0c;收集整理更不易。知识付费甚欢喜&#xff0c;为咱码农谋福利…

浅析C/C++的内存分段

这部分是计算机系统相关的知识&#xff0c;碍于本人才疏学浅&#xff0c;如本文存在疏漏或者错误&#xff0c;还望大佬能帮忙指出&#xff0c;感激不尽。 内存分段 从狭义上讲内存的分段可以分为堆、栈、数据段以及代码段&#xff08;内存映射区比较复杂&#xff0c;暂不涉及…

C++ Concurrency in Action 2nd Edition

《C Concurrency in Action - SECOND EDITION》的中文翻译-面圈网 (mianshigee.com) C/C 学习教程源码-C/C源码推荐-面试哥 (mianshigee.com) 作者正是为C11标准引入线程库的C标准委员会成员本人&#xff01;并且本书作者还编写了众多构成C标准的多线程和并发相关的提案、制定…

基于天鹰算法的无人机航迹规划-附代码

基于天鹰算法的无人机航迹规划 文章目录 基于天鹰算法的无人机航迹规划1.天鹰搜索算法2.无人机飞行环境建模3.无人机航迹规划建模4.实验结果4.1地图创建4.2 航迹规划 5.参考文献6.Matlab代码 摘要&#xff1a;本文主要介绍利用天鹰算法来优化无人机航迹规划。 1.天鹰搜索算法 …

如何使用腾讯云+Picgo搭建图床

目录 一、进入腾讯云进行实名认证 二、领取免费存储额度 2.1新用户界面概览就可以领取 三、开始创建远端图床并生成秘钥等信息 3.1创建存储桶 3.2配置基本信息 3.3配置高级选项 3.4确认配置页面点击创建即可 3.5创建访问秘钥 3.6查看秘钥等信息 3.7查看桶名称 四、图…