【Android】2.1 PhonewordApp—第1个Android应用程序

分类:C#、Android、VS2015;  创建日期:2016-02-04

本例子演示如何添加一个简单的单页导航,在此基础上,再演示如何在第2个页面中显示第1个页面中拨打过的所有电话号码。

(1)通过该例子理解Android App的基本架构。

(2)通过该例子理解实现Android多屏幕导航的基本技术。

本例子只是为了让我们对Android App开发有一个较全面的感性认识,读者不必一开始就纠结于代码中的细节问题,涉及到的相关概念在后面还会分别介绍。

运行截图

运行截图(Api19、Api21、Api23的实现代码都相同):

 

界面操作

单击“将文本转换为数字”,观察结果。

单击【转换】按钮,如果转换成功,则【拨号】按钮可用,单击【拨号】按钮,观察弹出的对话框。

如果单击【拨号】按钮,就会自动拨号。

 

下面介绍主要设计步骤。

1、新建项目

选择模板:Blank App (Android),项目名:PhonewordApp。

项目创建成功后,删除GettingStarted.Xamarin(广告文件)。

2、界面设计

(1)双击打开Main.axml,分别观察设计界面【Design】和源码【Source】的内容。

 

(2)按Delete键删除【Hello World,Click Me】按钮。

(3)从【工具箱】中拖放一个【Text (Large)】到设计界面,修改下面的属性:

    id:@+id/PhoneText

    text:电话

注:此时系统会自动在【Source】中添加对应的代码(下同)。

(4)从【工具箱】中拖放一个【Plain Text】到设计界面,放到【Text (Large)】的下方,修改下面的属性:

    id:@+id/PhoneNumberText

    text:138 4912 2599

(5)从【工具箱】中拖放一个【Button】到设计界面,放到【Plain Text】的下方,修改下面的属性:

    id:@+id/buttonTranslate

    text:转换

(6)从【工具箱】中拖放一个【Button】到设计界面放到上一个按钮的下方,修改属性:

    id:@+id/buttonCall

    text:拨号

经过以上步骤后,即得到下图所示的设计界面:

(7)保存文件,并单击【解决方案资源管理器】上方的【刷新】按钮。

注意:这一步的目的是为了让系统能找到设计界面内的资源并自动生成对应的ID,以便在后面键入C#代码时能看到与设计界面资源相关的智能提示。

3、编写C#代码

(1)鼠标右击项目名à添加类,在弹出的窗口中,选择【Class】模板,名称:PhoneTranslator.cs,如下图所示,单击【添加】按钮。

然后将PhoneTranslator.cs改为下面的代码:

using System.Text;
namespace PhonewordApp
{
    public static class PhonewordTranslator
    {
        public static string ToNumber(string raw)
        {
            if (string.IsNullOrWhiteSpace(raw))
            {
                return "";
            }
            else
            {
                raw = raw.ToUpperInvariant();
            }
            var newNumber = new StringBuilder();
            foreach (var c in raw)
            {
                if ("- 0123456789".Contains(c))
                    newNumber.Append(c);
                else
                {
                    var result = TranslateToNumber(c);
                    if (result != null)
                        newNumber.Append(result);
                }
            }
            return newNumber.ToString();
        }

        static bool Contains(this string keyString, char c)
        {
            return keyString.IndexOf(c) >= 0;
        }

        static int? TranslateToNumber(char c)
        {
            if ("ABC".Contains(c))
                return 2;
            else if ("DEF".Contains(c))
                return 3;
            else if ("GHI".Contains(c))
                return 4;
            else if ("JKL".Contains(c))
                return 5;
            else if ("MNO".Contains(c))
                return 6;
            else if ("PQRS".Contains(c))
                return 7;
            else if ("TUV".Contains(c))
                return 8;
            else if ("WXYZ".Contains(c))
                return 9;
            return null;
        }
    }
}

(2)打开MainActivity.cs,将该文件改为下面的代码:

using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using System.Collections.Generic;
namespace PhonewordApp
{
    [Activity(Label = "PhonewordApp", 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);
            SetContentView(Resource.Layout.Main);

            var phoneNumberText = FindViewById<EditText>(Resource.Id.PhoneNumberText);
            var buttonTranslate = FindViewById<Button>(Resource.Id.buttonTranslate);
            var buttonCall = FindViewById<Button>(Resource.Id.buttonCall);
            buttonCall.Enabled = false;  //禁用【拨号】按钮

            string translatedNumber = string.Empty;
            buttonTranslate.Click += (s, e) =>
            {
                translatedNumber = PhonewordTranslator.ToNumber(phoneNumberText.Text);
                if (string.IsNullOrWhiteSpace(translatedNumber))
                {
                    buttonCall.Text = "拨号";
                    buttonCall.Enabled = false;
                }
                else
                {
                    buttonCall.Text = "播出号码:" + translatedNumber + ",单击确认!";
                    buttonCall.Enabled = true;
                }
            };

            var buttonCallHistory = FindViewById<Button>(Resource.Id.buttonCallHistory);
            buttonCallHistory.Click += (sender, e) =>
            {
                var intent = new Intent(this, typeof(CallHistoryActivity));
                intent.PutStringArrayListExtra("phone_numbers", phoneNumbers);
                StartActivity(intent);
            };

            buttonCall.Click += (s, e) =>
            {
                phoneNumbers.Add(translatedNumber);
                buttonCallHistory.Enabled = true;
                // 当单击【拨号】时,尝试拨号
                var callDialog = new AlertDialog.Builder(this);
                callDialog.SetMessage("电话:" + translatedNumber + ",拨号吗?");
                callDialog.SetNeutralButton("拨号", delegate
                {
                    var callIntent = new Intent(Intent.ActionCall);
                    callIntent.SetData(Android.Net.Uri.Parse("tel:" + translatedNumber));
                    StartActivity(callIntent);
                });
                callDialog.SetNegativeButton("取消", delegate { });
                callDialog.Show();
            };

        }
    }
}

(3)重新生成项目,确保无错误。

注:drawable文件夹下的Icon.png是要显示的图标,也可将其换为其他图标文件。

(4)选择主菜单下该项目的属性,在弹出的窗口中,勾选【CALL PHONE】权限:

注:

(1)这一步必须做,否则因该App无拨号权限,拨号功能会失败。

(2)设置后,查看Properties文件夹下AndroidManifest.xml文件中自动添加的代码,理解权限设置的作用。

4、调试运行及代码片段解释

选择一种模拟器,然后按<F5>键调试运行。

注意:如果使用低于API 23的模拟器,必须设置项目属性(主菜单à项目属性),使用对应版本的API来编译应用程序,否则在模拟器上运行时可能会出现应用程序一闪就退出或者显示“应用程序已停止运行”的情况。

 

下面解释前面已经实现的代码片段的含义:

(1)如何显示Alert对话框

AlertDialog的详细用法见【第6章  UI设计(三)--对话框】。

(2)如何拨号

下面的代码演示了如何调用系统功能实现拨号:

var callIntent = new Intent(Intent.ActionCall);

callIntent.SetData(Android.Net.Uri.Parse("tel:" + translatedNumber));

StartActivity(callIntent);

 

注意:运行前需要先勾选【CALL PHONE】设置允许拨号权限,否则运行会出现异常:

5、创建第2个屏幕跟踪历史记录

(1)打开values文件夹下的Strings.xml文件,添加下面的代码:

<?xml version="1.0" encoding="utf-8"?>

<resources>

    ……

    <string name="CallHistory">拨号记录</string>

</resources>

(2)单击【解决方案资源管理器】上方的“刷新”按钮,或者重新生成项目。

注:选择其中之一即可,目的是为了让C#代码能识别它。

(3)打开Main.axml,从【工具箱】中拖放一个【Button】到Main.axml设计界面,将其放到上一个按钮的下方,修改属性:

    id:@+id/buttonCallHistory

    text:@string/CallHistory

    enabled:false

注:@string/CallHistory的含义是在values文件夹下的Strings.xml文件中提供该变量的值。

此时,可看到“STRING/CALLHISTORY”会自动变成“拨号记录”。

说明:这一步设置变量值的做法是实际的Android App项目中建议的做法,这样做的好处是能提高安卓App运行的效率。而步骤1的做法是一种硬编码的做法,硬编码在安卓App中不是建议的做法,步骤1只是为了刚入门时理解更容易。

(4)鼠标右击项目名,选择【添加…】à【新建项】,在弹出的窗口中,选择“Activity”模板,文件名:CallHistoryActivity.cs,单击【添加】。然后将该文件改为下面的内容(省略了using……):

namespace PhonewordApp

{

    [Activity(Label = "CallHistoryActivity")]

    public class CallHistoryActivity : ListActivity

    {

        protected override void OnCreate(Bundle bundle)

        {

         base.OnCreate(bundle);

         var phoneNumbers =

            Intent.Extras.GetStringArrayList("phone_numbers") ?? new string[0];

         this.ListAdapter = new ArrayAdapter<string>(this,

            Android.Resource.Layout.SimpleListItem1, phoneNumbers);

        }

    }

}

其中,c = a??b; 的含义相当于:if (a != null ){ c = a;} else { c = b;}

(5)修改MainActivity.cs文件,目标是收集第1个屏幕界面运行时拨打过的所有电话号码,并将其在第2个屏幕上显示出来。在MainActivity.cs文件中添加下面的代码:

……

using System.Collections.Generic;

namespace E01PhonewordApp

{

    [Activity(Label = "E01PhonewordApp", MainLauncher = true, Icon = "@drawable/icon")]

    public class MainActivity : Activity

    {

        static readonly List<string> phoneNumbers = new List<string>();

        protected override void OnCreate(Bundle bundle)

        {

            ……

 

            var buttonCallHistory =

                FindViewById<Button>(Resource.Id.buttonCallHistory);

            buttonCallHistory.Click += (sender, e) =>

            {

                var intent = new Intent(this, typeof(CallHistoryActivity));

                intent.PutStringArrayListExtra("phone_numbers",

                      phoneNumbers);

                StartActivity(intent);

            };

 

            buttonCall.Click += (s, e) =>

            {

                phoneNumbers.Add(translatedNumber);

                buttonCallHistory.Enabled = true;

                // 当单击【拨号】时,尝试拨号

                var callDialog = new AlertDialog.Builder(this);

                callDialog.SetMessage("播出号码:" + translatedNumber +

                   ",拨号吗?");

                callDialog.SetNeutralButton("拨号", delegate

                {

                    // Create intent to dial phone

                    var callIntent = new Intent(Intent.ActionCall);

                    callIntent.SetData(Android.Net.Uri.Parse("tel:" +

                        translatedNumber));

                    StartActivity(callIntent);

                });

                callDialog.SetNegativeButton("取消", delegate { });

                callDialog.Show();

            };

        }

    }

}

(6)重新生成项目,确保无错误。

(7)运行,再拨一个号(例如12345678901),然后查看拨号记录。下图是用另一种模拟器查看的运行效果(你可以创建多种不同的模拟器,分别观察同一个项目的运行效果):

到这里,我们就完成了用C#编写的第1个Android应用程序。

posted @ 2016-02-04 05:28  rainmj  阅读(4028)  评论(1编辑  收藏  举报