服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - IOS - iOS开源一个简单的订餐app UI框架

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

2021-02-04 15:41诸葛俊伟 IOS

这篇文章主要介绍了iOS开源一个简单的订餐app UI框架,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

前言

学 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, 下面我就主要展示一下效果,稍微讲一下实现过程,代码中已有很多注释。

引导页

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

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

菜单和购物车

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

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上的购买按钮后触发

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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)
 }

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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()
 }

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// 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")
}

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 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)。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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 ,还挺好用的。

自定义个人主页

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

profile

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

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

?
1
2
3
4
5
6
7
8
9
10
class collectionviewflowlayout: levitateheaderflowlayout {
 override func prepare() {
  super.prepare()
 
  collectionview?.alwaysbouncevertical = true
  scrolldirection = .vertical
  minimumlinespacing = 5
  minimuminteritemspacing = 0
 }
}

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

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

原文链接:http://www.jianshu.com/p/e74381751b51

延伸 · 阅读

精彩推荐
  • IOSIOS 屏幕适配方案实现缩放window的示例代码

    IOS 屏幕适配方案实现缩放window的示例代码

    这篇文章主要介绍了IOS 屏幕适配方案实现缩放window的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要...

    xiari5772021-06-01
  • IOSiOS中tableview 两级cell的展开与收回的示例代码

    iOS中tableview 两级cell的展开与收回的示例代码

    本篇文章主要介绍了iOS中tableview 两级cell的展开与收回的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    J_Kang3862021-04-22
  • IOSiOS 雷达效果实例详解

    iOS 雷达效果实例详解

    这篇文章主要介绍了iOS 雷达效果实例详解的相关资料,需要的朋友可以参考下...

    SimpleWorld11022021-01-28
  • IOS解析iOS开发中的FirstResponder第一响应对象

    解析iOS开发中的FirstResponder第一响应对象

    这篇文章主要介绍了解析iOS开发中的FirstResponder第一响应对象,包括View的FirstResponder的释放问题,需要的朋友可以参考下...

    一片枫叶4662020-12-25
  • IOS关于iOS自适应cell行高的那些事儿

    关于iOS自适应cell行高的那些事儿

    这篇文章主要给大家介绍了关于iOS自适应cell行高的那些事儿,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的...

    daisy6092021-05-17
  • IOSiOS通过逆向理解Block的内存模型

    iOS通过逆向理解Block的内存模型

    自从对 iOS 的逆向初窥门径后,我也经常通过它来分析一些比较大的应用,参考一下这些应用中某些功能的实现。这个探索的过程乐趣多多,不仅能满足自...

    Swiftyper12832021-03-03
  • IOSIOS开发之字典转字符串的实例详解

    IOS开发之字典转字符串的实例详解

    这篇文章主要介绍了IOS开发之字典转字符串的实例详解的相关资料,希望通过本文能帮助到大家,让大家掌握这样的方法,需要的朋友可以参考下...

    苦练内功5832021-04-01
  • IOSiOS布局渲染之UIView方法的调用时机详解

    iOS布局渲染之UIView方法的调用时机详解

    在你刚开始开发 iOS 应用时,最难避免或者是调试的就是和布局相关的问题,下面这篇文章主要给大家介绍了关于iOS布局渲染之UIView方法调用时机的相关资料...

    windtersharp7642021-05-04