从零开始Windows Phone开发(二):第二个练习-Flashlight

今天我们在WP上来实现一个“闪光灯”,WP7上是不能控制手机自带的硬件闪光灯的,但是我们可以通过将手机屏幕设置成全白色来模拟闪光灯的效果。在这个练习里我们将实现若干种不同颜色的闪光灯,以及SOS莫斯代码闪光灯和频闪闪光灯(开关切换非常快)。

1 用户界面设计

我们预备采用ApplicationBar来放置三个图标:分别是普通闪光灯、SOS摩斯码闪光灯和频闪闪光灯,用来控制闪光灯模式;在菜单中选择闪光颜色。

1.1 ApplicationBar的图标

在应用程序项目中添加一个文件夹Images用来存放将要添加的图标文件,打开源程序中被注释起来的那段ApplicationBar的代码,准备添加图标文件。右击Images文件夹选择Add-Existing Items,在我的电脑上,自带图标存放路径是:C:\Program Files (x86)\Microsoft SDKs\Windows Phone\v7.1\Icons\dark,选择合适的图标加入,并将其生成属性改为Content

修改ApplicationBar的代码:

    <phone:PhoneApplicationPage.ApplicationBar>
        <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True" Opacity="0.5">
            <shell:ApplicationBarIconButton IconUri="/Images/appbar.basecircle.rest.png" Text="Solid" Click="SolidButton_Click"/>
            <shell:ApplicationBarIconButton IconUri="/Images/appbar.overflowdots.png" Text="SOS" Click="SosButton_Click"/>
            <shell:ApplicationBarIconButton IconUri="/Images/appbar.feature.camera.rest.png" Text="Strobe" Click="StrobeButton_Click"/>

1.2 ApplicationBar的菜单

修改ApplicationBar的菜单项,使用不同的颜色:

            <shell:ApplicationBar.MenuItems>
                <shell:ApplicationBarMenuItem Text="red"/>
                <shell:ApplicationBarMenuItem Text="orange"/>
                <shell:ApplicationBarMenuItem Text="yellow"/>
                <shell:ApplicationBarMenuItem Text="green"/>
                <shell:ApplicationBarMenuItem Text="cyan"/>
                <shell:ApplicationBarMenuItem Text="purple"/>
                <shell:ApplicationBarMenuItem Text="gray"/>
                <shell:ApplicationBarMenuItem Text="white"/>
            </shell:ApplicationBar.MenuItems>
不在每个菜单内部定义各自的Click事件是每个菜单所做的工作基本相同,所以考虑将所有的事件处理方法放到同一个方法中,通过单击的菜单项的文本信息来转化成相应的颜色,当然这里也可以指定Click方法相同,但是我们决定在代码中实现。

1.3 主界面

因为这个应用程序并不需要额外的界面,所以将整个界面简化成只有一个Grid即可:

    <!--LayoutRoot is the root grid where all page content is placed-->
    <Grid x:Name="LayoutRoot" Background="White">
    </Grid>

到这里的效果是这样的:

     

注意到最上边沿的状态栏仍然影响整体的感觉,我们可以把状态栏禁用掉,同时把朝向更改一下:

    SupportedOrientations="PortraitOrLandscape" Orientation="Portrait"
    shell:SystemTray.IsVisible="False">
现在的效果好多了:


2 业务代码实现

2.1 响应菜单事件

为每个菜单的Click事件绑定相同的方法,通过检查菜单内容转化成相应的颜色,并改变当前闪光颜色:

2.1.1 在初始化方法中加入代码为每个菜单绑定事件:

        public MainPage()
        {
            InitializeComponent();
            foreach(ApplicationBarMenuItem menuItem in this.ApplicationBar.MenuItems)
                menuItem.Click += MenuItem_Click;
        }
并同时引入命名空间:
        using Microsoft.Phone.Shell;
准备写事件处理方法:

        void MenuItem_Click(object sender, EventArgs e)
        {

        }
2.1.2 根据点击的菜单的内容获取颜色:

        string chosenColor = (sender as IApplicationBarMenuItem).Text;
        Color c = (Color)typeof(Colors).GetProperty(chosenColor, BindingFlags.Public | BindingFlags.Static | BindingFlags.IgnoreCase).GetValue(null, null);

消息处理方法的第一个参数sender是一个object类型,表示触发该事件方法的对象,因此可以转化成任何由object派生的类型,IApplicationBarMenuItem是菜单项接口类型,菜单项类实现了这个接口,这个接口有属性Text表示菜单项的内容,使用一个string对象接收文本;下一步就是由文本获取颜色了,这里使用的是反射的方法,反射就是 运行时检查和处理程序元素 的功能。typeof(Colors)得到的是一个Type对象,应用Type.GetProperty(string, Bindingflags)方法使用指定的绑定约束搜索指定属性,返回获取到的符合属性约束的值,将该值转化为Color类对象即得到实际的颜色值。

BindingFlags.Public:表示可以在搜索中包含公共属性

BindingFlags.Static:表示期望得到返回值,或使用BindingFlags.Instance

BindingFlags.IgnoreCase:表示忽略搜索文本的大小写,使得可以由"red"搜索到内置的颜色类型"Red"。

2.1.3 设置颜色

设置颜色需要系统维护一个画刷(SolidColorBrush),每次获取新的颜色时,给这个画刷赋值并填充背景。

        private SolidColorBrush onBrush;

设置颜色:

        this.onBrush = new SolidColorBrush(c);
        this.LayoutRoot.Background = onBrush;

效果如下:

           

2.2 相应图标按钮事件

首先,我们需要提供一个标识当前工作状态的枚举类型:

        enum FlashMode
        {
            Solid,
            Sos,
            Strobe
        }
        FlashMode mode = FlashMode.Solid;

2.2.1 处理事件处理方法

        private void SolidButton_Click(object sender, EventArgs e)
        {
            if (mode == FlashMode.Solid)
                return;
            else
            {
                //Solid Handle
            }
        }

        private void SosButton_Click(object sender, EventArgs e)
        {
            if (mode == FlashMode.Sos)
                return;
            else
            {
                //SOS Handle
            }
        }

        private void StrobeButton_Click(object sender, EventArgs e)
        {
            if (mode == FlashMode.Strobe)
                return;
            else
            {
                //Strobe Handle
            }
        }

我们的想法是,点击Solid图标时,恢复正常模式,静态颜色背景;点击SOS图标时,按。。。—— —— ——  。。。的方式闪光;点击Strobe图标时,快速闪光。下面分别实现:

2.2.2 SOS模式

        this.mode = FlashMode.Sos;
        this.sosStep = 0;
        this.sosTimer.Start();
开启一个定时器,周期性地输出闪光。

        int sosStep;
        DispatcherTimer sosTimer = new DispatcherTimer();
初始化代码中:
        this.sosStep = 0;
        this.sosTimer.Interval = TimeSpan.Zero;
        this.sosTimer.Tick += sosTimer_Tick;

定时器代码:

        void sosTimer_Tick(object sender, EventArgs e)
        {
            switch (this.sosStep)
            {
                case 1:
                case 3:
                case 5:
                case 13:
                case 15:
                case 17:
                    this.LayoutRoot.Background = this.onBrush;
                    this.sosTimer.Interval = TimeSpan.FromSeconds(0.3);
                    break;
                case 7:
                case 9:
                case 11:
                    this.LayoutRoot.Background = this.onBrush;
                    this.sosTimer.Interval = TimeSpan.FromSeconds(1.0);
                    break;
                case 18:
                    this.LayoutRoot.Background = this.onBrush;
                    this.sosTimer.Interval = TimeSpan.FromSeconds(1.5);
                    break;
                default:
                    this.LayoutRoot.Background = this.offBrush;
                    this.sosTimer.Interval = TimeSpan.FromSeconds(.3);
                    break;
            }
            this.sosStep = (this.sosStep + 1) % 19;
        }

2.2.2 Strobe模式

同样地,需要使用一个定时器来控制闪光,具体代码不再详细给出

2.2.3 Solid模式

关闭所有定时器,模式设置为Solid。

2.2.4 别的问题

(1)目前还存在的问题是初始化的时候无法记住上一次的选择,这需要第一天练习里的独立存储设置来实现;

(2)动态更换图标的问题,在点击图标后,需要动态地改变显示的图标,可以这样实现:

(sender as IApplicationBarIconButton).IconUri = new Uri("Images/other.png", UriKind.Relative);

(3)使用反射是一个比较耗时的操作。

3 总结

本练习中学习的主要知识点有:

(1)ApplicationBar的操作,动态处理内容的方法(重新指定Uri的值)。

(2)DispatcherTimer使用定时器的方法,相关联的有Interval变量,Tick事件和Start、Stop方法,以及TimeSpan的用法。

(3)SolidColorBrush的用法,Color与Colors的区别(后者是一个预定义颜色的集合),

(4)处理事件相应方法中的sender参数的方法以及简单的反射方法

(5)没有在例子中出现的,MessageBox的用法:

 MessageBox.Show("Oh Lod!", "Warning!", MessageBoxButton.OKCancel);

效果是这样的:

如果我们需要改写按钮上的文字或者重写按钮事件,可以这样实现:

引入命名空间:

using Microsoft.Xna.Framework.GamerServices;

这里需要在项目引用中添加Microsoft.Xna.Framework.GamerServices才能识别

然后利用这两个函数实现自定义操作:

调用消息框出现:

Guide.BeginShowMessageBox("Warning!", "Oh My Lod!", new string[] { "Left", "Right" }, 0, MessageBoxIcon.Warning, new AsyncCallback(OnMessageBoxClosed), null);
关闭消息框回调方法:

        void OnMessageBoxClosed(IAsyncResult result)
        {
            int? buttonIndex = Guide.EndShowMessageBox(result);
            if (buttonIndex == 1) //确定
                //处理确定事件
                return;
            else if (buttonIndex == 2) //取消
                //处理取消事件
                return;
            else //按了硬件的返回键
                return;
        }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值