从2015年接触Xamarin到至今已经2个年头,我对Xamarin的技能没有长进多少,但它却已经足够成熟到在跨平台移动开发工具中占有一席之地。在扫了一些资料之后,突然发现国外有很多移动端的应用已经是用Xamarin开发,Telerik还有专门的团队来开发Xamarin UI 库,这再次激发起了我的兴趣!吓得我赶紧找了个视频做了个demo, 下面就一起来体验一下用C# 开发一个Material Deisgn风格的Android应用的乐趣吧。

先来看一下我们开发出来的应用是个什么样子?一个酷炫的tab view 和 list

下面是一个左侧菜单

这是一个Collapsing Tool Bar的实现效果

最后还有一个bottom sheet

  

整个例子中好玩的地方非常多,我们分为UI和C#代码两块来看。因为在整个UI层几乎是和原生Android开发一模一样,所以如果原来做过Android开发又懂C#,那用Xamarin来开发安卓程序几乎是没有什么学习成本 。那么对于没有Android开发经验的C#同学来说,学习Android的UI绘制则是必不可少的部份。

UI层的开发

  • Layout 与 Widget
  • Material Design 和 Android Support Library
  • AppbarLayout + TabLayout
  • DrawerLayout + NavigationView
  • CollapsingLayout + NestedView + CardView
  • ListView 与 RecyclerView

C#代码完成的那些事

  • 控件与事件绑定
  • Activity 之间数据传递
  • 多线程

Layout与Widget

Android的页面视图由XML来声明,而所有页面的这些UI组件都由一个布局(Layout)来组织。Android最早一共提供了6种基本布局。

  • Linear Layout
  • Relative Layout
  • Table Layout
  • Grid View
  • Tab Layout
  • List View

Widget则是一些其它的UI组件

  • Date Picker
  • Time Picker
  • Form Elements(Button, TextView, CheckBox, RadioButton, Toggle Button, Rating Bar)
  • Spinner
  • Auto Complete
  • Gallery
  • WebView
  • Tool Bar
  • View Pager
  • 等...

我们将会在后续的文章来详细再介绍这些Layout 和 Widgets的使用,今天我们的主角不是他们。而是Google基本Material Design 为android 开发的一套Design Support Library。

Material Design 和 Design Support Library

关于Material Deisgn已经有一份非常详细的中文文档http://design.1sters.com/,Google在2014年推出的全新的设计语言,这种设计语言旨在为手机、平板电脑、台式机和“其他平台”提供更一致、更广泛的“外观和感觉”。Google遵循MD设计风格重构了自己的几个主要APP并发布了安卓的DesignSupportLibrary来让大家更好地开发基于这种设计风格的APP。

我们的Demo中用到的组件包括:

  • AppBarLayout + Tab Layout 实现 图1中的Tab视图
  • Drawer Layout + Navigation View 实现图3中的左侧菜单
  • CoordinatorLayout
  • CollapsingToolbar Layout + NestedScrollView (图2中的页面往下滚图片缩小直到消失的效果实现 )
  • Recycler View (ListView的加强版,适合数据量大的List展示)

由于后面的三个CoordinatorLayout、CollapsingToolbar以及RecyclerView相对来说会有些复杂,所有我们后面会留专门的篇幅来讲,感兴趣的同学可以自己先研究起来或者关注后面的博客~

AppBarLayout + Tab Layout

TabLayout可以说是一个非常好用的视图,你几乎在每一个主流的APP里面都可以看到。我们用Support Library实现起来就非常的方便,下面是这几个组件的结构,ViewPager与AppBarLayout同级。

  

这里不太想给大家展示太多关于UI层的代码,如果感兴趣的同学可以直接到我的GitHub里面去下载。我们主要看一下C#如何在ViewPager里面放视图同时与TabLayout关联起来。只需要3步:

  1. 找到tab和view控件
  2. 通过TabAdapter给ViewPager设置视图
  3. 将ViewPager绑定到tab
var tabs = FindViewById<TabLayout>(Resource.Id.tabs);
var viewPager = FindViewById<ViewPager>(Resource.Id.viewpager); SetUpViewPager(viewPager);
tabs.SetupWithViewPager(viewPager);

SetUpViewPager方法如下:

private void SetUpViewPager(ViewPager viewPager)
{
var adapter = new TabAdapter(SupportFragmentManager);
adapter.AddFragment(new Fragment1(), "Fragment 1");
adapter.AddFragment(new Fragment2(), "Fragment 2");
adapter.AddFragment(new Fragment3(), "Fragment 3"); viewPager.Adapter = adapter;
}

是不是很简单?

DrawerLayout + NavigationView

图3中的左侧菜单,主流APP必备,也是只要几行代码就可以了。

  

在NavigationView的使用上,有两个属性需要注意一下。一个左侧菜单分为两部份:headerLayout和menu。

  

<android.support.design.widget.NavigationView
android:id="@+id/nav_view"
android:layout_height="match_parent"
android:layout_width="325dp"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="@layout/nav_header"
app:menu="@menu/drawer_view" />

所以我们需要有另外两个文件nav_header和drawer_view来配合一起完成这个菜单视图。

  

  nav_header其实很简单用了一个<ImageView>来显示图片,以及一个<TextView>来显示上面图里面的UserName。我们可以看一下app:menu="@menu/drawer_view"的drawer_view是如何构建成菜单项的。

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:checkableBehavior="single">
<item
android:id="@+id/nav_home"
android:icon="@drawable/ic_dashboard"
android:title="Home" />
<item
android:id="@+id/nav_messages"
android:icon="@drawable/ic_event"
android:title="Messages" />
<item
android:id="@+id/nav_friends"
android:icon="@drawable/ic_headset"
android:title="Friends" />
<item
android:id="@+id/nav_discussion"
android:icon="@drawable/ic_forum"
android:title="Discussion" />
</group>
<item android:title="Sub items">
<menu>
<item
android:icon="@drawable/ic_dashboard"
android:title="Sub item 1" />
<item
android:icon="@drawable/ic_forum"
android:title="Sub item 2" />
</menu>
</item>
</menu>

  实现一个这样的菜单只需要5分钟就搞定了~

控件与事件绑定

在VS操纵UI组件是一件非常简单的事。找到这个控件,接下来一切都变得简单,和之前的winform以及webform几乎是没有两样。

protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle); // Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main); var btnSelectDate = FindViewById<Button>(Resource.Id.btnDateSelector);
// 事件绑定匿名函数
btnSelectDate.Click += (o, e) =>
{
var dialog = Fragments.DatePickerFragment.NewInstance();
dialog.OnDateSelected += Dialog_OnDateSelected; // 事件绑定另一个方法
dialog.Show(FragmentManager, "tag");
};
} private void Dialog_OnDateSelected(DateTime dt)
{
var txtDate = FindViewById<TextView>(Resource.Id.txtDate);
txtDate.Text = dt.ToLongDateString();
}

在上面的代码中我们找到了 btnSelectDate的代码,然后绑定了它的Click事件来打开一个选择日期的Dialog。这里的事件处理我们用的是一个匿名方法。

而在这个Dialog的OnDateSelected事件我们则绑定了一个声明方法。注:OnDateSelected这个事件是我们自己声明的,而这个声明方法,相信大家不会觉得陌生。

DatePickerFragment.cs中用委托来声明事件,当然你也可以用传递Action的方式来解决。
public delegate void DateSelectedHandle(DateTime dt);
public event DateSelectedHandle OnDateSelected;
public void OnDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth)
{
var selectedDate = new DateTime(year, monthOfYear + , dayOfMonth);
if (OnDateSelected != null)
{
OnDateSelected(selectedDate);
}
}

这就是100%的C#代码。

Activity 之间数据传递

Android中Layout与Activity大家可以理解为webform中的.aspx页面与.aspx.cs code behind。 只是在Activity中我们还需要手动通过FindViewById来找到这个UI组件。如果Activity代表了一整个View,那我们来看看在不同的View之间如何传递数据。

var context = view.Context;
// CheeseDetailActivity是我们要跳转过去的Activity
var intent = new Intent(context, typeof(CheeseDetailActivity));
// 将数据Put到Extra中即可 EXTRA_NAME为这个数据的key
intent.PutExtra(CheeseDetailActivity.EXTRA_NAME, values[position]);
context.StartActivity(intent);

在CheeseDetailActivity中,只需要通过Intent.GetStringExtra(); 来获取即可

string cheeseName = Intent.GetStringExtra(EXTRA_NAME);

多线程

其实这里的多线程本不需要被提起,我只是为了向大家展示一下,这种线程处理也是100%C#来写。毕竟,越小的差异对于我们来说学习成本就越小。只是这里要注意一下,如果在非主线程中要操作UI,则需要调用RunOnUiThread(这名字起的也是好。。)

 void signUpDialog_mOnSignUpComplete(object sender, OnSignUpEventArgs e)
{
mProgressBar.Visibility = ViewStates.Visible;
Task.Run(() =>
{
Thread.Sleep();
RunOnUiThread(() => { mProgressBar.Visibility = ViewStates.Invisible; });
});
}

小结

   在这个盛行全干的时代,我想每个人都应该懂移动端开发。Xamarin为我们提供了一种简单、高效的方式来开发强大的、如原生般体验的APP。结合C#优雅的语法和宇宙最强大的IDE,这个事情也许值得一试。

你还可以扫描下面的二维码通过微信来看这篇文章。

是时候开始用C#快速开发移动应用了的更多相关文章

  1. arcpy+PyQt+py2exe快速开发桌面端ArcGIS应用程序

    前段时间有一个项目,大体是要做一个GIS数据处理工具. 一般的方法是基于ArcObjects来进行开发,因为我对ArcObjects不太熟悉,所以就思考有没有其他简单快速的方法来做. 在查看ArcGI ...

  2. 快速开发Grunt插件----压缩js模板

    前言 Grunt是一款前端构建工具,帮助我们自动化搭建前端工程.它可以实现自动对js.css.html文件的合并.压缩等一些列操作.Grunt有很多插件,每一款插件实现某个功能,你可以通过npm命名去 ...

  3. winform快速开发平台->让有限的资源创造无限的价值!

    最近一直在维护一套自己的快速开发平台. 主要应对针对C/S架构下的项目.然而对winform这快,还真没有看到过相对好的快速开发平台, 何为快速,在博客园逛了了好久, 预览了很多通用权限管理系统. 确 ...

  4. winform快速开发平台 -> 通用权限管理之动态菜单

    这几个月一直忙APP的项目,没来得及更新项目,想想该抽出时间整理一下开发思路,跟大家分享,同时也希望得到宝贵的建议. 先说一下我们的权限管理的的设计思路,首先一个企业信息化管理系统一定会用到权限管理, ...

  5. winform快速开发平台 -> 工作流组件(仿GooFlow)

    对于web方向的工作流,一直在用gooflow对于目前我的winform开发平台却没有较好的工作流组件.  针对目前的项目经验告诉我们.一个工作流控件是很必要的. 当然在winform方面的工作流第三 ...

  6. winform快速开发平台 -> 快速绑定ComboBox数据控件

    通常我们在处理编辑窗体时.往往会遇到数据绑定.例如combobox控件绑定数据字典可能是我们经常用到的.然而在我的winform快速开发平台中我是如何处理这个频繁的操作呢? 首先,我们要绑定combo ...

  7. winform快速开发平台 -> 基础组件之分页控件

    一个项目控件主要由及部分的常用组件,当然本次介绍的是通用分页控件. 处理思想:我们在处理分页过程中主要是针对数据库操作. 一般情况主要是传递一些开始位置,当前页数,和数据总页数以及相关关联的业务逻辑. ...

  8. 使用GizwitsOpenAPI,快速开发轻应用

    导读:使用机智云提供的Open API(Http / WebSocket),可以快速开发网页或微信应用等基于html的轻应用,用于管理和控制智能设备.机智云 Open API 主要帮助开发者通过 HT ...

  9. CYQ.Data 快速开发EasyUI

    EasyUI: 前端UI框架之一, 相对ExtJs来说,算是小了,这两天,抽空看了下EasyUI的相关知识,基本上可以和大伙分享一下: 官网: http://www.jeasyui.com/ 学习的话 ...

  10. C#.NET 大型企业信息化系统集成快速开发平台 4.2 版本 - 几十套业务系统集中统一授权管理实现经验分享

    由于这几年互联网电商的快速发展,快递公司也进入了快速发展的绝好快速成长期.随着社会的强劲需求公司的业绩年年攀新高.快速发展的公司都需要有强大的IT信息系统,硬件设备基本上款到了货也可以到了,但是软件系 ...

随机推荐

  1. RSA加密算法 C++实现

    上信息安全课,老师布置了几个大作业,其中一个为RSA加密算法的实现,不能用Java写.出于兴趣,决定尝试.完成之后,为了便于查找,于是写下这篇文章,以备后续查看.也供大家一起学习,一起进步. 1.预备 ...

  2. PHP运算符与表达式

    一.概述: 在我们平时的开发中,最离不开的就是运算,在编写比较复杂的后台程序的时候,算法更是必不可少的.涉及到运算就应该了解PHP的运算符,下面我们来一起看一下PHP中常见的运算符,以及和其他语言的区 ...

  3. cookie,session,token的定义及区别

    参考了很多文章总结的. 1.cookie(储存在用户本地终端上的数据) 服务器生成,发送给浏览器,浏览器保存,下次请求同一网站再发送给服务器. 2.session(会话) a.代表服务器与浏览器的一次 ...

  4. 玩转SSH端口转发

    SSH有三种端口转发模式,本地端口转发(Local Port Forwarding),**远程端口转发(Local Port Forwarding)**以及**动态端口转发(Dynamic Port ...

  5. python字符串实战

    haproxy配置文件 思路:读一行,写一行 global log 127.0.0.1 local2 daemon maxconn 256 log 127.0.0.1 local2 info defa ...

  6. OSI七层模型学习笔记

    1.简介 什么是OSI模型呢? OSI模型全名Open System InterConnect 即开放式系统互联,是国际标准化组织(ISO)提出的一个试图使各种计算机在世界范围内互连为网络的标准框架, ...

  7. Github+yeoman+gulp-angular初始化搭建angularjs前端项目框架

    在上篇文章里面我们说到了Github账号的申请与配置 那么当你有了Github账号并创建了一个自己的Github项目之后,首要的当然是搭建自己的项目框架啦! 本人对自己的定位是web前端狗,常用开发框 ...

  8. 2017Wow!新媒体营销深度分享会值得参加吗?

    "Wow!新媒体营销深度分享会"是虎嗅打造的创新跨界营销平台,以引领营销趋势和洞察技术奇点为目标,推动前沿技术创新与营销的碰撞融合. 在这里,你将看到2017年最前瞻的营销趋势.最 ...

  9. 使用java API操作hdfs--通过filesystem API 来读取数据

    上面的Path的包是导入错误了,nio中的包是抽象类,是无法创建的,所以换地方更改. 修改之后,指定jar包之后,编译成功,如下,并进行文件的读取操作,依然是成功啦:

  10. 在R中整理数据

    原始数据一般分散杂乱,并含有缺失和错误值,因此在进行数据分析前首先要对数据进行整理. 一.首先,了解原始数据的结构. 可使用如下函数(归属baseR)来查看数据结构: class(dataobject ...