在进入Xamarin.Forms之前,最好了解一些平台的基础信息。第一个应用程序是Hello Android! App,它是使用Blank App(Android)模板创建的。
应该检查的第一个设置是Android Manifest,可以从Project Properties选项卡中的Android Manifest上访问它(请参见下图)。在这里,需要定义Android的最低版本和目标版本,这与前面章节中的Windows运行库配置类似。这里需要选择应用程序支持的API级别。根据想要支持的设备,可以使用可用的功能。
1. 活动
使用Android时,用户界面屏幕会映射到一个活动上。为每个视图创建一个活动。Android开发利用了MVC(模式-视图-控制器)模式。活动类是控制器。代码示例显示了MainActivity——即主视图的活动。每个活动都来自Activity类或从Activity派生的类。通过这个类,可以重写由Activity基类提供的生命周期方法。在创建活动时,调用OnCreate方法。
调用方法SetContentView,会定义为此活动定义的用户界面。UI在资源中定义,如下一节所述:
[Activity(Label = "@string/app_name", Theme = "@style/AppTheme.NoActionBar", MainLauncher = true)]
public class MainActivity : AppCompatActivity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
//Xamarin.Essentials.Platform.Init(this, savedInstanceState);
SetContentView(Resource.Layout.activity_main);
}
}
该活动定义了Android应用程序的生命周期。下表列出了活动的生命周期方法。
3. 资源
在Solution Explorer中,可以看到Resources文件夹带有多个子文件夹。drawalbe文件夹用于存储图像。视图在layout文件夹中定义,values文件夹包含简单的字符串。
在示例代码中,字符串资源被更新,以包含用于按钮文本、应用程序名称和hello标志的字符串。
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<string name="app_name">AndroidBaseSample2</string>
<string name="action_settings">Settings</string>
<string name="main_button1_text">Click Me!</string>
<string name="hello">Hello Android!</string>
<string name="somedata_clickeditem_title">Clicked Item</string>
</resources>
视图是使用AXML文件定义的,它与XAML文件有相似之处。LinearLayout是一种安排子元素的布局控件。可以将LinearLayout与StackPanel类进行比较,它具有相同的功能。在示例应用程序中,在布局内部添加一个按钮控件,可以将按钮控件从从工具箱拖动到设计器。带有属性的android前缀是名称空间http://schemas.android.com/apk/res/android的别名。对于按钮,text设置为字符串资源中的资源字符串main_button1_text,宽度设置为与父节点的宽度相匹配,高度设置为换行,以免一行放不下。将id分配给 @+id/button1 ,会创建一个新的ID,名称@+id/button1是在设计器生成的文件Resource.Designer.cs中创建新ID来访问按钮的快捷方式:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/button1"
android:text="@string/main_button1_text"/>
</RelativeLayout>
在活动中,可以使用基类Activity中的FindViewById方法访问按钮控件,通过Reource.Id.button1引用传递的ID。在代码片段中,检索按钮,以添加单击事件处理程序。处理程序的实现代码向用户显示一个通知:
public class MainActivity : AppCompatActivity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.activity_main);
Button button1 = FindViewById<Button>(Resource.Id.button1);
button1.Click += (sender,e) =>
{
Toast.MakeText(ApplicationContext,"Hello Android",ToastLength.Long).Show();
};
}
在模拟器或物理设备上运行应用程序时,按钮会显示,可以单击它,会看到一个toast,如下图所示。
3. 显示列表
一个常见的场景是导航到页面,并显示列表。这是通过应用程序的下一个增强来显示的。为此,先创建一个模型。
(1). 定义模型
该模型是一个简单的类,定义了一些属性并重写了ToString()方法。
public class SomeData
{
public int Number { get; set; }
public string Text { get; set; }
public override string ToString() => $"{Number} {Text}";
}
(2). 使用ListActivity
接下来,创建一个活动。现在使用ListActivity基类,而不是从Activity基类中派生活动。ListActivity定义了用于在列表中选择项的虚属性和方法。在创建SomeDataListActivity时,将创建一个包含示例数据的集合,并将其存储在_items字段中。在OnCreate方法中,SomeDataListAdapter的一个新实例也分配给基类的ListAdapter属性。在MainActivity中,活动的用户界面由使用SetContentView的资源定义。这里,使用适配器来提供用户界面。该活动还定义了重写方法OnListItemClick,以显示所选项:
[Activity(Label ="SomeDataListActivity")]
public class SomeDataListActivity:ListActivity
{
private IList<SomeData> _items;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
_items = Enumerable.Range(0, 100)
.Select(i => new SomeData
{
Number = i,
Text = $"sample{i}"
})
.ToList();
ListAdapter = new SomeDataListActivity(this,_items);
}
protected override void OnListItemClick(ListView l, View v, int position, long id)
{
base.OnListItemClick(l, v, position, id);
//...implementation of the OnListItemClick event handler.
}
}
(3). 实现一个适配器
SomeDataListAdapter用于为SomeDataListAcitivity定义UI。这个类的核心是重写方法GetView,它需要返回列表中每一项的视图。该方法接收父ViewGroup,其中将显示该项的视图。
SomeDataListAdapter用于为SomeDataListActivity定义UI。这个类的核心是重写方法GetView,它需要返回列表中每一项的视图。该方法接收父ViewGroup,其中将显示该项的视图。LayoutInflater将AXML文件放大到一个视图中。可以为资源中的项创建视图。代码示例为Android使用一个预定义的AXML文件。Android.Resource.Layout.SimpleListItem1返回预定义AXML文件的ID。这个布局使用TextView元素定义一个简单的项。TextView元素使用FindViewById来访问,其中Text属性分配给项中的信息:
public class SomeDataListAdapter:BaseAdapter
{
private readonly Activity __activity;
private readonly IList<SomeData> _items;
public SomeDataListAdapter(Activity activity,IList<SomeData> itemms)
{
__activity = activity;
_items = itemms;
}
public override int Count => _items.Count;
public override Java.Lang.Object GetItem(int position) => position;
public override long GetItemId(int position) => position;
public override View GetView(int position, View convertView, ViewGroup parent)
{
var view = convertView;
if (view == null)
{
view = __activity.LayoutInflater.Inflate(Android.Resource.Layout.SimpleListItem1,null);
}
view.FindViewById<TextView>(Android.Resource.Id.Text1).Text =
$"{_items[position].Number}: {_items[position].Text}";
return view;
}
}
注意:
要了解SimpleListItem1和其他预定义布局是如何定义的,请参阅https://github.com/aosp-mirror/platform_frameworks_base/tree/master/core/res/res/layout。
4. 用Android导航
要导航到SomeDataListActivity,对于Android,需要启动活动,并传递活动类型。这是在MainActivity的StartActivity中完成的:
Button button2 = FindViewById<Button>(Resource.Id.button2);
button2.Click += (sender, e) =>
{
StartActivity(typeof(SomeDataListActivity));
};
运行该应用程序时,可以看到从SomeDataListAdapter返回的条目列表,其中包含预定义的SimpleListItem1,如下图所示。
4. 显示消息
在Android应用程序的第一个按钮上,在单击该按钮后,就会显示Toast。如何从Xamarin.Android中显示像UWP中MessageDialog这样的东西?对于Android,可以使用AlertDialog。单击列表中的项时,会使用这个对话框。
在使用对话框之前,需要创建它。要创建AlertDialog,需要实例化内部Builder类。使用AlertDialog.Builder,可以使用SetMessage定义要显示的消息,并使用SetTitle来定义要显示的标题。为了定义应显示的按钮,Builder类定义了一些方法,例如SetNenutralButton、SetPositiveButton和SetNegativeButton。甚至可以创建多选项SetMultiChoiceItems。在代码片段中,SetNeutralButton是使用预定义的资源字符串Android.Reource.String.Ok来设置的。在配置构建器后,AlertDialog将从Builder的Create方法中创建。最后,需要调用Show方法来显示对话框:
protected override void OnListItemClick(ListView l, View v, int position, long id)
{
base.OnListItemClick(l, v, position, id);
//...implementation of the OnListItemClick event handler.
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.SetMessage($"clicked {_items[position]}")
.SetTitle(Resource.String.somedata_clickeditem_title);
builder.SetNeutralButton(Android.Resource.String.Ok,(sender,e)=>
{
//user clicked the ok button
});
AlertDialog dialog = builder.Create();
dialog.Show();
}
运行该应用程序,AlertDialog如下图所示。
用Android构建应用程序提供了一些有趣的方面,但其开发与创建Windows应用程序非常不同。与iPhone相似的场景是怎样的呢?