Build apps with native UI using Xamarin in Visual Studio
Bài đăng này đã không được cập nhật trong 8 năm
<script>
alert("OK");
</script>
<script>
alert("OK");
</script>
Có lẽ cái tên Xamarin không còn xa lạ với dân làm native. Đúng vậy, Xamarin là một công cụ tuyệt vời, nó cho phép bạn phát triển các ứng dụng Android hoặc iOS bằng ngôn ngữ C#
Với gói công cụ của Xamarin, lập trình viên có thể viết các ứng dụng hoàn toàn bằng C# đồng thời chia sẻ các mã lập trình tương tự lên iOS, Android, Windows và Mac.
Ngoài ra, lập trình viên cũng có thể tái sử dụng thư viện .NET trong khi vẫn có thể dễ dàng tích hợp các thư viện và khung phát triển đặc trưng của từng nền tảng.
Xamarin cũng cung cấp các đoạn mã soạn sẵn hiệu năng cao với khả năng truy xuất vào tất cả các hàm API nội trú để lập trình viên có thể phát triển các ứng dụng nội trú (native app) tùy theo trải nghiệm của thiết bị. Mọi thứ lập trình viên cần phải làm với Objective-C hay Java đều có thể được thực hiện bằng C# với Xamarin.
Ở bài viết này, tôi sẽ hướng dẫn các bạn xây dựng một app đơn giản sử dụng Xamarin.
Trước tiên, các bạn phải setup môi trường và các công cụ cần thiết. Có thể làm theo hướng dẫn ở link này https://msdn.microsoft.com/en-us/library/mt613162.aspx
**Setup môi trường ở đây ** https://msdn.microsoft.com/en-us/library/mt488769.aspx
Ở đây tôi sử dụng Visual Studio 2015 làm tool để build app
Để bắt đầu tạo một ứng dụng Android bằng Xamarin Studio (nếu cần trình IDE mạnh mẽ hơn thì có thể dùng Visual Studio) ta vào File
-> New
-> Solution
-> Chọn Android Application -> Đặt tên cho Solution
Giao diện làm việc và cấu trúc project của một ứng dụng Xamarin Android
Nếu đã từng phát triển ứng dụng Android thuần với ngôn ngữ Java, ta dễ dàng thấy được cấu trúc thư mục và tập tin ở project Xamarin Android với Android thuần là hoàn toàn tương tự – có thể nói là giống nhau ngoại trừ code logic thuần được viết bằng Java (vd: MainActivity.java) còn với Xamarin thì được viết bằng C# (vd: MainActivity.cs)
Thực thi ứng dụng
Để thực thi ứng dụng ta chọn thiết bị hoặc máy ảo phù hợp, chọn chế độ debug, và click Start
Các thành phần của project
Trong project của ứng dụng Xamarin Android có các thành phần cơ bản sau:
- References: Chứa các thư viện được Import vào project, bao gồm Mono Android, .Net BCL, và các thư viện bên thứ ba mà nhà phát triển thêm vào.
- Components: Là các thư viện thực thi (linh kiện), mà nhà phát triển có thể thêm vào từ Xamarin Components Store (có miễn phí và trả phí)
- Assets: Thư mục chưa các tập tin raw, được đính kèm theo ứng dụng khi thực thi, mà nhà phát triển có thể truy cập đến bất kỳ lúc nào (vd: mở một file Assets.Open(“my_asset.txt”)
- Resources: Chứa các tập tin tài nguyên của ứng dụng như layout, hình ảnh,… (giống với thư mục res trong Android thuần)
- AndoridManifest.xml: Lưu trữ các thông số và cấu hình của ứng dụng, như tên, phiên bản, target version, permission,…
Ứng dụng HelloWorld
Mặc định Xamarin sẽ tạo một ứng dụng mẫu gồm 1 Activity (Main), trên giao diện sẽ có 1 Button “Click Me!”, khi click vào Button đó thì chướng trình sẽ đếm số lần click và hiển thị lên Button.
Tập tin Layout “Main.xml”
Định nghĩa giao diện người dùng (User Interface) của trang chính, nội dung source:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<Button
android:id="@+id/myButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/hello" />
</LinearLayout>
Layout được xây dựng không khác gì so với Android thuần.
LinearLayout là một dạng layout container – dùng để chứa các control khác – các control trong nó được sắp xếp theo dạng Stack (lần lượt từ trên xuống – vertical hoặc từ trái sang phải – horizontally
Một Button được tạo bên trong có id là “myButton” và hiển thị nội dung ứng với “string/hello” trong Resources/Values/String.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">Hello World, Click Me!</string>
<string name="app_name">HelloWorld</string>
</resources>
Ngoài việc định nghĩa giao diện bằng cách nhập các đoạn code xml như trên ta cũng có thể sử dụng giao diện trực quan để “vẽ” UI
Tập tin MainActivity.cs
using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
namespace HelloWorld
{
[Activity (Label = "HelloWorld", MainLauncher = true, Icon = "@drawable/icon")]
public class MainActivity : Activity
{
int count = 1;
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
// Set our view from the "main" layout resource
SetContentView (Resource.Layout.Main);
// Get our button from the layout resource,
// and attach an event to it
Button button = FindViewById<Button> (Resource.Id.myButton);
button.Click += delegate {
button.Text = string.Format ("{0} clicks!", count++);
};
}
}
}
Là tập tin chứa code logic miêu tả và thực thi chương trình chính. Nội dung:
Class MainActivity: Kế thừa thừa Android.App.Activity được định nghĩa các tham số cơ bản như: Label (nhãn), Icon (biểu tượng) và MainLauncher (trình thực thi chính – khi app chạy thi thì tập tin này sẽ thực thi đầu tiên)
Theo Chu trình sống của App (Application Life Cycle) – sẽ tìm hiểu ở phần sau – thì khi Activity khởi tạo thì sẽ gọi phương thức OnCreate, do vậy trong OnCreate sẽ là những đoạn lệnh dùng để khởi tạo các giá trị chính của Activity như:
- SetContentView: Chọn Layout cho Activity, ở đây đang chọn layout Main (định nghĩa trong tập tin Resources/Layout/Main.xml)
- Get Button có Id là “myButton” bằng phương thức FindViewById
- Xử lý sự kiện Click cho “myButton”
Ứng dụng: Phoneword
Ta sẽ tìm hiểu một ứng dụng mẫu của Xamarin có tên là Phoneword, ứng dụng gồm có 2 màn hình, màn hình chính sẽ “dịch” một đoạn text sang số điện thoại và cho phép người dùng call tới số đó, màn hình thứ 2 sẽ chứa lịch sử các cuộc gọi.
Các thành phần của project Phoneword
- Resources\layout\Main.xml định nghĩa UI cho trang chính
- Resources\values\Strings.xml khai báo các chuỗi ký tự sử dụng trong App
- MainActivity.cs code xử lý trang chính
- CallHistoryActivity.cs code xử lý trang thứ hai
- PhoneTranslator.cs chứa thuật toán dịch “phoneword”
- Ngoài ra để ứng dụng có thể thực hiện cuộc gọi, thì trong Manifest phải bật CallPhone ở mục
- Required permisssions
Trang chính
Nội dung tập tin Main.xml, Control được bố trí trong LinearLayout, sắp xếp theo thứ tự từ trên xuống gồm:
- TextView để hiển thị đoạn caption “Enter…”
- EditText dùng để nhập liệu
- Button đảm nhiệm 3 nhiệm vụ khác nhau.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:text="Enter a Phoneword:"
android:textAppearance="?android:attr/textAppearanceLarge"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/textView1" />
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/PhoneNumberText"
android:text="1-855-XAMARIN" />
<Button
android:text="Translate"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/TranslateButton" />
<Button
android:text="Call"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/CallButton" />
<Button
android:text="@string/callHistory"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/CallHistoryButton"
android:enabled="false" />
</LinearLayout>
Ta cũng có thể dùng giao diện trực quan để thiết kế UI bằng cách kéo thả các control trong Form Widgets và chọn các thuộc tính cho chúng trong Properties
Khởi tạo MainActivity.cs
using System;
using System.Collections.Generic;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
namespace Phoneword_Droid
{
[Activity(Label = "Phoneword", MainLauncher = true, Icon = "@drawable/icon")]
public class MainActivity : Activity
{
static readonly List<string> phoneNumbers = new List<string>();
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
// Get our UI controls from the loaded layout
Button translateButton = FindViewById<Button>(Resource.Id.TranslateButton);
EditText phoneNumberText = FindViewById<EditText>(Resource.Id.PhoneNumberText);
Button callButton = FindViewById<Button>(Resource.Id.CallButton);
Button callHistoryButton = FindViewById<Button> (Resource.Id.CallHistoryButton);
}
}
}
- Tạo class MainActivity kế thừa Android.App.Activity, set các thuộc tính cơ bản như Label, Icon và cho MainLauncher = true để khi người dùng mở app thì Activity này sẽ được khởi động.
- Tạo một static List string phoneNumbers để chứa danh sách các số mà người dùng đã gọi
- Trong phương thức OnCreate của Activity ta set layout cho MainActivity là Layout.Main với phương thức SetContentView
- Tiếp theo là get các đối tượng/control từ layout bằng FindViewById
Xử lý sự kiện Click cho button Translate
Trong OnCreate ta thêm đoạn code xử lý sự kiện Click cho button Transtlate như sau Xem PhoneTranslator.cs để biết thuật toán chuyển đối Phoneword.
string translatedNumber = string.Empty;
translateButton.Click += delegate
{
translatedNumber = Core.PhonewordTranslator.ToNumber(phoneNumberText.Text);
if (String.IsNullOrWhiteSpace(translatedNumber)) {
callButton.Text = "Call";
callButton.Enabled = false;
}
else {
callButton.Text = "Call " + translatedNumber;
callButton.Enabled = true;
}
};
Khi click vào button Translate chương trình sẽ dùng thuật toán ToNumber được viết trong PhoneTranslator.cs để chuyển các ký tứ được nhập vào ô phoneNumberText thành dạng số điện thoại. Nếu chuyển thành công thí số điện thoại sẽ được lưu vào một biến string – translatedNumber và đính vào Text của button Call.
Xử lý sự kiện Click cho button Call
Trong OnCreate ta tiếp tục xử lý sự kiện khi click vào button Call, ứng dụng sẽ hỏi xem người dùng có muốn gọi tới số máy đã dịch không, nếu chọn call thì sẽ gọi. Để làm việc đó ta sử dụng AlertDialog và Intent.ActionCall, lưu ý là phải bật CallPhone trong Manifest-Permisssions, code chi tiết và mô tả bên dưới.
// Add callButton event handler here
callButton.Click += (sender, e) =>
{
// On "Call" button click, try to dial phone number.
var callDialog = new AlertDialog.Builder(this);
callDialog.SetMessage("Call " + translatedNumber + "?");
callDialog.SetNeutralButton("Call", delegate
{
// add dialed number to list of called numbers.
phoneNumbers.Add(translatedNumber);
// enable the Call History button
callHistoryButton.Enabled = true;
// Create intent to dial phone
var callIntent = new Intent(Intent.ActionCall);
callIntent.SetData(Android.Net.Uri.Parse("tel:" + translatedNumber));
StartActivity(callIntent);
});
callDialog.SetNegativeButton("Cancel", delegate { });
// Show the alert dialog to the user and wait for response.
callDialog.Show();
};
Tập tin CallHistoryActivity.cs
using System;
using System.Collections.Generic;
using Android.App;
using Android.OS;
using Android.Widget;
namespace Phoneword_Droid
{
[Activity(Label = "@string/callHistory")]
public class CallHistoryActivity : ListActivity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Create your application here
}
}
}
Ta thấy CallHistoryActivity kế thừa một Activity được xây dựng sẵn là ListActivity, hiển thị một danh sách các items từ data, như array hay Cursor, kèm theo event khi người dùng chọn một item nào đó. Do đó không nhất thiết ta phải xây dựng layout cho Activity này.
Chuyển đổi màn hình
Để chuyển đổi màn hình/activity ta có thể dùng cách tạo một Intent mới và cho khởi động nó như sau:
var intent = new Intent(this, typeof(CallHistoryActivity));
StartActivity(intent);
csharp]
Ngoài ra để truyền dữ liệu sang Intent mới ta dùng các phương thức <strong>PutExtra</strong>, ví dụ để put vào một ArrayList ta làm như sau:
intent.PutStringArrayListExtra("phone_numbers", phoneNumbers);
Sang màn hình mới để lấy dữ liệu Extra ta dùng
var phoneNumbers = Intent.Extras.GetStringArrayList("phone_numbers") ?? new string[0];
Như vậy nội dung code hoàn chỉnh về việc xử lý sự kiện Click của button Call History và phương thức khởi tạo của CallHistoryActivity là:
callHistoryButton.Click += (sender, e) =>
{
var intent = new Intent(this, typeof(CallHistoryActivity));
intent.PutStringArrayListExtra("phone_numbers", phoneNumbers);
StartActivity(intent);
};
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Create your application here
var phoneNumbers = Intent.Extras.GetStringArrayList("phone_numbers") ?? new string[0];
this.ListAdapter = new ArrayAdapter<string>(this, Android.Resource.Layout.SimpleListItem1, phoneNumbers);
}
Để gán data source cho ListActivity ta gán thuộc tính ListAdapter của nó bằng một ArrayAdapter dạng string, có dữ liệu lấy từ list phoneNumbers ở MainActivity và có kiểu hiển thị là SimpleListItem1 được xây dựng sẵn. (dòng code cuối)
Nhấn Start và khởi động ứng dụng với Emulator hoặc thiết bị của bạn.
Kết luận: Ở bài viết này tôi đã hướng dẫn các bạn tạo một APP đơn giản với Xamarin. Các bạn hãy làm theo hướng dẫn trên máy của mình. Chúc các bạn học tốt
All rights reserved