文章出處

  從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 + 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,這個事情也許值得一試。

      

      你還可以掃描下面的二維碼通過微信來看這篇文章。


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()