精华内容
下载资源
问答
  • 独立完成系统开发一:项目简介

    千次阅读 多人点赞 2020-02-09 17:34:00
    当然我也意识到了一个问题,就是如果仅仅是在工作中完成所分配的任务重复的去做一些类似于curd之类的事,没有将所学的东西真正运用到实际的项目中串联起来以及没有一个完完整整的项目独立开发经验,那么就真的只能是...

    独立完成系统开发一:项目简介

    从工作到现在也有很长一段时间了,在这段时间里经历了很多同时也学到了很多。当然我也意识到了一个问题,哪就是如果仅仅是在工作中重复的去做一些类似于curd之类的事,没有将所学的东西真正运用到实际的项目中以及对一个项目没有一个全面的了解,那么可能就真的是一个码农了。

    所以我决定用我这些年所学的东西去独立的完成一个项目。虽然这个可能有点难度,并且需要耗费很多精力,但我觉得还是很有必要的,在提升自身能力的同时也相当于给这些年所付出的努力一个交代吧。为了更便于以后查看以及给这个项目的历程做个记录,所以我决定把这个写成一个博客的专栏,如果能帮助其他的童鞋那再好不过。同时我也会根据这个项目为主干去写一些这个项目里面所用到的技术博文。当然这个项目里面没用到的我有时间也会去写一写,在加深理解的同时也能够帮助其他需要的童鞋。

    项目介绍

    这篇是我写的第一篇博文就先介绍一下这个项目吧。
    这个项目的名字我想了很久,最后决定叫他MyAdmin,这个名字主要受到MySQL的启发(当然MySQL中My是MySQL作者女儿名字的简写并不是“我的”的意思。而这里的My意思就是“我的”),然后管理系统都叫什么admin之类的。所以就想到了MyAdmin,听起来还不错哈~

    而项目图标的设计,由于项目叫MyAdmin所以主要突出My ,所以图标里面要体现出这个单词,为此我还专门去了解了一下ps,最后设计的出来的结果:

    感觉还不错哈~,下面我来解释一下这个图标以及设计时的灵感,首先这个图标外圈绿色的部分的写法和M的写法一致的,只不过M的最后一笔是竖着的|而这里是斜着的/。然后图标中的最后一笔的/和前两笔也就是v的部分连起来可以看成y,这里稍微有点抽象哈。这样就将M和y整合在一起了,最后整个图形拼起来整体像一个斜着的V,而这个项目前端本来就是用vue做的,所以感觉这个图标更合适了呢。最后是配色由于图标整体看起来像一个v,而vue的图标也是v,所以外圈的颜色参考了vue的图标的配色,毕竟vue的图标设计的还是很棒的哈。

    目前项目已经完成,部分代码也开源了,具体可以查看githubgitee,欢迎star,如有问题可以提交相关issue,后面会考虑完全开源哈,敬请期待~

    演示地址:http://8.129.86.120/

    • 演示环境说明:演示地址目前只有工作流示例生成代码展示可以进行增加及修改系列操作,其他功能只开放了查询操作
    • 账号:管理员(admin),其他用户(user1、user2、user3...具体可查看系统中用户模块)
    • 密码:所有用户的密码都为123456

    业务

    这个项目的目标是包含一个系统中所有的基础功能,然后我们可以基于这个项目进行各种业务模块的开发。所以这个项目主要作为一个基础的平台,当然我也会在项目中提供一系列的示例。具体包含哪些功能可以参考githubgitee中的介绍

    使用技术

    这个项目采用的是一个前后端分离的模式,技术选型的话

    • 前端主要是基于vue,然后结合vue-element-admin前端模板来实现。
    • 后端主要是基于java,然后通过springboot,mybatis-plus,shiro、activiti等框架来实现

    最初我是想使用微服务的架构然后通过spring cloud来实现的,不过这个可能会更复杂,所以想先把springboot版本的弄好后面在弄个spring cloud的这样会简单些一步步来哈,并且如果项目不是特别大用微服务架构反而没有单个项目好。

    具体涉及知识点

    了解这些会让你更好的掌握整个项目

    • 前端
      • 基础的:HTML、JavaScript、CSS、ES6、SCSS
      • Vue系列及相关:Vue.js、Vuex、Vue Router 、Vue CLI,ElementUI、Axios
      • 插件:插件有很多这里简单列举几个:EChartss、js-xlsx、wangEditor、vue-amap等等
      • 其他:Node.js、webpack、mock.js、ESlint、Babel
    • 后端
      • 基础的:Java
      • 框架:Spring Boot、MyBatis-Plus、Shiro、Swagger2、Activiti
      • 数据库:MySQL
      • 缓存:EhCache、Redis
      • 其他:JWT、Druid、Logback等等
    • 工具
      • 前端开发工具使用vsCode,因为这个可以结合ESlint插件实现代码格式自动修复
      • 后端开发工具使用idea,当然eclipse也行,经过使用后我觉得idea在各个方面真的比eclipse要好,只不过占的内存有点大
      • 代码管理使用git,而且idea对git的支持比svn要好
      • web服务器,在正式环境这里使用nginx来实现动静分离及反向代理,如果部署多台后端还可以通过nginx实现负载均衡,前端项目通过webpack打包好之后直接放到nginx中就可以了,当然如果开发环境我们直接使用webpack-dev-server来实时打包构建就可以了,vue-cli构建的项目都会自带,至于后端直接使用springboot内置的tomcat就行了。

    当然整个项目所涉及到的东西肯定不仅仅只有这些,具体可以参考项目中的maven以及npm依赖。

    技术的选型

    上面说了项目里面涉及到的技术,而市面上的技术框架很多,所以下面来简单说一下我为什么选择他们。

    前端

    前端首先要明确一个点就是我们要弄的是一个前端分离的项目,因为前后端分离相比于前后端不分离的项目有很大的优势例如

    • 提高工作效率,分工更加明确。前端只关注前端的事,后台只关心后台的活,两者开发可以同时进行。不会出现相互制约的情况
    • 性能提升,通过前端路由的配置,我们可以实现页面的按需加载,无需一开始加载首页便加载网站的所有的资源,服务器也不再需要解析前端页面,并且在大并发情况下,可以同时水平扩展前后端服务器
    • 让系统更容易维护,发生bug,可以快速定位是谁的问题,不会出现互相踢皮球的现象,而且处理问题只需要一方处理就行了

    vue

    而在前后端项目里面前端框架主要流行的有这么几个,分别是vue、react以及angular,他们都有各自的优点但也有很多相似的地方,至于我选择vue主要有这么几方面

    • 首先这个项目并不是很大所以排除angular,然后vue和react相比我更熟悉的是vue,而且vue相对于其他两个上手会容易很多
    • vue中我找到了一个很好用的前端模板vue-element-admin ,通过这个模板我可以少做很多的工作,所以我选择了vue

    element

    然后就是vue的前端ui,vue的前端ui也是很多的例如:iViewElement等等,因为vue-element-admin使用的ui是element,所以这里也使用了element,而element是饿了么前端开源的UI框架所以还是很优秀的

    后端
    • spingboot
      • 目前行业里面如果是新增的项目90%都会采用springboot吧,相比于直接使用spring,使用sprinboot最直观的优势就是可以省去大量的配置,因为他为我们提供了开发绝大多数场景的starter pom,这些starter可以帮我们进行大量的自动配置,要什么那么只需要导入对应的starter pom依赖就可以了,并且使用sprinboot之后对项目进行配置不用再编写xml,在配置的时候我们可以直接修改配置文件或者在代码里面提供相应bean就可以了
    • mybatis-plus
      • mybatis-plus他是mybatis的一个增强,通过他可以实现不用写sql就可以操作数据库,当然这个只适用于增删改以及一些简单的查询,复杂的查询还是建议自己写sql。而且他还提供了分页组件、代码生成器等等。具体可以参考官网,这个是国人开发的,所以文档中文支持特别好
    • shiro和jwt
      • 由于spring security上手难度有点高,而且挺麻烦的。所以我就选择了比较熟悉而且使用简单的shiro,至于jwt是因为我们这个是前后端分离的项目所以需要对shiro进行改造,而jwt则作为token来使用
    • swagger2
      • 因为我们是前后端分离的项目,那么怎么分离呢?这就需要在后端使用swagger2以及在前端使用mock.js来实现了,在前端可以通过mock来模拟后端的数据这样就不需要在依赖于后端了,而在后端通过swagger可以生成接口文档,而且还可以直接对接口进行测试这样就不需要在依赖于前端了而且还可以直接生成接口文档。
    • activiti
      • 工作流常见的框架有jbpm和activiti,这两个我都有了解过,activiti相对于jbpm在api的使用方面会好用很多,而且相对于jbpm我更熟悉activiti,所以项目的工作流我选择使用activiti
    • mysql
      • 目前常用的数据就两个oracle和mysql,在平常的使用中你说使用起来那个更方便,我认为oracle使用起来会方便很多,因为在oralce中提供了很多强大的功能例如像数据库的闪回,递归函数等等。这些在mysql中是没有的。那为什么我会选择mysql呢,主要有有这么几点:首先mysql是免费的,而oralce是收费的(可以破解哈,不过还是建议支持正版),mysql没有oracle那么重量级,还有就是我更熟悉使用mysql来搭建主从,集群以及实现数据的分库分表。而且在平常中工作中大部分都是使用oralce,所以我想借这个机会在深入的了解一下mysql。

    系统预览

    这里只贴PC端的项目图片,至于移动端的以及工作流的gif图片预览可以去githubgitee上去看(工作流gif图片有点大,推荐到gitee上看,github可能加载不出来,还有gitee上大于1M的文件要登录之后才可以查看哦)

    在这里插入图片描述 在这里插入图片描述
    在这里插入图片描述 在这里插入图片描述
    在这里插入图片描述 在这里插入图片描述
    在这里插入图片描述 在这里插入图片描述
    在这里插入图片描述 在这里插入图片描述
    在这里插入图片描述 在这里插入图片描述
    在这里插入图片描述 在这里插入图片描述
    在这里插入图片描述 在这里插入图片描述
    在这里插入图片描述 在这里插入图片描述
    在这里插入图片描述 在这里插入图片描述
    在这里插入图片描述 在这里插入图片描述
    在这里插入图片描述 在这里插入图片描述
    在这里插入图片描述 在这里插入图片描述
    在这里插入图片描述 在这里插入图片描述
    在这里插入图片描述 在这里插入图片描述
    在这里插入图片描述 在这里插入图片描述

    下一篇:独立完成系统开发二:前端搭建

    展开全文
  • 1.BeginWaitCursor()是CCmdTarget类函数 函数原型:void BeginWaitCursor()...注意:在不是处理单个消息时,BeginWaitCursor()可能不像其它函数那样有效,例如:OnSetCursor()处理也能改变光标形状。 2.函数En...

    1.BeginWaitCursor()是CCmdTarget类的函数

      函数原型:void   BeginWaitCursor();  
      功能简介:本函数用于显示沙漏光标。调用本函数显示沙漏光标,告诉用户系统正在运行,繁忙。
      注意:在不是处理单个消息时,BeginWaitCursor()可能不像其它函数那样有效,例如:OnSetCursor()的处理也能改变光标形状。  
    2.函数EndWaitCursor可以恢复此前的光标。
    --------------------- 
    作者:行者无疆帆 
    来源:CSDN 
    原文:https://blog.csdn.net/yf0811240333/article/details/38760003 
    版权声明:本文为博主原创文章,转载请附上博文链接!

     

    SetCapture():

    该函数在属于当前线程的指定窗口里设置鼠标捕获。一旦窗口捕获了鼠标,所有鼠标输入都针对该窗口,无论光标是否在窗口的边界内。同一时刻只能有一个窗口捕获鼠标。如果鼠标光标在另一个线程创建的窗口上,只有当鼠标键按下时系统才将鼠标输入指向指定的窗口。

    当你不在需要继续获得鼠标消息就要应该调用ReleaseCapture()释放掉,否则别的线程想调用就会失败。记住:SetCapture()和ReleaseCapture()必须成对呈现。

            BeginWaitCursor();
    		SetCapture();
    		while(!m_ImgShow.m_ltCurCorImg.empty()&&!m_ImgShow.m_bganyu)
    		{
    			num++;
    			CLog::GetInstance()->WriteLog(_T("正在保存数据,num:%d"),num);
    			Sleep(50);
    		}
    		if (m_vImgBig.size()!=0)
    		{
    			CLog::GetInstance()->WriteLog(_T("保存多图干预数据m_vImgBig"));
    			m_correctMultiImgs.SaveImgVectorLayers(m_vImgBig);
    		}
    		if (m_vImgBig.size()!=0)
    		{
    			CLog::GetInstance()->WriteLog(_T("保存多图干预数据m_vImgSmall"));
    			m_correctMultiImgs.SaveImgVectorLayers(m_vImgSmall);
    		}
    		
    		EndWaitCursor();
    		ReleaseCapture();

     

    展开全文
  • 我们先建立完成我们的自定义列表,列表字段相对来说比较简单,可以... 分配组 由于涉及到批量的任务分配,因此可能分配给一个人,因此我们需要建立好相应的sharePoint组才能接受这些任务邮件d. 任务状态 任务状

    我们先建立完成我们的自定义列表,列表字段相对来说比较简单,可以采用4~5列的列表来作为分派任务的列表,列表字段如下:

    a. 任务名称    建立任务的名称,任务的相关的内容

    b. 任务分配起始时间          任务设置的开始时间

    c. 任务执行最终截止时间    任务开始后最后的结束时间

    d. 分配组      由于涉及到批量的任务分配,因此不太可能分配给一个人,因此我们需要建立好相应的sharePoint组才能接受这些任务邮件

    e. 任务状态  任务状态可以分为任务分派、响应任务、任务结束三个阶段

    f. 任务接收者  任务接收者主要是响应任务的人,由于我们需要了解到谁编辑了当前的任务,这个是直接分派到我们的组是不同的,因此我们需要设置单独的一个字段来了解谁进行了任务的修改

    接下来我们来建立这么几个字段:

    1. 任务名称,这里就是我们的Title ,我们直接修改相关的字段即可:

    2. 接下来设置我们的任务开始时间,默认为当前创建任务的时间,注意格式,这里我么需要设置为日期时间,否则后面无法进行计算:

    3. 接下来设置任务结束时间,我们这里设置的结束时间必须填写,否则会导致流程出错,因此这里填写必须填写的复选框:

    4.接下来设置任务的分配组,由于我们的任务可能分配给多个不同的类别用户,因此我们需要分配给这些用户组,这里我们必须设置如下:

    5. 接下来设置任务的分配状态:

    我们这里设置三种状态:

    任务分配

    任务响应

    任务关闭

    因此这里设置方法如下:

    6. 接下来的字段继续是我们的编辑者,也是我们的用户和用户组:


    到此为止,我们的用户编辑列表已经完成,接下来我们就要用我们的SharePoint Designer进行配置我们的工作流程了!

    展开全文
  • 说明 更新说明:Ehab Amer已针对Swift 5,iOS 12和Xcode 10更新了本教程。...您可能会发现自己删除了该区域中所有约束,然后又重新添加了它们。 UIStackView简化了此类任务。您可以轻松地在堆栈视图

    说明

    更新说明:Ehab Amer已针对Swift 5,iOS 12和Xcode 10更新了本教程。Jawwad Ahmad撰写了原文。

    您是否曾经需要在运行时期间从视图中添加视图或从视图中删除视图,并调整视图旁边的视图布局?也许您调整了一些约束或使用了第三方库来完成这项工作。也许不是在运行时运行,而是您想在情节提要中的其他视图之间添加一个新视图。

    在这些情况下,您需要更改几个约束。您可能会发现自己删除了该区域中的所有约束,然后又重新添加了它们。

    UIStackView简化了此类任务。您可以轻松地在堆栈视图中水平或垂直放置一系列视图,并通过对齐,分布和间距等属性将视图自动调整为可用空间的方式进行设置。请享用!:]

    注意:本教程假定您基本熟悉自动版式。如果您不熟悉自动版式,请查看“AutoLayout开始自动版式”视频教程。

    入门

    首先使用本教程下载项目材料。使用iPhone 8 Simulator在Xcode中构建并运行starter项目。您会看到以下内容:

    在这里插入图片描述
    这是假期景点应用程序。它提出了一个摆脱一切的地方清单。在前往任何地方之前,您将使用Stack Views解决该应用程序的一些问题。

    探索度假胜地

    去伦敦的信息视图通过点击伦敦。乍一看,该视图可能看起来不错,但存在一些问题:

    1. 查看视图底部的按钮行。由于它们之间的间距固定,因此它们无法适应屏幕宽度。为了更好地解决问题,请按Command-左箭头将模拟器旋转为横向。
      在这里插入图片描述
    2. 点击“天气”旁边的“隐藏”。这将隐藏文本,但不会重新定位其下面的部分,而是留出一块空白。
      在这里插入图片描述
    3. 节订购需要改进。这将是更符合逻辑的,如果看到什么后出现为什么参观定位它们之间的天气部分代替。
    4. 在横向模式下,按钮的底行太靠近视图的底部边缘。如果减小各部分之间的间距,则效果会更好-但仅在横向模式下。

    既然您已经知道将要进行的改进,那么现在该深入研究该项目了。打开Main.storyboard。它将以初始设备视图打开。确保将iPhone 8显示为所选设备。
    在这里插入图片描述
    这在运行时没有影响,但可以帮助您查看屏幕在该设备上的外观。您可以随时单击另一个图标来更改所选设备。将鼠标悬停在图标上可以显示其相应的设备。
    在这里插入图片描述
    注意:如果减小Interface Builder的画布宽度(大约小于650像素),则用于更改设备的UI会稍有变化。设备列表折叠到设备下拉列表中:
    在这里插入图片描述
    当按下时,将显示垂直排列的可用设备列表:
    在这里插入图片描述
    现在,仔细查看Spot Info View Controller:
    在这里插入图片描述
    您可能想知道颜色是什么?

    这些标签和按钮的背景色在运行时不会显示。在情节提要中,它们是视觉辅助工具,有助于显示更改堆栈视图的各种属性如何影响其嵌入式视图的框架。

    如果您希望在运行应用程序时随时查看背景颜色,则可以暂时将viewDidLoad()里面的以下行注释掉SpotInfoViewController。

    // Clear background colors from labels and buttons
    for view in backgroundColoredViews {
      view.backgroundColor = UIColor.clear
    }
    

    任何与插座连接的标签均具有与插座变量名称匹配的占位符文本。这样可以更轻松地确定在运行时将更新哪些标签的文本。例如,带有文本< whyVisitLabel>的标签连接到:

    @IBOutlet var whyVisitLabel: UILabel!
    

    是时候开始了!

    您的第一个堆栈视图

    首先,您将固定底部一行按钮之间的间距。堆栈视图可以通过各种方式沿其轴分布其子视图。一种方法是在每个视图之间设置相等的间距。
    在这里插入图片描述
    幸运的是,将现有视图嵌入到新的堆栈视图中可谓小菜一碟。首先,通过单击一个,然后在其他两个上单击命令,选择“ Spot Info View Controller”场景底部的所有按钮。使用情节提要画布左下角的“显示文档大纲”按钮打开大纲视图。
    在这里插入图片描述
    确认您已选择所有三个按钮。
    在这里插入图片描述
    它们在大纲视图中突出显示。您也可以在大纲视图中单击命令的每个按钮以选择它们。

    选择后,在情节提要画布右下角的“自动布局”工具栏中单击“嵌入”按钮。出现带有可用嵌入选项的菜单。选择堆栈视图:
    在这里插入图片描述
    Xcode将为您将按钮嵌入新的堆栈视图中。

    在这里插入图片描述

    堆栈视图约束

    尽管堆栈视图负责放置按钮,但是您仍然需要添加自动布局约束来定位堆栈视图本身。

    当您将视图嵌入堆栈视图时,它将失去对其他视图的约束。例如,在将按钮嵌入到堆栈视图中之前,“提交评分”按钮的顶部与RATING标签的底部之间存在垂直间距约束:
    在这里插入图片描述
    选择“提交评分”按钮,并验证它不再具有任何约束:

    在这里插入图片描述
    您还可以查看大小检查器(Option-Command-5)以验证是否没有约束:
    在这里插入图片描述
    有时很难在拥挤的情节提要的视图控制器中选择特定元素。您可以从大纲视图中选择元素,或使用Shift并在要选择的视图上单击鼠标右键或按住Control键并按住Shift键单击。这为您提供了一个上下文菜单,该菜单显示了单击位置的视图层次结构。通过在菜单中单击选择堆栈视图。
    在这里插入图片描述
    既然已经选择了“堆栈视图”,则可以向其添加约束。
    在这里插入图片描述
    单击自动版式工具栏中的“添加新约束”按钮以显示“添加新约束”弹出窗口。
    在这里插入图片描述
    首先,在Constrain to margins上添加一个选中标记。然后,将以下约束添加到堆栈视图的边缘:

    Top: 20, Leading: 0, Trailing: 0, Bottom: 0
    

    仔细检查顶部,顶部,底部和底部约束的数字。确保您已打开四个红色工字梁并限制到边距。然后,点击添加4个约束。
    在这里插入图片描述
    现在,堆栈视图的大小正确,但是它拉长了第一个按钮以填充任何额外的空间。

    在这里插入图片描述

    堆栈视图外观

    确定堆栈视图如何沿其轴布置其子视图的属性为distribution。当前,它设置为Fill,这意味着子视图将沿其轴完全填充堆栈视图。为此,堆栈视图将仅扩展其子视图之一以填充该额外空间。具体来说,它会以拥有最低优先级的水平内容来扩展视图,或者如果所有优先级都相等,则会扩展第一个视图。

    但是,您不希望按钮完全充满堆栈视图,而是希望它们之间的间距相等。

    确保堆栈视图仍处于选中状态,然后转到“属性”检查器。更改分配从填充到间距相等:
    在这里插入图片描述
    现在构建并运行,点击任意一个单元,然后旋转模拟器。您会看到底部按钮现在的间距相等!
    在这里插入图片描述

    在这里插入图片描述
    实施UI时,请始终问自己元素是否适合可用空间。

    这是您的内容如何影响用户体验的示例:将Wikipedia按钮的标题更改为Wikipedia网站并运行该应用程序。将模拟器从纵向旋转到横向以查看差异。
    在这里插入图片描述
    在这里插入图片描述
    在空间较窄的纵向模式下,最后一个按钮中的文本会被剪切,而在横向模式下,所有内容都适合。

    这是您经常遇到的事情,尤其是在iPhone SE等较窄的屏幕尺寸上。

    幸运的是,这很容易解决。在仍然选择堆栈视图的情况下,返回Attributes inspector。将分布从等间距更改为按比例填充,并将间距值更改为10:
    在这里插入图片描述
    现在,构建并运行并检查两个方向。您会按顺序找到所有内容。
    在这里插入图片描述
    将按钮的名称更改回Wikipedia。

    恭喜,您已经建立了第一个堆栈视图!

    没有堆栈视图

    为了在没有堆栈视图的情况下解决此间距问题,您将必须在每对按钮之间使用一个间隔视图,向所有间隔视图添加相等的宽度约束,以及几个其他约束以正确放置间隔视图。

    这看起来类似于以下内容。为了在屏幕截图中可见,间隔视图显示浅灰色背景:
    在这里插入图片描述
    如果您必须在情节提要中执行一次操作并不太麻烦,但是许多视图是动态的。由于相邻的间隔视图和约束,在运行时添加新按钮或隐藏或删除现有按钮不是一项简单的任务。

    为了在堆栈视图中隐藏视图,请将包含的视图的hidden属性设置为true,然后堆栈视图将处理其余视图。这是当用户将文本隐藏在WEATHER标签下时固定其间距的方法。将天气部分标签添加到堆栈视图后,即可在本教程中进行操作。

    注意:现在您知道如何在堆栈中指定子视图之间的间隔。但是,如果您想要在特定子视图后使用不同的间距怎么办?从iOS 11开始,您可以使用setCustomSpacing:afterView进行此操作

    转换节

    接下来,您将转换所有其他部分SpotInfoViewController以使用堆栈视图。这使您能够完成其余任务。从评分部分开始。

    转换评级部分
    在您创建的堆栈视图上方,选择“评分”标签和旁边的星号标签。

    然后,单击编辑器▸嵌入▸堆栈视图中。

    现在,选择新创建的堆栈视图,然后再次单击“添加新约束”按钮。在约束到边距中打勾,并添加以下三个约束:

    Top: 20, Leading: 0, Bottom: 20
    

    在这里插入图片描述
    现在转到“属性”检查器并将间距设置为8。

    注意:您可能已经注意到,间距已经设置为8。以前,间距自动设置为24。Xcode变得足够聪明,可以推断出间距值以匹配嵌入视图之前的值。很酷吧?

    生成并运行以验证所有内容与以前相同。

    取消嵌入堆栈视图

    在您走得太远之前,最好先进行一些急救培训,以防出现问题。例如,您可能会因为实验,重构或偶然而发现自己拥有额外的堆栈视图。

    幸运的是,有一种简单的方法可以从堆栈视图中取消嵌入视图。

    首先,选择要删除的堆栈视图。单击嵌入按钮。接下来,在出现的上下文菜单上选择“未嵌入”:
    在这里插入图片描述
    执行此操作的另一种方法是选择堆栈视图,然后从菜单中选择“编辑器”▸“未嵌入”。

    创建垂直堆栈视图
    现在,创建您的第一个垂直堆栈视图。选择“为什么访问”标签及其下方的,然后选择“嵌入在▸堆栈视图中”。

    当您将标签嵌入堆栈视图中时,Xcode会根据标签的位置推断它应该是垂直堆栈。

    较低的标签以前具有将其固定在右边距的约束,但是将标签嵌入堆栈视图中可以消除该约束。当前,堆栈视图没有任何约束,因此采用其最大视图的固有宽度。

    选择堆栈视图后,单击“添加新约束”按钮。将顶部约束,前导约束和尾随约束设置为0。同样,请确保选中约束到边距。

    然后,单击底部约束右侧的下拉菜单,然后选择WEATHER(当前距离= 20):
    在这里插入图片描述
    默认情况下,Interface Builder会向您显示到最近邻居的约束,对于底部约束,约束是距离15的“隐藏”按钮。您需要将该约束置于其下方的WEATHER标签。

    最后,点击添加4个约束。您现在应该看到以下内容:

    在这里插入图片描述
    现在,您有了一个展开的堆栈视图,其右边缘固定在视图的右边距。但是,底部标签的宽度仍然相同。您将通过更新堆栈视图的alignment属性来解决此问题。

    对齐属性

    该alignment属性确定堆栈视图如何垂直于其轴布置其视图。对于一个垂直堆叠视图中,可能的值是Fill,Leading,Center,和Trailing。

    水平堆栈视图的可能alignment值略有不同:

    在这里插入图片描述
    水平堆栈视图具有.top而不是.leading和具有.bottom而不是.trailing。也有两个属性,只有在水平方向上是有效的,.firstBaseline和.lastBaseline。

    选择每个值以查看它如何影响垂直堆栈视图中的标签放置:

    Fill:
    在这里插入图片描述
    Leading:
    在这里插入图片描述

    Center:
    在这里插入图片描述

    Trailing
    在这里插入图片描述

    测试完每个值后,将Alignment设置为Fill:
    在这里插入图片描述
    生成并运行以验证一切看起来都不错,并且没有回归。

    指定Fill意味着您希望所有视图都填充垂直于其轴的堆栈视图。这也会导致WHY VISIT标签也扩展到右边缘。

    如果您只希望底部标签扩展到边缘怎么办?

    目前,这并不重要,因为两个标签在运行时都具有清晰的背景,但是在转换天气部分时将很重要。

    您将学习如何使用附加的堆栈视图来实现这一点

    转换看什么部分

    转换此部分与您已经完成的操作类似。

    1. 首先,选择要查看的标签,然后选择其下方的< whatToSeeLabel>。
    2. 单击“嵌入”按钮,然后选择“堆栈视图”。
    3. 单击固定按钮。
    4. 选中约束到边距并添加以下四个约束:
    Top: 20, Leading: 0, Trailing: 0, Bottom: 20
    
    1. 将堆栈视图的Alignment设置为Fill。

    现在,您的情节提要板应如下所示:
    在这里插入图片描述这使您仅剩下天气部分。

    转换天气部分

    由于“隐藏”按钮,天气部分比其他部分更为复杂。

    要转换天气部分,您可以通过将WEATHER标签和Hide按钮嵌入水平堆栈视图中来创建嵌套堆栈视图。然后,将该水平堆栈视图和< weatherInfoLabel>嵌入到垂直堆栈视图中。

    它看起来像这样:

    在这里插入图片描述
    请注意,“天气”标签已扩展为等于“隐藏”按钮的高度。这将在WEATHER标签的基线与其下方的文本之间留出额外的空间。

    请记住,它alignment指定垂直于堆栈视图的位置。因此,您可以将设置alignment为Bottom:

    在这里插入图片描述
    但是,您不希望“隐藏”按钮的高度决定堆栈视图的高度。

    相反,您将从所有堆栈视图中删除“隐藏”按钮。

    “隐藏”按钮将保留在顶层视图的子视图中,您将向其添加约束到WEATHER标签中-该标签将在堆栈视图中。没错,您将从堆栈视图外部的按钮向堆栈视图内的标签添加约束!

    选择WEATHER标签并在其下方选择< weatherInfoLabel>,然后将它们堆叠在Stack View中。

    单击添加新约束按钮,选中约束到边距并添加以下四个约束:

    Top: 20, Leading: 0, Trailing: 0, Bottom: 20
    

    将堆栈视图的Alignment设置为Fill:

    在这里插入图片描述
    您需要在“隐藏”按钮的左边缘和“ WEATHER”标签的右边缘之间有一个约束,因此让“ WEATHER”标签填充堆栈视图将不起作用。

    但是,您确实希望底部的< weatherInfoLabel>填充堆栈视图。

    您可以通过仅将WEATHER标签嵌入到垂直堆栈视图中来完成此操作。请记住,alignment可以将垂直堆栈视图的设置为.leading,并且如果将堆栈视图拉伸到其固有宽度之外,则其子视图将保持与前端对齐。

    使用文档大纲或使用Control-Shift-click方法选择“天气”标签。然后,将其嵌入到新的堆栈视图中。

    将Alignment设置为Leading,并确保Axis设置为Vertical:
    在这里插入图片描述
    完善!外部堆栈视图正在拉伸内部堆栈视图以填充宽度,但是内部堆栈视图允许标签保持其原始宽度!

    生成并运行。哦哦 为什么“隐藏”按钮在文本中间挂出?
    在这里插入图片描述
    将WEATHER标签嵌入堆栈视图时,该标签和“隐藏”按钮之间的所有约束均被删除。

    要添加新的约束,请按住Control键并将“ Hide”按钮拖动到WEATHER标签。

    按住Shift键选择多个选项,然后选择“水平间距”和“第一基线”。然后按Enter,或在弹出视图之外的任何位置单击:
    在这里插入图片描述
    生成并运行。现在应正确放置“隐藏”按钮。由于设置为隐藏的标签嵌入在堆栈视图中,因此按“隐藏”可隐藏标签并调整其下方的视图-所有这些都无需手动调整任何约束。
    在这里插入图片描述

    在这里插入图片描述现在,所有部分都位于唯一的堆栈视图中,您可以将它们嵌入到外部堆栈视图中,这将使最后两个任务变得微不足道。

    顶层堆栈视图

    单击命令以在大纲视图中选择所有五个顶级堆栈视图。

    然后将它们全部嵌入一个Stack View中:
    在这里插入图片描述
    单击“添加新约束”按钮,选中“约束到边距”,并将约束0添加到所有边。然后将Spacing设置为20并将Alignment设置为Fill。现在,故事板场景应如下所示:
    在这里插入图片描述
    构建并运行:

    在这里插入图片描述哎呀!当将WEATHER堆栈视图嵌入到外部堆栈视图中时,似乎hide按钮再次失去了约束。没问题,只需以与以前相同的方式再次向其添加约束:

    • 按住Control键并将其从“隐藏”按钮拖动到WEATHER标签。
    • 按住Shift键。
    • 选择水平间距和基线。
    • 按Enter,或在弹出视图之外的任何位置单击。

    生成并运行。该隐藏按钮现在是在正确的位置。

    重新定位视图

    现在所有的部分都在顶层堆栈视图中,您将修改的位置看什么部分,因此,它的上面天气部分。

    从大纲视图中选择中间堆栈视图,然后将其拖动到第一视图和第二视图之间。

    注意:将指针保持在您要在其间拖动的堆栈视图的左侧,使其仍然是外部堆栈视图的子视图。蓝色小圆圈应该在两个堆栈视图之间的左侧,而不是右侧:

    在这里插入图片描述

    尺寸等级配置

    最后,将注意力转移到列表上剩下的一项任务上。在横向模式下,垂直空间非常宝贵,因此您希望将堆栈视图的各个部分放在一起。为此,您将使用大小类将顶级堆栈视图的间距设置为10,而不是垂直大小类为紧凑时的20。

    选择顶层堆栈视图,然后在“属性”检查器中,单击“间距”旁边的+按钮:
    在这里插入图片描述
    选择“任意宽度”和“紧凑高度”,然后选择“添加变化”。
    在这里插入图片描述
    在新的hC字段中将Spacing设置为10:
    在这里插入图片描述
    生成并运行。纵向模式下的间距应保持不变。旋转模拟器,并注意各部分之间的间距已减小,并且按钮现在从视图底部开始有足够的空间:
    在这里插入图片描述
    如果没有添加顶层堆栈视图,您仍然可以使用大小类将分隔五个部分的四个约束中的每个约束的垂直间距设置为10,但设置起来不是更好吗?在一个地方?

    与时间相关的是更好的事情,例如动画!

    动画

    当前,该应用在隐藏和显示天气详细信息时非常跳动。您将添加一些动画来平滑过渡。

    堆栈视图与UIView动画引擎兼容。这意味着对已布置的子视图的出现或消失进行动画处理就像isHidden在动画块内切换其属性一样简单。

    更改isHidden已安排子视图的属性将更新其父堆栈视图的布局。如果该更新是在动画块中进行的,则如果您在动画块中自己更改了布局,则将是相同的。

    现在该写一些代码了!打开SpotInfoViewController.swift并查看updateWeatherInfoViews(hideWeatherInfo:animated:)。

    您将在方法末尾看到这些行:

    weatherHideOrShowButton.setTitle(newButtonTitle, for: .normal)
    weatherInfoLabel.hidden = shouldHideWeatherInfo
    

    将它们替换为以下内容:

    if animated {
      UIView.animate(withDuration: 0.3) {
        self.weatherHideOrShowButton.setTitle(newButtonTitle, for: .normal)
        self.weatherInfoLabel.isHidden = shouldHideWeatherInfo
      }
    } else {
      weatherHideOrShowButton.setTitle(newButtonTitle, for: .normal)
      weatherInfoLabel.isHidden = shouldHideWeatherInfo
    }
    

    生成并运行,然后点击“隐藏”或“显示”按钮。动画版本不会更好吗?

    除了在动画视图隐藏属性堆栈视图中包含的,你也可以在栈动画性能视图本身,比如alignment,distribution,spacing甚至axis。

    然后去哪儿?

    您可以使用本教程顶部或底部的“下载材料”按钮下载项目的完整版本。以下是一些需要进一步研究的资源:

    参考

    https://www.raywenderlich.com/2198310-uistackview-tutorial-for-ios-introducing-stack-views

    展开全文
  • Android后台任务

    2020-05-17 14:21:44
    简介 每个 Android 应用都有一个主线程,负责处理界面...在用户与应用积极互动时,可能需要执行几项这样的任务。 后台处理的挑战 后台任务会使用设备的有限资源,例如 RAM 和电池电量。如果处理不当,可能会导致用户体
  • 反射API的使用 反射通常被用在需要检查或修改其他运行在JVM中的程序的运行时行为的程序中。...请牢记这个忠告,反射是一种强大的技术,它使得程序可以完成用其他手段不可能完成的任务。 可扩展性程序
  • 算法简介

    2019-10-02 20:51:50
    算法 算法(Algorithm)是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法...不同的算法可能用不同的时间、空间或效率来完成同样的任务。一个算法的优劣可以用空间复杂度与时间复杂度来衡量...
  • Git简介

    2019-06-08 23:03:00
    一、Git 简史   二、Git的官网  官网地址:https://git-scm.com/ 三、Git 的优势   大部分操作在本地完成需要联网 ...  尽可能添加数据而不是删除或修改数据 ... 代码托管中心的任务:维护远...
  • Python 协程简介

    2020-04-26 23:50:34
    当我们要完成一个简单的任务的时候,我们通常就是按照事件的先后顺序按照过程编程,同头到尾程序逐行执行,当我们需要实现的功能越复杂对性能要求越高时我们开始慢慢引入了多线程、多进程、协程等概念,多线程和多...
  • Git 简介

    2019-10-19 15:15:31
    (1)大部分操作在本地完成需要联网 (2)完整性保证(Hash值验证) (3)尽可能添加数据而不是删除或修改数据 (4)分支操作非常快捷流畅 (5)与 Linux 命令全面兼容 3.4Git 结构 3.5Git 和代码托管中心 (1...
  • 简介 ...大家完成的时间,完成的进度都是相同的,你写一点我写一点,甚至可能你今天写的出现了错误,影响到了我昨天写的代码,最后怎么才能将大家的代码轻松的汇总起来,又怎么在汇总所有人的代码...
  • OSI七层模型简介

    2019-05-12 21:11:00
    OSI是定义良好的协议规范,并由许多可选部分完成类似的任务,它定义了开放系统的层次结构, 层次之间的相互关系以及各层包括的可能的任务,是作为一个框架协调和组织各层所提供的服务, 但是OSI参考模型并没有提供...
  • Oozie-简介及部署

    2019-01-20 13:05:32
    现实业务中处理数据时不可能只包含一个MR操作,一般都是多个MR,并且中间还可能包含多个Java或HDFS,甚至是shell操作,利用Oozie可以完成这些任务。 实际上Oozie不是仅用来配置多个MR工作流,它可以是各种程序...
  • 我们将性能定义为完成某种任务所需要时间度量。 换句话说,性能即响应时间,我们通过任务和时间而不是资源来测量性能。 数据库服务器目的是执行SQL语句,所以它关注是查询或者语句,数据库服务器性能用查询...
  • 基础算法简介

    2020-08-21 18:51:24
    不同的算法可能用不同的时间、空间或效率来完成同样的任务。一个算法的优劣可以用空间复杂度与时间复杂度来衡量。 特性 输入: 算法具有0个或多个输入 输出: 算法至少有1个或多个输出 有穷性: 算法在有限的步骤之后会...
  • 具有Cats-EffectScala中并发 本文基于库,介绍了Scala中并发异步效果主题。 但是,这里介绍许多概念不仅适用于其他Scala...同步:线程通过成功或失败来完成任务,然后再执行之后任何任务。 异步:线程启动某
  • Google OR-Tools简介

    千次阅读 2019-07-05 16:05:45
    一、车辆路线:为在给定限制条件下提取和交付包裹的车队找到最佳路线(例如,“此卡车能承载超过20000磅”或“所有交付必须在两小时内完成”)。 二、调度:为一组复杂的任务找到最佳的调度,其中一些任务需要先...
  • java代码优化简介

    2011-08-22 17:43:03
    可供程序利用的资源(内存、CPU时间、网络带宽等)是有限的,优化的目的就是让程序用尽可能少的资源完成预定的任务。优化通常包含两方面的内容:减小代码的体积,提高代码的运行效率。本文讨论的主要是如何提高代码...
  • OSI是一个定义良好的协议规范集,并有许多可选部分完成类似的任务。它定义了开放系统的层次结构、层次之间的相互关系以及各层所包括的可能的任务,作为一个框架来协调和组织各层所提供的服务。 OSI参考模型并没有...
  • 转载自:http://www.ibm.com/developerworks/cn/opensource/os-refactoringphp/index.html 简介 回顾 PHP 15 年的发展历程... 随着代码库的增长,手动测试已经变成不可能完成的任务,无论是大是小,所有代码的变化...
  • 我们不可能就盯着程序,等它运行完再去运行下一个程序,所以,一般做法就是通过shell来做,但是如果涉及到工作流很复杂(比方说有1,2,3,4四个作业,1输出作为2 3 4输入,然后2 3结果运算之后再和...
  • 让我们假装现在要完成一个任务:尽可能按照函数式语言原则来写JavaScript代码。 接下来一系列文章就是为了让你们和我一起开始这样一段旅程。首先,我们需要纠正一些你们脑子中可能对函数式语言错误概念。 JS...
  • 算法 是解决问题的一种具体,清晰的描述,是程序解决问题的清楚指令。...不同的算法可能用不同的时间、空间或效率来完成同样的任务。 一个算法的优劣可以用空间复杂度与时间复杂度来衡量。 数据结构 数据结...
  • 34-C++-结构简介

    2018-06-09 17:30:43
    数组完成这项任务,因为虽然数组可以存储多个元素,但所有元素类型必须相同。也就是说,一个数组可以存储20个int,另一个数组可以存储10个float,但同一个数组能在一些元素中存储int,在另一些元素中存储...

空空如也

空空如也

1 2 3 4 5 ... 17
收藏数 327
精华内容 130
关键字:

不可能完成的任务简介