2017/3/14

Xamarin.Forms 教學系列文(八.貳 + 九)事件 x 觸擊 x 跨平台方法




學習目標
  • XAML Events
  • Tap gestures
  • 跨平台方法實作與使用

這小節主要延續第八章 XAML 和 C# 的配合,介紹 XAML 事件指派,與設定任何 Visual Elements 都可以進行的 互動事件 ( GestureRecognizers )。
Xamarin GestureRecognizers 互動事件目前有三種,觸擊 (Tap)、縮放 (Pinch) 和 Pan (拖曳)。

最後講解第九章,針對不同平台的方法實作,與前面提到的 onplatform 不一樣,

因為有些 "共用" 方法還未出現於 Xamarin.Forms,所以必須將實作拉到 iOS 或 Android 專案內,再回到 Portable 專案內執行。

原文書第八章末和第九章其實有實作一個叫做 Monkey tap 的小遊戲 (篇幅滿大的),但不會出現在本小節教學,有機會再另一開篇好了...
這系列的教學著重於方法的介紹。


XAML Events

若要在 XAML 的 Visual Elements 內寫對應 C# 的事件,最簡單的例子可以來看 Button Clicked 事件:
    <StackLayout Orientation="Horizontal">             
        <Button Text="Click Me" x:Name="Button_Click" Clicked="Button_Click_Clicked" />           
    </StackLayout> 

建立事件時,我通常會交由 Visual Studio 自己去產生事件方法,

以此處的例子來說,我會先指派 x:Name 的值,接著利用 intellisense 的強大...

標籤內按下 Clicked= 就會出現...


按下 Enter 後就會藉由 x:Name 幫你產生事件名稱...

再去 .cs 看,就會產生對應的方法了...

好處就是不用去記得要帶入什麼參數 ( object 和 EventArgs )。
若有寫過 Webform 的應該會很熟悉...


Tap gestures

若你要一個 BoxView 也擁有點擊的事件時該怎辦?

就要借用 GestureRecognizers 來處理,每一個 Visual Elements 都能加入 GestureRecognizers,並於 GestureRecognizers 內指定要做的事件
事件除了 Tap (觸擊) 外,還有 Pinch (縮放手勢) 以及 Pan (拖曳)  以使用。
詳可見 https://developer.xamarin.com/guides/xamarin-forms/application-fundamentals/gestures/

在 BoxView 加入觸擊事件:
<BoxView Color="Blue">     
    <BoxView.GestureRecognizers>         
        <TapGestureRecognizer Tapped="OnBoxViewTapped" />                     
        </BoxView.GestureRecognizers> 
    </BoxView>

當然要有對應的 C# 事件:
        private void OnBoxViewTapped(object sender, EventArgs e)
        {

        }


實作跨平台方法

第九章會提到這件事情完全是因為 - 要讓第八章實作的小遊戲 Monkey Tap 加入聲音

但 Xamarin.Forms 沒有提供產生聲音的類別庫,而各平台產生音效的方法又不一樣。

所以我們必須在 不同平台 內各別去實作,然後在 Portable 內藉由 ASP.NET 提供的 Dependency 方法來映射並使用。

這邊舉一個簡單的例子,程式功能為顯示平台的資訊:

1. 起手式 - 先在 Portable 專案內定義介面
namespace DisplayPlatformInfo 
{     
    public interface IPlatformInfo     
    {         
        string GetModel();
 
        string GetVersion();     
    } 
}

2. 接著在不同平台的專案內實作
iOS 實作:
using System; 
using UIKit; 
using Xamarin.Forms; 
 
[assembly: Dependency(typeof(DisplayPlatformInfo.iOS.PlatformInfo))] 
 
namespace DisplayPlatformInfo.iOS 
{     
    public class PlatformInfo : IPlatformInfo     
    {         
        UIDevice device = new UIDevice();
 
        public string GetModel()         
        {             
            return device.Model.ToString();
        } 
 
        public string GetVersion()         
        {             
            return String.Format("{0} {1}", device.SystemName,                            
                device.SystemVersion);         
        }     
     } 
}

Android 實作:
using System; 
using Android.OS; 
using Xamarin.Forms; 
 
[assembly: Dependency(typeof(DisplayPlatformInfo.Droid.PlatformInfo))] 
 
namespace DisplayPlatformInfo.Droid 
{     
    public class PlatformInfo : IPlatformInfo     
    {         
        public string GetModel()         
        {             
            return String.Format("{0} {1}", Build.Manufacturer,                                              
            Build.Model);         
        }
 
        public string GetVersion()       
        {          
            return Build.VERSION.Release.ToString();       
        }  
    }
}

3. 最後回到可攜式 (Portable) 專案內使用:
namespace DisplayPlatformInfo 
{     
    public partial class DisplayPlatformInfoPage : ContentPage     
    {         
        public DisplayPlatformInfoPage()         
        {             
            InitializeComponent(); 
 
            IPlatformInfo platformInfo = DependencyService.Get<Iplatforminfo>();              
            modelLabel.Text = platformInfo.GetModel();             
            versionLabel.Text = platformInfo.GetVersion();         
        }     
    }
}
注意 IPlatformInfo platformInfo 藉由 DependencyService.Get() 的宣告用法。

執行結果:




8 則留言:

  1. 實作跨平台方法的第3步驟
    IPlatformInfo platformInfo = DependencyService.Get();
    那邊要改成
    IPlatformInfo platformInfo = DependencyService.Get< IPlatformInfo>();

    <>那邊一樣被吃掉了,感謝有此教學系列文。

    回覆刪除
    回覆
    1. 謝拉,沒注意到那邊會被視為html tag...文章修正了喔! 感謝你!

      刪除
  2. 作者已經移除這則留言。

    回覆刪除
  3. 羅根好樣的,謝謝你整已翻譯排版的很棒,
    請問您現在是從事Xamarin開發相關的工作嗎?

    回覆刪除
    回覆
    1. Asp.net 網頁系統 & Xamarin.Forms App開發,不過其實正職是PM...

      刪除
    2. 難怪XD GDGD,請教您一下,
      現在走Xamarin應用的開發公司或客戶量多嗎?
      做遊戲的話與Unity的結合性好嗎?
      還是Xamarin指教適合走Windows Form與WPF類的系統應用程式
      感謝

      刪除
    3. 一個一個問題回答好了,
      台灣目前用Xamarin開發的公司還不多(技術還太新),只要牽扯到技術的問題,已經有產品的公司相當難轉換(跳槽?)。
      客戶量又是另外一個層面的問題,基本上只要有需求,客戶不會管你是用什麼技術...把它需要的產品生出來又便宜就對了...
      我還沒試過Unity,但前一陣子有個左岸網友跟我聊過,騰訊的"傳說對決"架構是Xamarin
      我目前對於Xamarin.Forms的概念為,很適合開發公司內部用App,或表單型,不太需要特定平台或特殊操作的應用程式

      刪除
    4. 感謝回覆!!
      聽到傳說對決 就明白了
      Thanks.

      刪除