iOS开源一个简单的订餐app UI框架_IOS

前言

学 Swift 也有一段时间了,做了一些小的 demo。一直想做个完整的项目,发现这边学校的外卖订餐也逐渐流行起来,不像中国有那么多强大的外卖软件,美国也有,但不多,起码中国人对那些软件都不太熟知也不怎么用。打算专门针对午餐的外卖做个app,做了几天,只做出个 UI,看上去很小的软件,新手做起来感觉东西还是有点多。 Swift 如何与后端交互 之类的之后再慢慢学吧,有数据库之类的我都挺熟悉,SQL 或者 MongoDB。

目录
在这个 app 中,所有 UI 都是用代码创建的,你可以在 100 Days of Swift 看到,我之前练习的时候都是用的 storyboard,但是到了10页以上感觉 storyboard 就开始有点乱了,特别是那些 segue 的线牵得满屏幕都是的时候。之后我就开始用 SnapKit 做 UI 了,虽然比起 CSS 来,还是有点不方便,但用起来感觉还行。下面我大概罗列了一些实现的基本功能:

引导页
午餐菜单(tableView)
购物车,动画
下拉刷新
自定义个人主页 (collectionView)
Reminder 和 Setting 需要后台,就用了 Alert 来简单响应了
全屏右滑退出

具体代码请看我的 Github, 下面我就主要展示一下效果,稍微讲一下实现过程,代码中已有很多注释。

引导页

引导页我是用 collectionView 做的,刚开始先判断要不要进入引导页,如果版本更新,则进入。collectionView 滑动方向设置为 .horizontal ,设置任意数量的页数。添加一个启动的 startButton ,设置前几页都为 startButton.isHidden = true ,最后一页的时候显示出来,再添加一个渐出的显示动画。

菜单和购物车

shoppingCart

菜单可以下拉刷新,本打算自定义下拉刷新,就像 ALin 的项目中那样,但是好像有点问题,我就用了自带的UIRefreshControl ,下拉的时候显示刷新的时间,稍微调整了下时间的 format。代码很简单

复制代码 代码如下:

let dateString = DateFormatter.localizedString(from: NSDate() as Date, dateStyle: .medium, timeStyle: .short)
self.refreshControl.attributedTitle = NSAttributedString(string: "Last updated on \(dateString)", attributes: attributes)
self.refreshControl.tintColor = UIColor.white

然后做了个购物车的动画,将菜单里的图片先放大后缩小“抛入”购物车,其实是沿着 UIBezierPath 走的一个路径,这段动画完了之后,在 animationDidStop() 里做购物车图片的抖动,和显示购买的物品数量,那个 countLabel 是个长宽都为 15 的在购物车图片右上角的 UILabel() 。

先实现一个回调方法,当点击了cell上的购买按钮后触发

func menuListCell(_ cell: MenuListCell, foodImageView: UIImageView)
 {
  guard let indexPath = tableView.indexPath(for: cell) else { return }

  // retrieve the current food model, add it to shopping cart model
  let model = foodArray[indexPath.section][indexPath.row]
  addFoodArray.append(model)
  // recalculate the frame of imageView, start animation
  var rect = tableView.rectForRow(at: indexPath)
  rect.origin.y -= tableView.contentOffset.y
  var headRect = foodImageView.frame
  headRect.origin.y = rect.origin.y + headRect.origin.y - 64
  startAnimation(headRect, foodImageView: foodImageView)
 }

这是点击购买之后的动画实现:

fileprivate func startAnimation(_ rect: CGRect, foodImageView: UIImageView)
 {
  if layer == nil {
   layer = CALayer()
   layer?.contents = foodImageView.layer.contents
   layer?.contentsGravity = kCAGravityResizeAspectFill
   layer?.bounds = rect
   layer?.cornerRadius = layer!.bounds.height * 0.5
   layer?.masksToBounds = true
   layer?.position = CGPoint(x: foodImageView.center.x, y: rect.minY + 96)
   KeyWindow.layer.addSublayer(layer!)

   // animation path
   path = UIBezierPath()
   path!.move(to: layer!.position)
   path!.addQuadCurve(to: CGPoint(x:SCREEN_WIDTH - 25, y: 35), controlPoint: CGPoint(x: SCREEN_WIDTH * 0.5, y: rect.origin.y - 80))
  }
  groupAnimation()
 }

这是放大,缩小,抛入购物车的组动画

 // start group animation: throw, larger, smaller image
 fileprivate func groupAnimation()
 {
  tableView.isUserInteractionEnabled = false

  // move path
  let animation = CAKeyframeAnimation(keyPath: "position")
  animation.path = path!.cgPath
  animation.rotationMode = kCAAnimationRotateAuto

  // larger image
  let bigAnimation = CABasicAnimation(keyPath: "transform.scale")
  bigAnimation.duration = 0.5
  bigAnimation.fromValue = 1
  bigAnimation.toValue = 2
  bigAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn)  // smaller image
  let smallAnimation = CABasicAnimation(keyPath: "transform.scale")
  smallAnimation.beginTime = 0.5
  smallAnimation.duration = 1
  smallAnimation.fromValue = 2
  smallAnimation.toValue = 0.5
  smallAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)  // group animation
  let groupAnimation = CAAnimationGroup()
  groupAnimation.animations = [animation, bigAnimation, smallAnimation]
  groupAnimation.duration = 1.5
  groupAnimation.isRemovedOnCompletion = false
  groupAnimation.fillMode = kCAFillModeForwards
  groupAnimation.delegate = self
  layer?.add(groupAnimation, forKey: "groupAnimation")
 }

组动画结束后的一些动画效果。

 // end image animation, start other animations
 func animationDidStop(_ anim: CAAnimation, finished flag: Bool)
 {  if anim == layer?.animation(forKey: "groupAnimation")
  {   // start user interaction
   tableView.isUserInteractionEnabled = true

   // hide layer
   layer?.removeAllAnimations()
   layer?.removeFromSuperlayer()
   layer = nil

   // if user buy any food, show the count label
   if self.addFoodArray.count > 0 {
    addCountLabel.isHidden = false
   }   // show the count label
   let goodCountAnimation = CATransition()
   goodCountAnimation.duration = 0.25
   addCountLabel.text = "\(self.addFoodArray.count)"
   addCountLabel.layer.add(goodCountAnimation, forKey: nil)   // shopping cart shaking
   let cartAnimation = CABasicAnimation(keyPath: "transform.translation.y")
   cartAnimation.duration = 0.25
   cartAnimation.fromValue = -5
   cartAnimation.toValue = 5
   cartAnimation.autoreverses = true
   cartButton.layer.add(cartAnimation, forKey: nil)
  }
 }

购物车里面可以增加/减少购买数量,总价跟着会动态变动。主要是有用到了两个东西,一个是 selected 变量,一个是 reCalculateCount() 函数。根据 selected 来决定最后的总价,如果有变动,则重新计算 (reCalculateCount)。

fileprivate func reCalculateCount()
 {
  for model in addFoodArray! {
   if model.selected == true {
    price += Float(model.count) * (model.vipPrice! as NSString).floatValue
   }
  }
  // assign price
  let attributeText = NSMutableAttributedString(string: "Subtotal: \(self.price)")
  attributeText.setAttributes([NSForegroundColorAttributeName: UIColor.red], range: NSMakeRange(5, attributeText.length - 5))
  totalPriceLabel.attributedText = attributeText
  price = 0
  tableView.reloadData()
 }

没有实现 Pay() 功能。打算之后尝试 Apple Pay ,之前用惯了支付宝,刚来美国的时候很难受,其实很多地方中国都已经比美国好很多了。还好现在有了 Apple Pay ,还挺好用的。

自定义个人主页

profile

本来打算做成简书那样,但是。。作为新手感觉还是有点难度。也是因为我这 app 里没有必要实现那些,就没仔细研究。

如前面提到的这页用的 collectionView,两个 section,一个是 UserCollectionViewCell , 下面是 HistoryCollectionViewCell 。 下面这个 section 像一个 table 的 section,有一个会自动悬浮的 header,这 header 用的是 ALin 大神的轮子, LevitateHeaderFlowLayout() ,当然这个文件的 copyright 是用他的名字的。

class CollectionViewFlowLayout: LevitateHeaderFlowLayout {
 override func prepare() {
  super.prepare()

  collectionView?.alwaysBounceVertical = true
  scrollDirection = .vertical
  minimumLineSpacing = 5
  minimumInteritemSpacing = 0
 }
}

这项目总体来说应该算很小的,如果后端也实现了,也算一个蛮完整的小项目了吧。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索ios
, app
, ui
订餐
wpf 开源ui框架、开源前端ui框架、开源ui框架、html5 ui 开源框架、android 开源ui框架,以便于您获取更多的相关知识。

时间: 2025-01-26 12:48:57

iOS开源一个简单的订餐app UI框架_IOS的相关文章

photoshop制作一个简单又时尚的UI按扭

在这个教程里,将和童学们分享如何使用photoshop制作一个简单又时尚的UI按扭,这个按扭可以用在电子商务网站,或者是网店上. 1.新建一个文档(ctrl+N)大小为:600*600(虽然我们按扭的大小:170*50,但是尺寸大方便我们的修改) 2.选择"圆角矩形工具"并设圆角"5px"绘制一个大小为:170*50 的圆角矩形.(可以使用标尺定位) 3.新建一个图层,按组合键"ctrl+enter"把路径转化为选区,并填充黑色. 双击这个图层给

iOS写一个插件禁止在app内截屏和使用相机

问题描述 iOS写一个插件禁止在app内截屏和使用相机 ipad开发,现在app需要做到不能让用户使用截图和相机功能,这个插件怎么写啊? 解决方案 这个你应该没办法,截屏,拍照,都是在系统那一层做的,你的App控制不到

实现一个简单的struts和spring框架

apache终于发布了struts2的正式版:struts2.0.6GA,所以我也该从webwork迁移至struts2.struts2 基本上就是webwork的翻版,所以迁移过程倒是很简单,只需要修改下配置文件和一些包名就可以了.如 果在Eclipse.Netbeans这些集成开发工具的帮助下,记不清包名也很容易找到想要的类的,呵呵. 在Eclipse下建立一个Dynamic Web Application. 从struts2.0.6的lib目录中复制下面的库文件到WEB-INF/lib目录

推荐一个非常棒的Titanium MVC框架_IOS

虽然之前我自己也有一个Titanium的框架,但ChariTi另一个吸引我的地方是其对内存管理的处理非常好,对使用后的控件和页面的释放工作做得很好,我曾做过测试,使用ChariTi后基本上不怎么会有内存泄漏的问题出现,即使使用webview的情况下也能很好地进行控制,内存很快就得到释放了. 不过我觉得ChariTi还有些需要完善的地方.其现在还不支持自定义多语言功能的使用,我指的自定义是指可以直接在APP里面可以即时进行语言转换.另外就是在页面的转换时,没有任何动画效果,我觉得至少要加上左右滑动

app-一个简单的记事本APP,在其他人eclipse上无问题,但我的就是运行不了,logcat如下

问题描述 一个简单的记事本APP,在其他人eclipse上无问题,但我的就是运行不了,logcat如下 补充说明:只有这一个项目是不能运行的,其他项目可以运行 解决方案 noclassdeffounderroe,有类没找到,eclipse是不是JDK版本的设置问题.版本太低或太高 解决方案二: NoteListActivity类没有找到,确认项目是否拷贝完整,有没有在manifest.xml文件中注册NoteListActivity 解决方案三: 解决方案四: 先看下项目中有没有NoteList

mdi-请教实现这样的一个简单功能的 MFC MDI 框架该怎么构建

问题描述 请教实现这样的一个简单功能的 MFC MDI 框架该怎么构建 本人之前有写过一个简单的 MFC SDI 的框架,也就是每次打开一幅图像,然后处理完这一幅图像再读进来下一幅重复处理操作,这样的功能 SDI 也就够了.最近想升级下程序框架,就试着在写一个 MDI 的框架,想实现的大致效果就是: 1.主窗口分成 3 块区域,最左边的区域存放选择的所有图像的缩略图(或者说图标icon),双击其中某幅图像的话,该图像就会在其右的最大的区域以全图形式显示出来,双击了多幅图像的话,这些被双击的图像都

WWDC15 Session笔记 - 30 分钟开发一个简单的 watchOS 2 app

Apple Watch 和 watchOS 第一代产品只允许用户在 iPhone 设备上进行计算,然后将结果传输到手表上进行显示.在这个框架下,手表充当的功能在很大程度上只是手机的另一块小一些的显示器.而在 watchOS 2 中,Apple 开放了在手表端直接进行计算的能力,一些之前无法完成的 app 现在也可以进行构建了.本文将通过一个很简单的天气 app 的例子,讲解一下 watchOS 2 中新引入的一些特性的使用方法. 本文是我的 WWDC15 笔记中的一篇,在 WWDC15 中涉及到

iOS 流式布局 UI 框架 CocoaUI 开源

CocoaUI 是一个强大的 iOS UI 框架,使用 Web 开发者熟悉的 HTML+CSS 流式布局方式,轻松地开发 iOS 原生 App 的界面.CocoaUI 的特性主要包括: 高效的原生界面, 非低效的 WebView 控件方式 自适应(Adaptive)动态流式布局, 轻松适配多种屏幕尺寸 采用简洁高效的 HTML+CSS 语法定义布局(Layout)和展现(Appearance) CocoaUI 的界面控件布局方式是流式布局方式,这种界面布局算法已经在 Web 领域得到验证, 具有

用Swift构建一个简单的iOS邮件应用的方法_Swift

在前几个月内,我一直在做InboxKit的研究,它是关于Inbox平台的IOS SDK.Inbox为和邮件数据的交互提供高层API,使得你可以忽略IMAP,Exchange,MIME的解析以及thread探测(当然还有很多其他事情...),并使你致力于完成富有创意的APP的创作上.我们的目标很简单:尽可能地打造一个优雅的,跨提供商的邮件应用.毕竟,它很难. 在Objective-C中,InboxKit使得创建邮件体验变得很轻松,那么,Swift又如何呢?Swift在WWDC后已正式被IOS社区所