从2015年接触Xamarin到至今已经2个年头,我对Xamarin的技能没有长进多少,但它却已经足够成熟到在跨平台移动开发工具中占有一席之地。在扫了一些资料之后,突然发现国外有很多移动端的应用已经是用Xamarin开发,Telerik还有专门的团队来开发Xamarin UI 库,这再次激发起了我的兴趣!吓得我赶紧找了个视频做了个demo, 下面就一起来体验一下用C# 开发一个Material Deisgn风格的Android应用的乐趣吧。
我们分为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步:
找到tab和view控件
通过TabAdapter给ViewPager设置视图
将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这个事件是我们自己声明的,而这个声明方法,相信大家不会觉得陌生。
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 + 1, 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(3000); RunOnUiThread(() => { mProgressBar.Visibility = ViewStates.Invisible; }); }); }
小结
在这个盛行全干的时代,我想每个人都应该懂移动端开发。Xamarin为我们提供了一种简单、高效的方式来开发强大的、如原生般体验的APP。结合C#优雅的语法和宇宙最强大的IDE,这个事情也许值得一试。
共同学习,写下你的评论
评论加载中...
作者其他优质文章