手勢操作
另外,對於像是
Image
, Label
這類控制項,Xamarin.Forms 並沒有提供類似按鈕的 Click 的事件,因次,若想要偵測到使用者有點選這些控制項,就需要使用到這篇章節所提到手勢操作功能。建立標籤式的樣板式頁面方案
- 首先,開啟您的 Visual Studio 2015
- 接著透過 Visual Studio 2015 功能表,選擇這些項目
檔案
>新增
>專案
準備新增一個專案。 - 接著,Visual Studio 2015 會顯示
新增專案
對話窗,請在這個對話窗上,進行選擇Visual C#
>Cross-Platform
>Blank Xaml App (Xamarin.Forms Portable)
- 接著,在最下方的
名稱
文字輸入盒處,輸入XFGestures
這個名稱,最後使用滑鼠右擊右下方的確定
按鈕。 - 當專案建立到一半,若您的開發環境還沒有建置與設定完成 Mac 電腦與 Xamarin Studio for Mac 系統,此時會看到
Xamarin Mac Agent Instructions
對話窗出現,這個對話窗是要提醒您進行與 Mac 電腦連線設定,這是因為,您無法在 Windows 作業系統進行 iOS 相關應用程式的建立與設計工作,而是需要透過 Mac 電腦安裝的 XCode 來協助您完成這些 iOS 應用程式的建立工作。不過,這不影響您繼續開發 Xamarin.Forms 的應用程式,只不過此時,您無法編譯與執行 iOS 的應用程式。 - 接著會看到
新的通用Windows專案
對話視窗,此時,您只需要按下確定
按鈕即可,此時,專案精靈會繼續完成相關平台的專案建立工作。 - 最後,整個新的 Xamarin.Forms 專案就建立完成了。
準備所需要的圖片資源
這個練習專案需要用到一些圖片檔案,因此,您需要進行將這些圖片檔案複製到適當的位置,這些檔案位於https://github.com/vulcanlee/Xamarin.Forms.StepByStep/tree/master/Images/XFGestures
Android 平台
當圖片檔案下載下來之後,請使用檔案總管全選這些圖片檔案,並且拖拉到 Android 專案 XFGestures.Droid > Resources > drawable 目錄內,如下圖所示: 當這些圖片檔案拖拉到 Android 專案內的 drawable 資料夾內,這些圖片檔案的建置動作必須是 AndroidResource 複製圖片檔案到Android專案內
iOS 平台
請使用檔案總管全選這些圖片檔案,並且拖拉到 iOS 專案 XFGestures.iOS > Resources 目錄內,這些圖片檔案的建置動作必須是 BundleResource 複製圖片檔案到iOS專案內
升級到 Xamarin.Forms 2.3 板以上
這個範例專案內,會使用到 Margin 這個屬性,因此,需要升級 Xamarin.Forms 套件到2.3以上版本
- 滑鼠右擊方案
XFGestures
,選擇管理方案的 NuGet 套件
- 點選
已安裝
>Xamarin.Forms
套件 > 選擇所有專案 > 選擇最新版本編號 >安裝
進階應用 Font Awesome
這個範例專案內將會使用到 Font Awesome 字體,您需要分別設定 Android 與 iOS 類型專案,使其可以使用 Font Awesome 字體圖示。
下載 Font Awesome 字型檔案與安裝
先打開瀏覽器,連線https://github.com/vulcanlee/Xamarin.Forms.StepByStep/tree/master/Font%20Awesome 會看到 Font Awesome 字型檔案
fontawesome.ttf
,點擊該連結,下載 Font Awesome的檔案到您本機磁碟機某個目錄上。
使用檔案總管,將剛剛下載的這個
fontawesome.ttf
檔案,拖拉到 XFGestures.Droid
專案內的 Assets
資料夾內。
使用檔案總管,將這個
fontawesome.ttf
檔案,拖拉到 XFGestures.iOS
專案內的 Resources
資料夾內。
想要在 Android 與 iOS 系統內使用 Font Awesome 提供的字體圖示,做法並不一樣,底下分別就兩個平台的做法進行說明。
Android 專案部分
請在
XFGestures.Droid
專案內,建立一個名為 Renderers
資料夾,並且在此資料夾內,建立一個類別檔案 AwesomeRenderer.cs
。該類別檔案的內容如下所示:using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Xamarin.Forms.Platform.Android;
using Xamarin.Forms;
using XFGestures.Droid;
using Android.Graphics;
using XFGestures.Droid.Renders;
[assembly: ExportRenderer(typeof(Label), typeof(AwesomeLabelRenderer))]
[assembly: ExportRenderer(typeof(Xamarin.Forms.Button), typeof(AwesomeButtonRenderer))]
namespace XFGestures.Droid.Renders
{
public class AwesomeLabelRenderer : LabelRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
base.OnElementChanged(e);
AwesomeUtil.CheckAndSetTypeFace(Control);
}
}
public class AwesomeButtonRenderer : ButtonRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Button> e)
{
base.OnElementChanged(e);
AwesomeUtil.CheckAndSetTypeFace(Control);
}
}
internal static class AwesomeUtil
{
public static void CheckAndSetTypeFace(TextView view)
{
if (view.Text.Length == 0) return;
var text = view.Text;
if (text.Length > 1 || text[0] < 0xf000)
{
return;
}
var font = Typeface.CreateFromAsset(Xamarin.Forms.Forms.Context.ApplicationContext.Assets, "fontawesome.ttf");
view.Typeface = font;
}
}
}
iOS 專案部分
在
XamarinLogin.iOS
專案中,使用滑鼠右擊 Info.plist
檔案,在彈出功能表中,選擇 開啟方式
,再出現 開啟方式 - Info.plist
對話窗後,請選擇 XML(文字)編輯器
,接著,點擊 確定
按鈕。
此時,Visual Studio 會開啟 XML 編輯器,請參考下兩圖,加入底下 XML 宣告到 Info.plist 檔案內。
<key>UIAppFonts</key>
<array>
<string>fontawesome.ttf</string>
</array> </dict>
- Info.plist尚未修改前的內容截圖
- Info.plist尚未修改後的內容截圖
開始進行 核心PCL 頁面設計
App.xaml.cs
在
App
類別的建構式內,使用底下程式碼置換。
這個應用程式將會使用
TabbedPage
標籤頁面作為第一個呈現的頁面,在這個頁面中,一共加入了三個子標籤頁面 TapInsideImage
, TapInsideFrame
, TapInsideFrameXaml
。在這個範例程式中,將會說明如何使用點擊的手勢操作功能。TapInsideImage
這個頁面展示了如何透過 C# 程式碼,在一個 Image 控制項中,綁定一個手勢物件,當使用者對於這個圖片有點選動作產生時候,就會觸發相對應的事件。TapInsideFrame
這個頁面展示了如何透過 C# 程式碼,在一個 Frame 框架中,綁定一個手勢物件,當使用者對於這個框架有點選動作產生時候,就會觸發相對應的事件。TapInsideFrameXaml
這個頁面展示了如何透過 XAML 的宣告定義與 ICommand 的資料綁定功能,針對 Image 與 Label 這兩個控制項,提供手勢操控的處理,其中,透過了NumberOfTapsRequired
這個屬性設定,可以控制手勢點選是單點,還是雙擊。
App.xaml.cs
public App()
{
InitializeComponent();
//MainPage = new XFGestures.MainPage();
var tabs = new TabbedPage();
// demonstrates an Image tap (and changing the image)
tabs.Children.Add(new TapInsideImage { Title = "圖片手勢", Icon = "csharp.png" });
// demonstrates adding GestureRecognizer to a Frame
tabs.Children.Add(new TapInsideFrame { Title = "框架手勢", Icon = "csharp.png" });
// demonstrates using Xaml, Command and databinding
tabs.Children.Add(new TapInsideFrameXaml { Title = "Xaml手勢", Icon = "xaml.png" });
MainPage = tabs;
}
TapInsideImage
請在核心PCL專案,使用滑鼠右擊
XFGestures
,在彈出功能表中,點選 加入
> 類別
,當出現 加入新項目 - XFGestures
對話視窗後,點選 Visual C#
> 介面
,接著在最下方的 名稱
欄位文字輸入盒中,輸入TapInsideImage
。
接著,請將底下 C# 程式碼置換剛剛產生的介面程式碼。
TapInsideImage.cs
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace XFGestures
{
public class TapInsideImage : ContentPage
{
int tapCount;
readonly Label label;
public TapInsideImage()
{
var image = new Image
{
Source = "tapped.jpg",
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.CenterAndExpand,
};
var foo = new StackLayout();
var tapGestureRecognizer = new TapGestureRecognizer();
// tapGestureRecognizer.NumberOfTapsRequired = 2; // double-tap
tapGestureRecognizer.Tapped += OnTapGestureRecognizerTapped;
image.GestureRecognizers.Add(tapGestureRecognizer);
label = new Label
{
Text = "點擊圖片!",
FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label)),
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.CenterAndExpand
};
label.GestureRecognizers.Add(tapGestureRecognizer);
Content = new StackLayout
{
Padding = new Thickness(20, 100),
Children =
{
image,
label
}
};
}
void OnTapGestureRecognizerTapped(object sender, EventArgs args)
{
tapCount++;
label.Text = String.Format("已經觸發 {0} 次點擊(Tap)!",
tapCount,
tapCount == 1 ? "" : "s");
var imageSender = (Image)sender;
// watch the monkey go from color to black&white!
if (tapCount % 2 == 0)
{
imageSender.Source = "tapped.jpg";
}
else
{
imageSender.Source = "tapped_bw.jpg";
}
Debug.WriteLine("image tapped: " + ((FileImageSource)imageSender.Source).File);
}
}
}
TapInsideFrame
請在核心PCL專案,使用滑鼠右擊
XFGestures
,在彈出功能表中,點選 加入
> 類別
,當出現 加入新項目 - XFGestures
對話視窗後,點選 Visual C#
> 介面
,接著在最下方的 名稱
欄位文字輸入盒中,輸入TapInsideFrame
。
接著,請將底下 C# 程式碼置換剛剛產生的介面程式碼。
TapInsideFrame.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace XFGestures
{
public class TapInsideFrame : ContentPage
{
int tapCount;
readonly Label label;
public TapInsideFrame()
{
var frame = new Frame
{
OutlineColor = Color.Accent,
BackgroundColor = Color.Transparent,
Padding = new Thickness(20, 100),
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.CenterAndExpand,
Content = new Label
{
Text = "點擊(Tap) 框架內部",
FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label))
}
};
var tapGestureRecognizer =
new TapGestureRecognizer();
//tapGestureRecognizer.NumberOfTapsRequired = 2; // double-tap
tapGestureRecognizer.Tapped += OnTapGestureRecognizerTapped;
frame.GestureRecognizers.Add(tapGestureRecognizer);
label = new Label
{
Text = " ",
FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label)),
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.CenterAndExpand
};
Content = new StackLayout
{
Children =
{
frame,
label
}
};
}
void OnTapGestureRecognizerTapped(object sender, EventArgs args)
{
tapCount++;
label.Text = String.Format("已經觸發 {0} 次點擊(Tap)!",
tapCount,
tapCount == 1 ? "" : "s");
}
}
}
TapInsideFrameXaml
請在核心PCL專案,使用滑鼠右擊
XFGestures
,在彈出功能表中,點選 加入
> 新增項目
,當出現 加入新項目 - XFGestures
對話視窗後,點選 Visual C#
> Cross-Platform
> Forms Xaml Page
,接著在最下方的 名稱
欄位文字輸入盒中,輸入 TapInsideFrameXaml
。
由於這裡產生的是一個
Forms Xaml Page
項目,因此,需要定義 XAML 內容與 code-behind 的 C# 程式碼。 接著,請將底下 C# 程式碼置換剛剛產生的介面程式碼。TapInsideFrameXaml.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XFGestures.TapInsideFrameXaml">
<StackLayout>
<Image Source="tapped.jpg" HeightRequest="150" WidthRequest="150">
<Image.GestureRecognizers>
<!-- Using the Command property works fine -->
<TapGestureRecognizer
Command="{Binding TapCommand}"
CommandParameter="Image1" />
</Image.GestureRecognizers>
</Image>
<Label Text="點擊(Tap)猴子圖片或者底下社群字體" Font="Large"
HorizontalOptions="Center">
</Label>
<StackLayout
Orientation="Horizontal"
HorizontalOptions="Center">
<Label Text=""
FontSize="60"
FontFamily="FontAwesome"
Margin="0,0,40,0"
>
<Label.GestureRecognizers>
<TapGestureRecognizer
NumberOfTapsRequired="1"
Command="{Binding TapCommand}"
CommandParameter="Frame1" />
</Label.GestureRecognizers>
</Label>
<Label Text=""
FontSize="60"
FontFamily="FontAwesome"
Margin="0,0,40,0"
>
<Label.GestureRecognizers>
<TapGestureRecognizer
NumberOfTapsRequired="2"
Command="{Binding TapCommand}"
CommandParameter="Frame1" />
</Label.GestureRecognizers>
</Label>
<Label Text=""
FontSize="60"
FontFamily="FontAwesome"
>
<Label.GestureRecognizers>
<TapGestureRecognizer
NumberOfTapsRequired="2"
Command="{Binding TapCommand}"
CommandParameter="Frame1" />
</Label.GestureRecognizers>
</Label>
</StackLayout>
<Label x:Name="label"
Text="{Binding NumberOfTapsTapped}"
Font="Large"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand"
/>
</StackLayout>
</ContentPage>
在建構式內,將這個頁面的
BindingContext
屬性,設定為 TapViewModel
這個 ViewModel 所產生的物件,這樣,在整個頁面內,就可以透過資料綁定的方式,取得 ViewModel 內的資料。TapInsideFrameXaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
[assembly: XamlCompilation(XamlCompilationOptions.Compile)]
namespace XFGestures
{
public partial class TapInsideFrameXaml : ContentPage
{
public TapInsideFrameXaml()
{
InitializeComponent();
// The TapViewModel contains the TapCommand which is wired up in Xaml
BindingContext = new TapViewModel();
}
}
}
TapViewModel
請在核心PCL專案,使用滑鼠右擊
XFGestures
,在彈出功能表中,點選 加入
> 類別
,當出現 加入新項目 - XFGestures
對話視窗後,點選 Visual C#
> 介面
,接著在最下方的 名稱
欄位文字輸入盒中,輸入TapViewModel
。
接著,請將底下 C# 程式碼置換剛剛產生的介面程式碼。
TapViewModel.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using Xamarin.Forms;
namespace XFGestures
{
/// <summary>
/// ViewModel to demonstrate binding to a Command from a GestureRecognizer
/// </summary>
/// <remarks>
/// View models can be used regardless of whether the UI is build in code or with Xaml.
/// In this example the view model is referenced by a Xaml page, but the same bindings
/// can be done in C#.
/// </remarks>
public class TapViewModel : INotifyPropertyChanged
{
ICommand tapCommand;
int taps = 0;
string numberOfTapsTapped;
public TapViewModel()
{
// configure the TapCommand with a method
tapCommand = new Command(OnTapped);
}
/// <summary>
/// Expose the TapCommand via a property so that Xaml can bind to it
/// </summary>
public ICommand TapCommand
{
get { return tapCommand; }
}
/// <summary>
/// Called whenever TapCommand is executed (because it was wired up in the constructor)
/// </summary>
void OnTapped(object s)
{
taps++;
Debug.WriteLine("parameter: " + s);
NumberOfTapsTapped = String.Format("已經觸發 {0} 次點擊(Tap)",
taps,
taps == 1 ? "" : "s");
}
/// <summary>
/// Display string that is bound to a Label on the page
/// </summary>
public string NumberOfTapsTapped
{
get { return numberOfTapsTapped; }
set
{
if (numberOfTapsTapped == value)
return;
numberOfTapsTapped = value;
OnPropertyChanged();
}
}
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
}
實際執行畫面
請再度重新執行,這個時候應用程式可以順利正常運行,螢幕截圖如下:
佈署注意事項
iOS 執行結果
請在方案總管內,滑鼠右擊
XFGestures.iOS
專案,選擇 設定為起始專案
,接著按下 F5
開始執行。
Xamarin.Forms
GestureRecognizer
類別,可以任您應用程式中的使用者介面控制項,具有處理點擊、雙指縮放、平移這些手勢操控的偵測與處理能力。