现在起,我们就开始正式开发“计算器”应用。
这一节,我们将完成计算器的界面布局,让它初具计算器的模样。
计算器界面是通过布局文件定义的。它位于项目的res\layout\activity_main.xml
文件中。
这个布局文件通过java源代码MainActivity.java
中的setContentView()
函数,设置到界面上。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
接下来,我们的界面布局,就会在这个布局文件activity_main.xml中进行。
在修改布局文件的过程中,可以通过Preview
功能,来实时观看我们修改的界面布局效果。
首先确定布局形式。界面分为两个大区域,上半区域显示计算表达式和计算结果,下半区域显示键盘,这两个区域一上一下,呈线型排列,因此我们选择LinearLayout
布局。并且通过将LinearLayout的android:orientation
属性设置成vertical
来将它包含的内容以竖直方式排列。整个界面将尽可能占用整个屏幕,因此使用match_parent
指定布局的宽度和高度。match_parent
说明尺寸要尽可能的大。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.anddle.calculator.MainActivity" android:orientation="vertical">
</LinearLayout>
上半区域还包含了表达式区域和计算结果区域,它们也成竖直排列,所以还需要一个LinearLayout包含它们。上半区域占整个界面的1/3。
下半区域是键盘的显示区域,像一个表格排列,我们选用TableLayout作为这个区域的布局。下半区域占整个界面的2/3。
LinearLayout要在竖直方向上按比例分配,就需要为它的子布局使用android:layout_weight
属性,并且把android:layout_height
设置成0dp
。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.anddle.calculator.MainActivity" android:orientation="vertical">
<LinearLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1">
</LinearLayout>
<TableLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="2">
</TableLayout>
</LinearLayout>
结果区域和表达式区域一上一下,各占一半空间。它们用来显示文字内容,因此可以使用TextView控件。
为结果区域指定android:id
为result_area
,为表达式区域指定android:id
为formula_area
。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.anddle.calculator.MainActivity" android:orientation="vertical">
<LinearLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:orientation="vertical">
<TextView android:id="@+id/result_area" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1"/>
<TextView android:id="@+id/formula_area" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1"/>
</LinearLayout>
<TableLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="2">
</TableLayout>
</LinearLayout>
在TableLayout设计键盘按钮。键盘分成4*5格,每一行用TableRow布局,TableRow是与TableLayout配合使用的布局,用来表示表格的每一行。
<TableLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="2">
<TableRow android:layout_weight="1">
</TableRow>
<TableRow android:layout_weight="1">
</TableRow>
<TableRow android:layout_weight="1">
</TableRow>
<TableRow android:layout_weight="1">
</TableRow>
<TableRow android:layout_weight="1">
</TableRow>
</TableLayout>
按钮可以使用安卓自有的控件Button
。通过android:text
属性为每个Button设置需要显示的内容,并为它们各自的android:id
取上对应的id名字。对于最后一行中的‘0’按钮,我们需要为这个Button
控件再多使用一个android:layout_span
属性,让它能够占据三格的位置。
<TableLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="2">
<TableRow android:layout_weight="1">
<Button android:id="@+id/btn_c" android:text="C"/>
<Button android:id="@+id/btn_del" android:text="DEL"/>
<Button android:id="@+id/btn_dot" android:text="."/>
<Button android:id="@+id/btn_add" android:text="+"/>
</TableRow>
<TableRow android:layout_weight="1">
<Button android:id="@+id/btn_7" android:text="7"/>
<Button android:id="@+id/btn_8" android:text="8"/>
<Button android:id="@+id/btn_9" android:text="9"/>
<Button android:id="@+id/btn_sub" android:text="-"/>
</TableRow>
<TableRow android:layout_weight="1">
<Button android:id="@+id/btn_4" android:text="4"/>
<Button android:id="@+id/btn_5" android:text="5"/>
<Button android:id="@+id/btn_6" android:text="6"/>
<Button android:id="@+id/btn_mul" android:text="*"/>
</TableRow>
<TableRow android:layout_weight="1">
<Button android:id="@+id/btn_1" android:text="1"/>
<Button android:id="@+id/btn_2" android:text="2"/>
<Button android:id="@+id/btn_3" android:text="3"/>
<Button android:id="@+id/btn_div" android:text="/"/>
</TableRow>
<TableRow android:layout_weight="1">
<Button android:id="@+id/btn_0" android:text="0" android:layout_span="3" />
<Button android:id="@+id/btn_equ" android:text="="/>
</TableRow>
</TableLayout>
至此,计算器的界面布局就完成了。
这一节我们将实现计算器的功能。在实现的过程中,可以随时将修改的代码部署到设备上,看看实际的效果。
按钮是可以在用户点击的时候做出响应的。
首先在布局文件中,给所有Button
控件的android:onClick
属性设置一个响应函数,这里我们取名也叫做onClick
。
<TableRow android:layout_weight="1">
<Button android:id="@+id/btn_c" android:text="C" android:onClick="onClick"/>
<Button android:id="@+id/btn_del" android:text="DEL" android:onClick="onClick"/>
<Button android:id="@+id/btn_dot" android:text="." android:onClick="onClick"/>
<Button android:id="@+id/btn_add" android:text="+" android:onClick="onClick"/>
</TableRow>
在MainActivity.java
的源代码当中,添加对应的onClick()
函数方法。这个方法是public
的,返回值为void
,传入的参数是view
-也就是这个按钮对象。
public void onClick(View view)
{
}
用每个按钮的android:id
来区分,每次点击的是哪个按钮。在代码中,id
可以通过Android Studio自动编译生成的R
-资源类来访问,形如R.id.xxx
。
public void onClick(View view)
{
switch (view.getId()) {
case R.id.btn_0:
case R.id.btn_1:
case R.id.btn_2:
case R.id.btn_3:
case R.id.btn_4:
case R.id.btn_5:
case R.id.btn_6:
case R.id.btn_7:
case R.id.btn_8:
case R.id.btn_9:
case R.id.btn_add:
case R.id.btn_sub:
case R.id.btn_mul:
case R.id.btn_div:
case R.id.btn_dot:
case R.id.btn_c:
case R.id.btn_del:
case R.id.btn_equ:
break;
}
}
当用户点击数字键(0-9和.)以及运算符键(+-*/)时,需要将它们对应的符号显示到表达式区域。
view
转换成Button
类型,通过Button
的getText()
方法,获取按钮上的字符;findViewById()
方法获取表达式区域;在通过表达式区域TextView
的getText()
方法,获取已经显示在表达式区域上的内容;TextView
的setText()
方法,显示到表达式区域上。public void onClick(View view) {
switch (view.getId()) {
case R.id.btn_0:
case R.id.btn_1:
case R.id.btn_2:
case R.id.btn_3:
case R.id.btn_4:
case R.id.btn_5:
case R.id.btn_6:
case R.id.btn_7:
case R.id.btn_8:
case R.id.btn_9:
case R.id.btn_add:
case R.id.btn_sub:
case R.id.btn_mul:
case R.id.btn_div:
case R.id.btn_dot: {
Button btn = (Button) view;
String strAdded = btn.getText().toString();
TextView formula = (TextView) findViewById(R.id.formula_area);
String strContent = formula.getText().toString();
String strNewContent = strContent + strAdded;
formula.setText(strNewContent);
}
break;
......
}
}
当用户点击“C”按钮的时候,清空显示区域的内容和结果区域的内容。
findViewById()
方法,分别获取表达式区域和结果区域;TextView
的setText()
方法,分别为它们设置空字符串。public void onClick(View view)
{
switch (view.getId()) {
......
case R.id.btn_c: {
TextView formula = (TextView) findViewById(R.id.formula_area);
formula.setText("");
TextView result = (TextView) findViewById(R.id.result_area);
result.setText("");
}
break;
......
}
}
当用户点击“DEL”按钮的时候,删除表达式内容的最后一个字符。
String
类的subString()
方法,截取最后一个字符之前的所有内容;public void onClick(View view)
{
switch (view.getId()) {
......
case R.id.btn_del: {
TextView formula = (TextView) findViewById(R.id.formula_area);
String strContent = formula.getText().toString();
if (strContent.length() > 0) {
strContent = strContent.substring(0, strContent.length() - 1);
formula.setText(strContent);
}
}
break;
}
}