极客大学产品经理训练营 解决方案的设计与积累 第 6 课总结 John 易筋 ARTS 打卡 Week 37
1. Algorithm: 每周至少做一个 LeetCode 的算法题
笔者的文章:
算法:合并两个有序链表21. Merge Two Sorted Lists
LeetCode 全集请参考:LeetCode Github 大全
题目
Merge two sorted linked lists and return it as a sorted list. The list should be made by splicing together the nodes of the first two lists.
Example 1:
Example 2:
Example 3:
Constraints:
递归解法,机器思考方式
倒序拼接,把最大的结果链表先返回,然后逐个拼接次大的。
遍历思维
创建一个结果链表 result;
依次对比链表 l1, l2,把小的 node 加入结果中,并指向下一个;
记得首尾:把还不为空的链表加入到结果链表的尾部;
开始的时候,可以检查边界,直接退出、
2. Review: 阅读并点评至少一篇英文技术文章
笔者的文章:
翻译:swift 5 iOS的UIStackView教程:堆栈视图简介
说明
更新说明:Ehab Amer 已针对 Swift 5,iOS 12 和 Xcode 10 更新了本教程。Jawwad Ahmad 撰写了原文。
您是否曾经需要在运行时期间从视图中添加视图或从视图中删除视图,并调整视图旁边的视图布局?也许您调整了一些约束或使用了第三方库来完成这项工作。也许不是在运行时运行,而是您想在情节提要中的其他视图之间添加一个新视图。
在这些情况下,您需要更改几个约束。您可能会发现自己删除了该区域中的所有约束,然后又重新添加了它们。
UIStackView 简化了此类任务。您可以轻松地在堆栈视图中水平或垂直放置一系列视图,并通过对齐,分布和间距等属性将视图自动调整为可用空间的方式进行设置。请享用!:]
注意:本教程假定您基本熟悉自动版式。如果您不熟悉自动版式,请查看“AutoLayout开始自动版式”视频教程。
入门
首先使用本教程下载项目材料。使用 iPhone 8 Simulator 在 Xcode 中构建并运行 starter 项目。您会看到以下内容:
这是假期景点应用程序。它提出了一个摆脱一切的地方清单。在前往任何地方之前,您将使用 Stack Views 解决该应用程序的一些问题。
探索度假胜地
去伦敦的信息视图通过点击伦敦。乍一看,该视图可能看起来不错,但存在一些问题:
查看视图底部的按钮行。由于它们之间的间距固定,因此它们无法适应屏幕宽度。为了更好地解决问题,请按 Command-左箭头将模拟器旋转为横向。
点击“天气”旁边的“隐藏”。这将隐藏文本,但不会重新定位其下面的部分,而是留出一块空白。
节订购需要改进。这将是更符合逻辑的,如果看到什么后出现为什么参观定位它们之间的天气部分代替。
在横向模式下,按钮的底行太靠近视图的底部边缘。如果减小各部分之间的间距,则效果会更好-但仅在横向模式下。
既然您已经知道将要进行的改进,那么现在该深入研究该项目了。打开Main.storyboard
。它将以初始设备视图打开。确保将 iPhone 8 显示为所选设备。
这在运行时没有影响,但可以帮助您查看屏幕在该设备上的外观。您可以随时单击另一个图标来更改所选设备。将鼠标悬停在图标上可以显示其相应的设备。
注意:如果减小 Interface Builder 的画布宽度(大约小于 650 像素),则用于更改设备的 UI 会稍有变化。设备列表折叠到设备下拉列表中:
当按下时,将显示垂直排列的可用设备列表:
现在,仔细查看 Spot Info View Controller:
您可能想知道颜色是什么?
这些标签和按钮的背景色在运行时不会显示。在情节提要中,它们是视觉辅助工具,有助于显示更改堆栈视图的各种属性如何影响其嵌入式视图的框架。
如果您希望在运行应用程序时随时查看背景颜色,则可以暂时将 viewDidLoad()里面的以下行注释掉 SpotInfoViewController。
任何与插座连接的标签均具有与插座变量名称匹配的占位符文本。这样可以更轻松地确定在运行时将更新哪些标签的文本。例如,带有文本< whyVisitLabel>的标签连接到:
是时候开始了!
您的第一个堆栈视图
首先,您将固定底部一行按钮之间的间距。堆栈视图可以通过各种方式沿其轴分布其子视图。一种方法是在每个视图之间设置相等的间距。
幸运的是,将现有视图嵌入到新的堆栈视图中可谓小菜一碟。首先,通过单击一个,然后在其他两个上单击命令,选择“ Spot Info View Controller”场景底部的所有按钮。使用情节提要画布左下角的“显示文档大纲”按钮打开大纲视图。
确认您已选择所有三个按钮。
它们在大纲视图中突出显示。您也可以在大纲视图中单击命令的每个按钮以选择它们。
选择后,在情节提要画布右下角的“自动布局”工具栏中单击“嵌入”按钮。出现带有可用嵌入选项的菜单。选择堆栈视图:
Xcode 将为您将按钮嵌入新的堆栈视图中。
堆栈视图约束
尽管堆栈视图负责放置按钮,但是您仍然需要添加自动布局约束来定位堆栈视图本身。
当您将视图嵌入堆栈视图时,它将失去对其他视图的约束。例如,在将按钮嵌入到堆栈视图中之前,“提交评分”按钮的顶部与 RATING 标签的底部之间存在垂直间距约束:
选择“提交评分”按钮,并验证它不再具有任何约束:
您还可以查看大小检查器(Option-Command-5)以验证是否没有约束:
有时很难在拥挤的情节提要的视图控制器中选择特定元素。您可以从大纲视图中选择元素,或使用 Shift 并在要选择的视图上单击鼠标右键或按住 Control 键并按住 Shift 键单击。这为您提供了一个上下文菜单,该菜单显示了单击位置的视图层次结构。通过在菜单中单击选择堆栈视图。
既然已经选择了“堆栈视图”,则可以向其添加约束。
单击自动版式工具栏中的“添加新约束”按钮以显示“添加新约束”弹出窗口。
首先,在 Constrain to margins 上添加一个选中标记。然后,将以下约束添加到堆栈视图的边缘:
仔细检查顶部,顶部,底部和底部约束的数字。确保您已打开四个红色工字梁并限制到边距。然后,点击添加 4 个约束。
现在,堆栈视图的大小正确,但是它拉长了第一个按钮以填充任何额外的空间。
堆栈视图外观
确定堆栈视图如何沿其轴布置其子视图的属性为 distribution。当前,它设置为 Fill,这意味着子视图将沿其轴完全填充堆栈视图。为此,堆栈视图将仅扩展其子视图之一以填充该额外空间。具体来说,它会以拥有最低优先级的水平内容来扩展视图,或者如果所有优先级都相等,则会扩展第一个视图。
但是,您不希望按钮完全充满堆栈视图,而是希望它们之间的间距相等。
确保堆栈视图仍处于选中状态,然后转到“属性”检查器。更改分配从填充到间距相等:
现在构建并运行,点击任意一个单元,然后旋转模拟器。您会看到底部按钮现在的间距相等!
实施 UI 时,请始终问自己元素是否适合可用空间。
这是您的内容如何影响用户体验的示例:将 Wikipedia 按钮的标题更改为 Wikipedia 网站并运行该应用程序。将模拟器从纵向旋转到横向以查看差异。
在空间较窄的纵向模式下,最后一个按钮中的文本会被剪切,而在横向模式下,所有内容都适合。
这是您经常遇到的事情,尤其是在 iPhone SE 等较窄的屏幕尺寸上。
幸运的是,这很容易解决。在仍然选择堆栈视图的情况下,返回 Attributes inspector。将分布从等间距更改为按比例填充,并将间距值更改为 10:
现在,构建并运行并检查两个方向。您会按顺序找到所有内容。
将按钮的名称更改回 Wikipedia。
恭喜,您已经建立了第一个堆栈视图!
没有堆栈视图
为了在没有堆栈视图的情况下解决此间距问题,您将必须在每对按钮之间使用一个间隔视图,向所有间隔视图添加相等的宽度约束,以及几个其他约束以正确放置间隔视图。
这看起来类似于以下内容。为了在屏幕截图中可见,间隔视图显示浅灰色背景:
如果您必须在情节提要中执行一次操作并不太麻烦,但是许多视图是动态的。由于相邻的间隔视图和约束,在运行时添加新按钮或隐藏或删除现有按钮不是一项简单的任务。
为了在堆栈视图中隐藏视图,请将包含的视图的 hidden 属性设置为 true,然后堆栈视图将处理其余视图。这是当用户将文本隐藏在 WEATHER 标签下时固定其间距的方法。将天气部分标签添加到堆栈视图后,即可在本教程中进行操作。
注意:现在您知道如何在堆栈中指定子视图之间的间隔。但是,如果您想要在特定子视图后使用不同的间距怎么办?从 iOS 11 开始,您可以使用setCustomSpacing:afterView进行此操作。
转换节
接下来,您将转换所有其他部分 SpotInfoViewController 以使用堆栈视图。这使您能够完成其余任务。从评分部分开始。
转换评级部分
在您创建的堆栈视图上方,选择“评分”标签和旁边的星号标签。
然后,单击编辑器▸嵌入▸堆栈视图中。
现在,选择新创建的堆栈视图,然后再次单击“添加新约束”按钮。在约束到边距中打勾,并添加以下三个约束:
现在转到“属性”检查器并将间距设置为 8。
注意:您可能已经注意到,间距已经设置为 8。以前,间距自动设置为 24。Xcode 变得足够聪明,可以推断出间距值以匹配嵌入视图之前的值。很酷吧?
生成并运行以验证所有内容与以前相同。
取消嵌入堆栈视图
在您走得太远之前,最好先进行一些急救培训,以防出现问题。例如,您可能会因为实验,重构或偶然而发现自己拥有额外的堆栈视图。
幸运的是,有一种简单的方法可以从堆栈视图中取消嵌入视图。
首先,选择要删除的堆栈视图。单击嵌入按钮。接下来,在出现的上下文菜单上选择“未嵌入”:
执行此操作的另一种方法是选择堆栈视图,然后从菜单中选择“编辑器”▸“未嵌入”。
创建垂直堆栈视图
现在,创建您的第一个垂直堆栈视图。选择“为什么访问”标签及其下方的<whyVisitLabel>,然后选择“嵌入在▸堆栈视图中”。
当您将标签嵌入堆栈视图中时,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 标签也扩展到右边缘。
如果您只希望底部标签扩展到边缘怎么办?
目前,这并不重要,因为两个标签在运行时都具有清晰的背景,但是在转换天气部分时将很重要。
您将学习如何使用附加的堆栈视图来实现这一点
转换看什么部分
转换此部分与您已经完成的操作类似。
首先,选择要查看的标签,然后选择其下方的< whatToSeeLabel>。
单击“嵌入”按钮,然后选择“堆栈视图”。
单击固定按钮。
选中约束到边距并添加以下四个约束:
将堆栈视图的 Alignment 设置为 Fill。
现在,您的情节提要板应如下所示:
这使您仅剩下天气部分。
转换天气部分
由于“隐藏”按钮,天气部分比其他部分更为复杂。
要转换天气部分,您可以通过将 WEATHER 标签和 Hide 按钮嵌入水平堆栈视图中来创建嵌套堆栈视图。然后,将该水平堆栈视图和< weatherInfoLabel>嵌入到垂直堆栈视图中。
它看起来像这样:
请注意,“天气”标签已扩展为等于“隐藏”按钮的高度。这将在 WEATHER 标签的基线与其下方的文本之间留出额外的空间。
请记住,它 alignment 指定垂直于堆栈视图的位置。因此,您可以将设置 alignment 为 Bottom:
但是,您不希望“隐藏”按钮的高度决定堆栈视图的高度。
相反,您将从所有堆栈视图中删除“隐藏”按钮。
“隐藏”按钮将保留在顶层视图的子视图中,您将向其添加约束到 WEATHER 标签中-该标签将在堆栈视图中。没错,您将从堆栈视图外部的按钮向堆栈视图内的标签添加约束!
选择 WEATHER 标签并在其下方选择< weatherInfoLabel>,然后将它们堆叠在 Stack View 中。
单击添加新约束按钮,选中约束到边距并添加以下四个约束:
将堆栈视图的 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:)。
您将在方法末尾看到这些行:
将它们替换为以下内容:
生成并运行,然后点击“隐藏”或“显示”按钮。动画版本不会更好吗?
除了在动画视图隐藏属性堆栈视图中包含的,你也可以在栈动画性能视图本身,比如 alignment,distribution,spacing 甚至 axis。
然后去哪儿?
您可以使用本教程顶部或底部的“下载材料”按钮下载项目的完整版本。以下是一些需要进一步研究的资源:
有关自动布局和使用的主题,有几个 WWDC 视频 UIStackViews。WWDC 2017的Interface Builder中的自动布局技术是一个很好的起点。
您还可以UIStackView从Apple文档中了解更多信息。
参考
https://www.raywenderlich.com/2198310-uistackview-tutorial-for-ios-introducing-stack-views
3. Tips: 学习至少一个技术技巧
笔者的文章:
问题
git 或者 CocoaPods 拉取依赖的时候,多次需要输入用户名密码。
Mac OS 版本 Catalina 10.15
解决
创建文件 ~/.ssh/config
, 写入下面的配置,解决。
参考
https://stackoverflow.com/questions/7773181/git-keeps-prompting-me-for-a-password
4. Share: 分享一篇有观点和思考的技术文章
笔者的文章:
说明
讲师:邱岳(二爷)
1. 解决方案
解决方案的前提是明确了 利益相关者 和 待解决的问题
出解决方案是产品经理的天职,不要直接转发
注意 X-Y Problem,核心关注 X
大量的练习/模仿/储备,然后跳出框架
解决方案不要局限于【功能】
1.1 非功能解决方案
飞机值机机器,刷身份证取登机牌,用户经常会漏了身份证。很多产品,就是添加提醒页面,加声音等流程,但是效果不佳。
更好的解决方案是,把刷身份证做成垂直的,手不能离开。
能不能靠文案解决问题?
招聘网站推广,用【高薪职位】或者【高端职位】等。
能不能靠规则/制度解决问题?
比如微博为了限制语言攻击,限制粉丝在 30 天能不能留言。
比如阿里巴巴为了制约黑产获取红包等,限制新用户 30 天内不能领红包等。
能不能靠商业手段解决问题?
比如直播带货,退货成本比较高。有的时候,直接卖二手卖掉就好。
1.2 在解决方案开始之前:目标指标化
卫哲的 3+1
3:需求是从哪里来的?目标客户是谁? // 有多少人有这样的需求?这个需求紧迫吗?// 他们的痛是什么?场景是什么?(用产品之前/之后)
1:解决之后再数据上会有什么表现?
Numbers lend an air of legitimacy (合法性) and credibility (可靠性).
比如微信公众号显示,粉丝数,阅读数,赞赏等。
拆解宏观商业目标,分解为特性设计的微观目标。
* 指标是对业务的理解,不是标准字典、指标是结果的展现,而不是操作的抓手。
思考:在当前直播页面上的目标应该是什么?
在线人数,互动量,互动率,完成率,毕业率。
1.3 理解功能性解决方案的逻辑:交互框架
翻译网页举例:
用户一进来,会有个光标,暗示用户输入的位置;
输入文字以后,就提示【翻译文档】,告诉用户翻译是自动进行的;
翻译的语言,可以选择输入输出的语言;
系统处理与一些异常,比如提示别的的翻译
右上角使用 Pro 版本推荐
2. 用户的心智模型
产品经理,理解用户的心智模型
产品经理 设计模型
实现系统表现,匹配用户的心智模型
3. 设计步骤
信息架构 & 概念模型:概念与关系
描述用户心智模型:名词与关系
通过界面信息引导用户心智模型建立
罗列筛选所有信息元素与数据,确定信息元素与数据的级别
设计界面架构与用户动线,承接用户动作
3.1 如果我们设计一个代替钉钉的训练营界面?
概念与关系:课程(训练营/课程)?教室?讲师?日程?班主任?助教?同学?作业?留言(问题/回答)?
怎样表达课程和作业的关系?比如:Tree View?有更好的吗?报名若干课程呢?
训练营:题目/时间/价格/学员数量/评分...... 什么关系?强调哪个?
动作:订购?回看?交作业?......强调哪个?什么动作?
点击训练营标题,你觉得回去哪里?点击老师的头像,你觉得回去哪里?
4. 功能设计的若干原则
抽象与隐喻
产品经理抽象系统模型,符合用户的心智模型。
统一可预期
比如下拉刷新,tab 有红点表示有信息
带着出离心做功能设计
做的过程当中,要想着未来可能会下掉。功能和数据的关停和调整空间。
控制与控制感
比如网络断了显示一个重连,或者网络加速。(实际上已经在重连了,不点也可以)。
比如欧洲有些电梯关闭按钮是没用的,点和没点都是按时关的。
* 永远惦记新人视角
* KISS (Keep It Simple Stupid)
* 做一个靠谱的产品经理
数据迁移/客户通知/客户服务培训
5. 方案设计工具箱
借鉴是最好的解决方案积累方式(不是抄袭)。
二爷常去的站点列表
Product Hunt ; Dribbble ; Hacker News | show ; Quora ; Lauching Next ; Betabound ; Betalist ; Slideshare ; Google ; 36Kr ; TechCrunch ; Techmeme...
宝典:HIG(Human Interface Guideline)
产品经理的学产品方式:猜 → 画 → 用 → 复刻 → remix (再搅和) → 总结 → 再 remix
从游戏中学解决方案
6. 跟大家一起,从 Medium 开始......
搜索关键词: product design
阅读并记录笔记,后续再根据子主题继续研究。
推荐书
《设计心理学》-- 唐·诺曼
《文案训练手册》
版权声明: 本文为 InfoQ 作者【John(易筋)】的原创文章。
原文链接:【http://xie.infoq.cn/article/f27ccdeb587341460db83290d】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论