ios官方菜单项目重点剖析附项目源码
项目知识重点:
1,使用堆栈视图实现自动布局。
2,自定义控件的创建与使用。
3,调用手机系统图片库。
开发环境:工具:Xcode8.2测试版,语言:swift3.0.1(由于环境原因,流程略微不同)
一,项目功能介绍及预览
主体功能:对一个菜单列表进行展示,删除,修改,添加操作
界面预览:


二,自定义控件
我们创建工程后先将我们的新增页面构建好,从预览图中可以看出是由一个导航条,文本框,和一个图片视图,还有五颗星构成。相信前几个控件都没什么问题,关键在于这个自定义控件。
我们都知道每一个控件都是会默认关联一个类的,所以:我们这个五角星评价控件(下文称rating)如出一辙的需要关联一个自定义的类。
//
// RatingControl.swift
// Food
//
// Created by C02 on 2016/12/14.
// Copyright © 2016年 Aida. All rights reserved.
// import UIKit /*
自定义星级评价控件
*/
class RatingControl: UIView { let spacing = //星星间距
let ratingCount = //星星个数
var filledArr = [UIButton]()//filled星星数组
var rating = {
didSet{
setNeedsLayout()
}
} required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder) for _ in ..<ratingCount{
let btn = UIButton()
btn.setImage(UIImage(named:"empty"), for: .normal)
btn.setImage(UIImage(named: "filled"), for: .selected)
btn.setImage(UIImage(named: "filled"), for: [.highlighted,.selected])
btn.adjustsImageWhenHighlighted = false
//控件单击事件
btn.addTarget(self, action: #selector(RatingControl.ratingClicked(sender:)), for:.touchDown)
filledArr += [btn]
self.addSubview(btn)
}
} func ratingClicked(sender:UIButton){
rating = filledArr.index(of: sender)! +
updateBtnStar()
} func updateBtnStar(){
for(index,btn) in filledArr.enumerated(){
btn.isSelected = index < rating
}
} override func layoutSubviews() {
let size = Int(self.frame.height)
for (index,btn) in filledArr.enumerated() {
btn.frame = CGRect(x: index * (size + spacing), y: , width: size, height: size)
}
updateBtnStar()
} //返回此控件大小
override var intrinsicContentSize: CGSize {
//控件默认高度44
let ratingHeight = Int(self.frame.height)
//控件宽度=星星数*(控件高度+间距)
let ratingWidth = ratingCount*(ratingHeight+spacing)
return CGSize(width: ratingWidth, height: ratingHeight)
} }
三,使用自定义控件

解析:在我们的视图控制器中加入文本框和图片后,再添加一个view视图,然后将这个view关联我们上一步定义的RatingControl类。

此时运行模拟器,便可以看到我们的rating控件,大小与位置我们稍后再做调整。
四,使用堆栈视图实现自动布局。
我们都知道我们的应用可能会运行在不同分辨率,不同尺寸,横屏,竖屏等状态下,所以布局自然不能一成不变。
1,选中三个控件->Xcode工具栏Editor->Embed In->StakeView将其嵌入到堆栈视图中,或者使用视图下方的快捷工具。
2,添加合适的约束
我们要将我们的控件在各种情况下都可以得到正常的显示,可以将整个视图分割成若干个子视图,把子视图位置调整好。同理,一种层层处理方式再继续调整每一个控件。
显而易见,本例中我们先需要将栈调整。

选中StackView首先对上左右三个方向进行约束,但是此时并不能确定StackView的高度,在确定StackView中每一个控件的高度后,自然这个栈的所有约束也就完成了。
注意:在我们的ImageView和Rating控件需要固定大小需要如此设置
为了有良好的交互性,因此我们这里设置了一个默认的图片,以及控件之间的间距。
五,调用手机系统图库及配置手势操作
在新增项的时候我们需要通过点击视图中的默认图片添加一个手机图库中的图片。
注意:此时我们需要拖入一个UITapGestureRecognizer控件在ImageView上,要让点击有效此时必须启用用户交互,如图所示。

接下来就是将这个控件关联到我们的代码中
//
// ViewController.swift
// Food
//
// Created by Aida on 2016/12/14.
// Copyright © 2016年 Aida. All rights reserved.
// import UIKit class ViewController: UIViewController ,UITextFieldDelegate,UIImagePickerControllerDelegate,UINavigationControllerDelegate{ @IBOutlet weak var nameText: UITextField! @IBOutlet weak var photoImg: UIImageView! @IBOutlet weak var ratingControl: RatingControl!
@IBOutlet weak var saveOutlet: UIBarButtonItem! var meal:Meal?
override func viewDidLoad() {
super.viewDidLoad()
self.nameText.delegate = self } override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
} //MARK: 手势识别方法
@IBAction func selectPhoto(_ sender: UITapGestureRecognizer) {
let imagePickerController = UIImagePickerController() imagePickerController.sourceType = .photoLibrary imagePickerController.delegate = self present(imagePickerController, animated: true, completion: nil)
} //图片选择之前取消事件
func imagePickerControllerDidCancel(_ picker: UIImagePickerController){ dismiss(animated: true, completion: nil)
} //选中图片事件
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]){ let selectedImage = info[UIImagePickerControllerOriginalImage] as! UIImage // Set photoImageView to display the selected image.
photoImg.image = selectedImage // Dismiss the picker.
dismiss(animated: true, completion: nil)
}
用户授权:由于应用要使用手机图库需要经过授权,因此需要在项目的info.plist文件中配置相关字段。
<key>Privacy - Photo Library Usage Description</key><string>您允许我们访问相册吗</string>

小结:到这一步,这个小项目的几个重点就介绍完了。有任何问题可以联系:QQ:1016882435.
另附项目完整源码:https://pan.baidu.com/s/1boDcwgB 密码:acsy
ios官方菜单项目重点剖析附项目源码的更多相关文章
- Spring3 + Spring MVC+ Mybatis 3+Mysql 项目整合(注解及源码)
Spring3 + Spring MVC+ Mybatis 3+Mysql 项目整合(注解及源码) 备注: 之前在Spring3 + Spring MVC+ Mybatis 3+Mysql 项目整合中 ...
- winserver的consul部署实践与.net core客户端使用(附demo源码)
winserver的consul部署实践与.net core客户端使用(附demo源码) 前言 随着微服务兴起,服务的管理显得极其重要.都知道微服务就是”拆“,把臃肿的单块应用,拆分成多个轻量级的 ...
- 基于tomcat插件的maven多模块工程热部署(附插件源码)
内容属原创,转载请注明出处 写在前面的话 最近一直比较纠结,归根结底在于工程的模块化拆分.以前也干过这事,但是一直对以前的结果不满意,这会重操旧业,希望搞出个自己满意的结果. 之前有什么不满意的呢? ...
- 嗨,让我带你逐行剖析Vue.js源码
本项目受到了阮一峰老师的肯定,已刊登在阮一峰老师微信公众号的科技爱好者周刊第87期,同时也被多个微博大V转发,短短一个月时间内在github上star数量就已经突破2k! Hello,大家好,我最近在 ...
- Spring Boot整合ElasticSearch和Mysql 附案例源码
导读 前二天,写了一篇ElasticSearch7.8.1从入门到精通的(点我直达),但是还没有整合到SpringBoot中,下面演示将ElasticSearch和mysql整合到Spring Boo ...
- 转:【Java集合源码剖析】HashMap源码剖析
转载请注明出处:http://blog.csdn.net/ns_code/article/details/36034955 您好,我正在参加CSDN博文大赛,如果您喜欢我的文章,希望您能帮我投一票 ...
- 【Java集合源码剖析】HashMap源码剖析
转载出处:http://blog.csdn.net/ns_code/article/details/36034955 HashMap简介 HashMap是基于哈希表实现的,每一个元素是一个key-va ...
- 单独编译和使用webrtc音频回声消除模块(附完整源码+测试音频文件)
单独编译和使用webrtc音频降噪模块(附完整源码+测试音频文件) 单独编译和使用webrtc音频增益模块(附完整源码+测试音频文件) 说实话很不想写这篇文章,因为这和我一贯推崇的最好全部编译并使用w ...
- 在WebBrowser中执行javascript脚本的几种方法整理(execScript/InvokeScript/NavigateScript) 附完整源码
[实例简介] 涵盖了几种常用的 webBrowser执行javascript的方法,详见示例截图以及代码 [实例截图] [核心代码] execScript方式: 1 2 3 4 5 6 7 8 9 1 ...
随机推荐
- 最快让你上手ReactiveCocoa之基础篇
前言 很多blog都说ReactiveCocoa好用,然后各种秀自己如何灵活运用ReactiveCocoa,但是感觉真正缺少的是一篇如何学习ReactiveCocoa的文章,这里介绍一下. 1.Rea ...
- 使用gulp解决外部编辑器修改Eclipse文件延迟更新的问题
本人前端用惯了Hbuilder,修改了eclipse项目中的文件后,由于是外部编辑器修改过的,eclipse不会自动部署更新,一般按F5刷新项目,或者在 preferences > genera ...
- css实现网页表格
一. 准备工作 1. 点击此下载 相关文件 二. 在浏览器中运行 table.html 文件,即可看到效果 三. 效果图
- WPF 自定义滑动ScrollViewer
自定义滑动滚动条 预期目标:横向滚动条,可以左右滑动,用鼠标按住(触摸)然后释放可以实现快速滑动. 我们有几种方案: 1.ScrollViewer,修改其中的横向滚动条,将其中的背景设置为透明. 但是 ...
- webdriver学习笔记
该篇文章记录本人在学习及使用webdriver做自动化测试时遇到的各种问题及解决方式,问题比较杂乱.问题的解决方式来源五花八门,如有疑问请随时指正一遍改正. 1.WebDriver入门 //webdr ...
- 1597: [Usaco2008 Mar]土地购买
1597: [Usaco2008 Mar]土地购买 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 4023 Solved: 1470[Submit] ...
- [LeetCode] Integer to Roman 整数转化成罗马数字
Given an integer, convert it to a roman numeral. Input is guaranteed to be within the range from 1 t ...
- HTTP服务器(1)
单文件服务器 导语 在研究HTTP服务器时,我们可以从一个单文件服务器开始.无论接受到什么请求,这个服务器始终发送同一个文件.下面是示例代码,绑定的端口,发送的文件名以及文件的编码从命令行读取.如果省 ...
- javascript中的感叹号 "!"
JavaScript中会经常遇到一个操作符:! 这是一个布尔操作符,用于将操作的值强制转换为布尔值并取反.常用场景如下: //条件判断中使用 var a; var b=null; if(!a){ co ...
- mac 修改command+q 退出
实在受不了! 在chrome中command+w 是关闭当前页面,command+q 退出浏览器: 经常查阅资料打开了N多个窗口,关闭时不小心将command+q当command+w按: so ... ...
