第十五章:交互式界面(十)

简介:

入口属性和活动
除了从InputView继承Keyboard属性之外,Entry还定义了另外四个属性,其中只有一个属性在上一个程序中看到:

  • Text - 条目中显示的字符串
  • TextColor - 颜色值
  • IsPassword - 一种布尔值,可以在输入字符后立即屏蔽字符
  • Placeholder - 条目中显示的浅色文本,但在用户开始输入后立即消失。

通常,程序通过访问Text属性来获取用户键入的内容,但程序也可以初始化Text属性。 也许程序希望建议一些文本输入。
Entry还定义了两个事件:

  • TextChanged
  • Completed

Text属性的每次更改都会触发TextChanged事件,这通常对应于每次击键(shift和一些特殊键除外)。 程序可以监视此事件以执行有效性检查。 例如,您可以检查有效数字或有效电子邮件地址以启用“计算”或“发送”按钮。
当用户按下键盘上的特定键以指示文本已完成时,将触发Completed事件。 此密钥是特定于平台的:

  • iOS:密钥标记为return,不在电话或数字键盘上。
  • Android:键是键盘右下角的绿色复选标记。
  • WindowsPhone:键是大多数键盘上的输入(或返回)符号(↵),但在Url键盘上是一个符号(→)。 电话和数字键板上没有这样的键。

在iOS和Android上,完成的键除了生成Completed事件外还会解除键盘。 在Windows 10 Mobile上它没有。
Android和Windows用户也可以使用纵向屏幕左下角的手机“后退”按钮来关闭键盘。 这会导致Entry失去输入焦点,但不会导致Completed事件触发。
让我们编写一个名为QuadraticEquations的程序来求解二次方程,它是以下形式的方程式:
axx + bx + c = 0
对于任何三个常数a,b和c,程序使用二次方程求解x:
x = (-b + sqrt(b*b-4ac)/2a) 或者
x = (-b - sqrt(b*b-4ac)/2a)
在三个Entry视图中输入a,b和c,然后按一个标记为Solve for x的按钮。
这是XAML文件。 不幸的是,数字键盘不适合这个程序,因为在所有三个平台上它都不允许输入负数。 因此,没有指定特定的键盘:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="QuadaticEquations.QuadraticEquationsPage">
    <ContentPage.Resources>
        <ResourceDictionary>
            <Style TargetType="Label">
                <Setter Property="FontSize" Value="Medium" />
                <Setter Property="VerticalOptions" Value="Center" />
            </Style> 
            <Style TargetType="Entry">
                <Setter Property="WidthRequest" Value="180" />
            </Style>
        </ResourceDictionary>
    </ContentPage.Resources>
    <StackLayout>
        <!-- Entry section -->
        <StackLayout Padding="20, 0, 0, 0"
                     VerticalOptions="CenterAndExpand"
                     HorizontalOptions="Center">
            <StackLayout Orientation="Horizontal">
                <Entry x:Name="entryA"
                       TextChanged="OnEntryTextChanged"
                       Completed="OnEntryCompleted" />
                <Label Text=" x&#178; +" />
            </StackLayout>
            <StackLayout Orientation="Horizontal">
                <Entry x:Name="entryB"
                       TextChanged="OnEntryTextChanged"
                       Completed="OnEntryCompleted" />
                <Label Text=" x +" />
            </StackLayout>
            <StackLayout Orientation="Horizontal">
                <Entry x:Name="entryC"
                       TextChanged="OnEntryTextChanged"
                       Completed="OnEntryCompleted" />
                <Label Text=" = 0" />
            </StackLayout>
        </StackLayout>
 
        <!-- Button -->
        <Button x:Name="solveButton"
                Text="Solve for x"
                FontSize="Large"
                IsEnabled="False"
                VerticalOptions="CenterAndExpand"
                HorizontalOptions="Center"
                Clicked="OnSolveButtonClicked" />
        <!-- Results section -->
        <StackLayout VerticalOptions="CenterAndExpand"
                     HorizontalOptions="Center">
            <Label x:Name="solution1Label"
                   HorizontalTextAlignment="Center" />
            <Label x:Name="solution2Label"
                   HorizontalTextAlignment="Center" />
        </StackLayout>
    </StackLayout>
</ContentPage>

标签,条目和按钮视图分为三个部分:顶部的数据输入,中间的按钮和底部的结果。请注意隐式Style条目中特定于平台的WidthRequest设置。这使每个条目的宽度为1英寸。
该程序提供了两种触发计算的方法:按键盘上的完成键,或按页面中间的按钮。这样的程序中的另一个选项是执行每次击键的计算(或者更准确,每个TextChanged
事件)。这可以在这里工作,因为重新计算非常快。但是,在本设计中,结果位于屏幕底部附近,并且在虚拟键盘处于活动状态时被覆盖,因此必须重新组织页面以使这种方案有意义。
QuadraticEquations程序使用TextChanged事件,但仅用于确定键入每个条目的文本的有效性。文本传递给Double.TryParse,如果方法返回false,则Entry文本显示为红色。 (在Windows 10 Mobile上,只有当Entry失去输入焦点时才会显示红色文本。)此外,仅当所有三个Entry视图都包含有效的double值时,才会启用Button。这是显示所有程序交互的代码隐藏文件的前半部分:

public partial class QuadraticEquationsPage : ContentPage
{
    public QuadraticEquationsPage()
    {
        InitializeComponent();
        // Initialize Entry views.
        entryA.Text = "1";
        entryB.Text = "-1";
        entryC.Text = "-1";
    }
    void OnEntryTextChanged(object sender, TextChangedEventArgs args)
    {
        // Clear out solutions.
        solution1Label.Text = " ";
        solution2Label.Text = " ";
        // Color current entry text based on validity.
        Entry entry = (Entry)sender;
        double result;
        entry.TextColor = Double.TryParse(entry.Text, out result) ? Color.Default : Color.Red;
        // Enable the button based on validity.
        solveButton.IsEnabled = Double.TryParse(entryA.Text, out result) &&
                                Double.TryParse(entryB.Text, out result) &&
                                Double.TryParse(entryC.Text, out result);
    }
    void OnEntryCompleted(object sender, EventArgs args)
    {
        if (solveButton.IsEnabled)
        {
            Solve();
        }
    }
    void OnSolveButtonClicked(object sender, EventArgs args)
    {
        Solve();
    }
 __
}

Entry的Completed处理程序仅在启用Button时调用Solve方法,(如您所见)表示所有三个Entry视图都包含有效值。 因此,Solve方法可以安全地假设所有三个Entry视图都包含有效数字,这些数字不会导致Double.Parse引发异常。
Solve方法必然复杂,因为二次方程可能有一个或两个解,每个解可能有一个虚部和一个实部。 该方法将第二个解决方案的实际部分初始化为Double.NaN(“非数字”),并且只有在不再是这种情况时才显示第二个结果。 仅当虚部非零时才显示虚部,并且加号或短划线(Unicode u2013)连接实部和虚部:

public partial class QuadraticEquationsPage : ContentPage
{
    __
    void Solve()
    {
        double a = Double.Parse(entryA.Text);
        double b = Double.Parse(entryB.Text);
        double c = Double.Parse(entryC.Text);
        double solution1Real = 0;
        double solution1Imag = 0;
        double solution2Real = Double.NaN;
        double solution2Imag = 0;
        string str1 = " ";
        string str2 = " ";
        
        if (a == 0 && b == 0 && c == 0)
        {
            str1 = "x = anything";
        }
        else if (a == 0 && b == 0)
        {
            str1 = "x = nothing";
        }
        else
        {
            if (a == 0)
            {
                solution1Real = -c / b;
            }
            else
            {
                double discriminant = b * b - 4 * a * c;
                if (discriminant == 0)
                {
                    solution1Real = -b / (2 * a);
                }
                else if (discriminant > 0)
                {
                    solution1Real = (-b + Math.Sqrt(discriminant)) / (2 * a);
                    solution2Real = (-b - Math.Sqrt(discriminant)) / (2 * a);
                }
                else
                {
                    solution1Real = -b / (2 * a);
                    solution2Real = solution1Real;
                    solution1Imag = Math.Sqrt(-discriminant) / (2 * a);
                    solution2Imag = -solution1Imag;
                }
            }
            str1 = Format(solution1Real, solution1Imag);
            str2 = Format(solution2Real, solution2Imag);
        }
        solution1Label.Text = str1;
        solution2Label.Text = str2;
    }
    string Format(double real, double imag)
    {
        string str = " ";
        if (!Double.IsNaN(real))
        {
            str = String.Format("x = {0:F5}", real);
            if (imag != 0)
            {
                str += String.Format(" {0} {1:F5} i", 
                                     Math.Sign(imag) == 1 ? "+" : "\u2013", 
                                     Math.Abs(imag));
            }
        }
        return str;
    }
}

以下是几个解决方案:
2018_09_19_162726

目录
相关文章
|
1月前
|
SQL 安全 前端开发
设计一个交互式网站
【10月更文挑战第8天】设计一个交互式网站
19 3
|
1月前
|
SQL 测试技术 数据库
如何设计一个交互式网站?
【10月更文挑战第7天】如何设计一个交互式网站?
26 4
|
JavaScript Android开发
|
JavaScript Android开发 iOS开发
|
JavaScript Android开发 索引
|
JavaScript Android开发