入口属性和活动
除了从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² +" />
</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;
}
}
以下是几个解决方案: