Xamarin Forms:小马过河,王者归来
因为我媳妇的原因,去年下半年从零开始学习Android原生开发,做了一个答题库app。整体给我的感觉是入门难度不大,前期折腾一番,大部分时间都是花在开发上面,其实任何一门语言都是如此。
今年我又有另一个需求想要开发一款app同时支持android和iOS。作为一名.net圈子的人怎么可能不知道Xamarin。只是一直以来国内关于Xamarin的信息太少,而且每年Xamarin社区的发展和完善相关的情况也都没有相应的报道,说白了关注度不高,让想使用它的人没有太多勇气去决定使用它。我也是这样,没办法转投关注国外论坛和相关博客,果然是墙内墙外的环境大不相同。中国还是一大群人围着小马七嘴八舌,而国外已经小马过河,王者归来了。发现了一篇博客极大的鼓舞了我选择Xamarin的勇气,所以决定翻译这篇博文分享给各位。最后插一嘴,我认为.NETer是幸运的,虽然经历过黑暗,但是我认为并非坏事,在国内这种培训机构横飞的年代没有像Java那样泛滥成灾。值得庆幸的是.NET目前依然在手游、医疗、金融、教育等领域占有较大份额。.net依然是高效开发的首选语言。废话不多说,下面是译文:
原文地址:https://www.sharpnado.com/xamarin-forms-works/
2017年7月,我接到了以前的同事打来的电话,问我是否有兴趣和他一起做个APP,客户端是一个可以专门编辑赛马比分结果的巴黎赛马报。
可爱的小马
他们想针对小马训练员们提供一个多平台的新产品叫做 Exalt Training。
为此,他们和一个名叫Souffl获得过创新奖的法国公司合作。
如果你们想自己了解更多关于他们的产品请访问:https://souffl.com/projets/la-premiere-solution-de-tracking-sportif-dediee-aux-entraineurs-de-chevaux-de-course/。
经过了6个月的延期iOS app开发失败之后,他们决定从原生native转投Xamarin native,包括android和iOS平台。
Xamarin Forms成熟并且功能强大
没错我说的,如果你们中任何人质疑,这就是给你们的答案:它简单粗暴、高效快捷,它可以处理各种复杂场景甚至你要想的所有功能。
多说无益!
我们实现的复杂功能包括:
- 渐变的背景
- 多种动画效果
- 在谷歌地图上绘制渐变路径
- 数据可视化曲线图
- 超多视图轮播(views 20+)
- 有吸附效果的水平列表视图
- 可拖放的的表格视图
- 自定义选项卡
- 带隐藏菜单的选项卡组成的自定义导航,向上滑动可显示菜单。
这些功能所用到技术,我会一一回答,如下:
技术 | 作用 |
---|---|
SkiaSharp | Animation / Draw on map / Plots |
Custom renderers | Gradient / Horizontal list views |
Xamarin animation API | Animations |
Xamarin custom components | BottomBar / Tabbar |
Lottie | Animations |
WebSocket | Real time communication |
最后,我们将会在帅气的 Visual Studio应用中心上面添加注释。
注意:方便起见,所有android模拟器捕获包含的gif和png图片,都要确保我们在iOS app中有完全相同的资源可用。
SkiaSharp
SkiaSharp是一个跨平台的底层API。你可以在canvas中绘制文本、圆形、路径(DrawText, DrawCircle, DrawPath)。虽然很强大,但依然需要通过一些数学技巧来实现你自己的布局。
以下所有的视图都是用SkiaSharp绘制的。
在Goole Maps上绘制
这个有点挑战,因为你必须将gps位置转换到像素坐标,而不通过调用 Google Maps SDK(为了有较好的响应时间)。
幸运的是我已经在10年前工作中的一个项目中解决过这个问题。
这回我们将使用GDI+在web视图里面的虚拟地球上绘制自定义的图标和路径。好了,我已经有了数学墨卡托的投影法术了。
剩下的工作就不是很困难了,因为只需要用着色器绘制一个路径即可,因此我们可以看到不同(渐变)表示的马儿的速度。
这个skiasharp位嵌入到一个的自定义ContentView的sessionmap方法中。
这个颜色代表马奔跑的速度,蓝色是快,红色是快到极限。
绘制曲线
在地图的下面我们想显示马儿的卖力情况(心率和速度)。所以我们需要在马儿训练时间上绘制曲线。
我们为此创建了一个SessionGraphView的ContentView。
将上面两个联系到一起
当然我们还需要一些交互性功能,用户可以拖动时间线的时候同时也更新马儿卖力情况的数值和对应地图上的位置。
这是通过将属性currentTime从sessiongraphview绑定到sessionmap组件来实现的。
自定义控件
另一个界面,我们需要一个根据月为索引的日期选择控件。因为Xamarin Forms没有这个,我们决定用SkiaSharp来实现它。
这是一个简单的控件名为MonthSlidesView,继承自ContentView,具备CurrentLowerDate
and CurrentUpperDate
.两个属性。
当然,这个控件与反映马随着时间的推移前进的曲线相互作用。
可发光的数字动画
这个动画是100%SkiaSharp,包含在名为glowingnumberview的skcancasview中。
它的实现是通过无限循环来进行的,具体技术描述请参考:https://docs.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/graphics/skiasharp/basics/animation.
是通过两个圆圈来改变透明半透明值来实现的。
放大的动画
自定义渲染器
CarouselView
有一个界面的特效是轮播所有正在训练的马儿,我们称之为Live Screen.
所以我们需要一个轮播视图。不幸的是Xamarin.Forms CarouselView一直都是非正式版本pre-alpha(至今都3年了):https://www.nuget.org/packages/Xamarin.Forms.CarouselView.
所以我们找到了一个开源的项目: https://github.com/alexrainman/CarouselView。
非常失望这个项目有性能问题和许多大小重置的问题,所以最终我们forking了它:https://github.com/roubachof/CarouselView. 例如,在android上,我们将PageAdapter
切换到了 FragmentStatePagerAdapter,以避免内存问题。
Horizontal/Grid-ListView
针对这个我们想要一些特定的行为:
- 对于水平布局,应将捕捉效果应用于第一个可见项。
- 使用网格布局,我们应该能够拖放项目以重新排序集合。
- 由于项目布局很复杂,我们需要一些视图预加载来平滑滚动。
Xamarin Forms ListView太简单,无法使用。
因此我们通过挖掘网络找到了这篇博客:(https://causerexception.com/2018/02/06/xamarin-forms-ultimate-horizontal-list-guide/).
遗憾的是实现太过于简单,并且还有性能问题。
最终还是不得不通过ListView下的HorizontalListView来凑合着实现效果。
实现
在android上,我们使用RecyclerView,LinearSnapHelper来实现捕捉触发效果,ItemTouchHelper来实现拖放效果。
为了提高性能,我们对item实现了异步预加载。
在iOS上,我们用了UICollectionView,拖放功能完全支持,我们使用一个简单的技巧来实现捕捉效果。
这个 Xamarin Forms ListView 的实现形式很快会被上传到Github上去。
其他渲染器
- 渐变
- Material 框架(cardView on android custom shadow on ios)
我们大部分时间都在试图创建自定义Xamarin.Forms 视图。
Xamarin Forms 动画效果
我们使用animation api实现多个视觉效果,如下:
自定义Xamarin Forms 容器
我们也可以只用Xamarin.Forms创建一些组件,不使用其他渲染器。
TabBar (android style)
我们将这个组件分为两部分:
- TabHostView 有选中效果的选项卡
- ViewSwitcher 可显示隐藏的视图切换
通过一个可绑定的属性SelectedIndex将两个放到一起,效果如下:
TaskLoaderView
我们创建一个通用的 Xamarin.Forms component,在加载和处理视图的所有错误状态时显示ActivityLoader。
- 为空(无返回内容)
- 错误(错误消息+重试按钮)
- 刷新时出错(带错误消息的snackbar)
- 成功(返回视图)
你可以通过下面看到更详细的内容:
https://github.com/roubachof/Xamarin-Forms-Practices.
BottomBar (ios style)
设计一个自定义导航容器。首先它实际上就是个底部选项卡(tabbar),但是如果你要向上滑动这个选项卡,这个容器会占据显示在整个界面上,并显示一个menu。这个菜单可以操作,包括一些像用户的个人信息和设置功能。这个组件也就是常规用到的TabHostView
和 ViewSwitcher。只是TabHostView是放在屏幕的底部。
当组件的状态为Peek的时候,只显示在底部。
应用一个手势,我们进行简单的转换,将隐藏的menu向上移动并显示。同样的,向下滑动隐藏menu。
Lottie
(Lottie是Airbnb开源的跨平台动画库。官网:http://airbnb.io/lottie/)
我们使用lottie来代替一些太难不能实现的组件功能。
Web socket and communication
我们使用 .net的 ClientWebSocket 来实现直播服务
REST我们用到了:
- Refit
- Polly (用在我们的链接恢复策略)
- InsanePowerPack (改造http缓存)
- Fusillade (低优先级的同步服务和图片加载)
- 自定义的 in-memory cache (缓存失效这个比较难搞)
Visual Studio App Center
我们用应用程序中心来进行持续集成,每次主要推送都会构建android 和 iOS.
使用预构建脚本在分支上运行创建两个不同的应用程序。
如果我们在qa分支上创建了一个app,这个应用程序将会连接到我们的后台。如果在建个qa-mock,那么所有的数据都是模拟数据。
我们也可以通过发行版本让各类用户来测试我们的app。
我最喜欢的还是app center里面的每一个崩溃报告都包括一些text。因为在崩溃的时候,我们可以在应用程序里记录的相关日志并附加到每个报告中去。
Xamarin Forms:小马过河,王者归来的更多相关文章
- 牛客网 牛客小白月赛2 B.小马过河-简单的计算几何
B.小马过河 链接:https://www.nowcoder.com/acm/contest/86/B 这个题是一个简单的几何题???套个板子就过了,就是直线上两点确定的这条直线和直线外一点的垂足的坐 ...
- .NET框架之“小马过河”
.NET框架之"小马过河" 有许多流行的.NET框架,大家都觉得挺"重",认为很麻烦,重量级,不如其它"轻量级"框架,从而不愿意使用.面对形 ...
- 老司机学新平台 - Xamarin Forms开发框架二探 (Prism vs MvvmCross)
在上一篇Xamarin开发环境及开发框架初探中,曾简单提到MvvmCross这个Xamarin下的开发框架.最近又评估了一些别的,发现老牌Mvvm框架Prism现在也支持Xamarin Forms了, ...
- Xamarin.Forms介绍
On May 28, 2014, Xamarin introduced Xamarin.Forms, which allows you to write user-interface code tha ...
- Material Design For Xamarin.Forms
最近,升级 Xamarin.Forms 到最新版本后,发现Droid 项目下引入了以下几个依赖包: Xamarin.Android.Support.DesignXamarin.Android.Supp ...
- Xamarin.Forms——尺寸大小(五 Dealing with sizes)
如之前所见的大量可视化元素均有自己的尺寸大小: iOS的状态栏高度为20,所以我们需要调整iOS的页面的Padding值,留出这个高度. BoxView设置它的默认宽度和高度为40. Frame的默认 ...
- Xamarin.Forms入门学习路线
Xamarin 介绍 Xamarin是一套跨平台解决方案,目的是使用C#语言创造原生的iOS,Android,Mac和Windows应用. Xamarin的三个优势: Xamarin App拥有原生A ...
- 从零开始学Xamarin.Forms(五) 技巧
原文:从零开始学Xamarin.Forms(五) 技巧 由于HTML5规范于2014年10月终于定稿,公司.net开发人员较少,国内外已有了较为成熟的UI框架.手机软件硬件的快速发展等等原因,所以我就 ...
- C#使用Xamarin开发可移植移动应用(2.Xamarin.Forms布局,本篇很长,注意)附源码
前言 系列目录 C#使用Xamarin开发可移植移动应用目录 源码地址:https://github.com/l2999019/DemoApp 可以Star一下,随意 - - 一点感想 很意外的,第一 ...
随机推荐
- JAVA简单的文件I/O操作实例
如果只是对文件进行普通的读写,可以不用文件流. 以下是实例: File file = new File("test1.txt"); //向文件写入数据的 PrintWriter p ...
- krpano之字幕添加
字幕是指介绍语音的字幕,字幕随着语音的播放而滚动,随语音暂停而暂停.字幕添加的前提是用之前的方法添加过介绍语音. 原理: 字幕层在溢出隐藏的父元素中向右滑动,当点击声音控制按钮时,字幕位置被固定,再次 ...
- leetcode773
使用两种语言实现,先贴C++的 class Solution { public: vector<vector<int>> floodFill(vector<vector& ...
- Spring Cloud Feign 1(声明式服务调用Feign 简介)
Spring Cloud Feign基于Netflix Feign 同时整合了Spring Cloud Ribbon和Spring Cloud Hytrix,除了提供两者的强大功能外,它还提供了一种声 ...
- python3.3 MD5
代码如下: # /usr/bin/python # -*- coding:utf-8 -*- import hashlib h=hashlib.md5() data = ' h.update(data ...
- Unity3D自带Demo AngryBots路径
[Unity3D自带Demo AngryBots路径] 1.Windows: C:\Users\Public\Documents\Unity Porjects 2.MacOSX: /Users/Sha ...
- Spring总结四:IOC和DI 注解方式
首先我们要了解注解和xml配置的区别: 作用一样,但是注解写在Bean的上方来代替我们之前在xml文件中所做的bean配置,也就是说我们使用了注解的方式,就不用再xml里面进行配置了,相对来说注解方式 ...
- Linux VmWare安装虚拟机(centos6.9)
开启虚拟机 ---------------------------------------------------------------------------------------------- ...
- 有关Lucene的问题(4):影响Lucene对文档打分的四种方式
原文出自:http://forfuture1978.iteye.com/blog/591804点击打开链接 在索引阶段设置Document Boost和Field Boost,存储在(.nrm)文件中 ...
- cocos2d-x 在vs2010下的搭建(win7系统)
1从官网下载cocos2d-x2.1.3的源码地址如下: http://cocos2d-x.org/ 2.解压下载的软件包我们会发现红框中vs2010的项目文件双击打开它 3.打开后我们要生成一些wi ...