從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步:
- 找到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這個事件是我們自己聲明的,而這個聲明方法,相信大家不會覺得陌生。
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 + 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,這個事情也許值得一試。
你還可以掃描下面的二維碼通過微信來看這篇文章。
文章列表