现在起,我们就开始正式开发“计算器”应用。
这一节,我们将完成计算器的界面布局,让它初具计算器的模样。
计算器界面是通过布局文件定义的。它位于项目的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;
}
}
当用户点击“=”按钮的时候,开始计算。
我们将使用第三方计算库Arity
对表达式进行计算。Arity
库文件可以在安豆网提供的下载地址进行下载。
下载完成后,
arity-2.1.2.jar
复制到项目工程所在的Calulator\app\libs
目录下,如果这个目录不存在,就自己创建一个;Project
视图;app->libs->arity-2.1.2,jar
上点击右键,选择Add as Library...
;OK
。利用第三方库,对运算表达式进行计算,
Symbols
对象,使用它的evl()
方法,计算表达式的内容;try...catch
抓住异常,用Toast
类给用户一个内容为错误!
的提示。public void onClick(View view)
{
switch (view.getId()) {
......
case R.id.btn_equ: {
TextView formula = (TextView) findViewById(R.id.formula_area);
String strContent = formula.getText().toString();
try {
Symbols s = new Symbols();
double res = s.eval(strContent);
TextView result = (TextView) findViewById(R.id.result_area);
result.setText(String.valueOf(res));
formula.setText("");
} catch (SyntaxException e) {
Toast.makeText(MainActivity.this, “错误!”, Toast.LENGTH_SHORT).show();
}
}
break;
}
}
至此,一个具有计算功能的计算器就已经出现了。
这一节,我们将对粗糙的计算器界面进行美化。
在布局文件activity_main.xml
中,给整个界面增加一个背景颜色#FF4B5459
,使用android:background
属性设置,这里的颜色是采用AARRGGBB的形式进行定义的;
<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" android:background="#FF4B5459">
</LinearLayout>
给结果显示区域和表达式显示区域之间,增加一条间隔线,高度设置为5dp
,用颜色“#FF5C6265”;
<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"/>
<View android:layout_width="match_parent" android:layout_height="5dp" android:background="#FF5C6265" />
<TextView android:id="@+id/formula_area" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1"/>
</LinearLayout>
显示区域的字体颜色通过android:textColor
属性设置成白色#FFFFFFFF
;字体大小通过android:textSize
属性设置成45sp
;通过android:gravity
属性让文字位于左边居中显示;显示区域的页边距通过android:padding
属性设置成5dp
;
<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" android:textColor="#FFFFFFFF" android:textSize="45sp" android:gravity="center_vertical|right" android:padding="5dp"/>
<View android:layout_width="match_parent" android:layout_height="5dp" android:background="#FF5C6265" />
<TextView android:id="@+id/formula_area" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:textColor="#FFFFFFFF" android:textSize="45sp" android:gravity="center_vertical|right" android:padding="5dp"/>
</LinearLayout>
修改Button
的字体大小和字体颜色,与修改TextView
的字体大小和字体颜色完全一样。
<TableRow android:layout_weight="1">
<Button android:id="@+id/btn_c" android:text="C" android:onClick="onClick" android:textColor="#FF000000" android:textSize="35sp"/>
......
</TableRow>
修改Button
的按键背景效果,需要使用selector drawble。
打开res\values\colors.xml
文件,定义没有按下按钮
时背景的颜色为#D0DCE3
,按下按钮
时背景的颜色为#BED1DB
;
<resources>
......
<color name="colorBtnNormal">#D0DCE3</color>
<color name="colorBtnPressed">#BED1DB</color>
</resources>
在res\drawable\
目录下,点击右键,启动创建drawable resource的向导;
创建selector drawable的xml文件,文件名为button_selector
;
根据Button
是否被按下的状态android:state_pressed
,分别为它们设置不同的颜色,android:state_pressed=true
,说明当前按钮被按下,android:state_pressed=false
,说明当前按钮没有被按下;设置颜色使用@color
关键字,并加上之前在colors.xml中定义的颜色的名字;
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="false" android:drawable="@color/colorBtnNormal"/>
<item android:state_pressed="true" android:drawable="@color/colorBtnPressed"/>
</selector>
给Button
的android:background
属性,使用drawable selector,
<TableRow android:layout_weight="1">
<Button android:id="@+id/btn_c" android:text="C" android:onClick="onClick" android:textColor="#FF000000" android:textSize="35sp" android:background="@drawable/button_selector"/>
......
</TableRow>
为了减少修改每个Button
的工作量,可以将Button
的这种显示效果定义成一种style
,为“计算器”应用中的所有Button
设置这种style
就可以了。
打开res\values\styles.xml
文件,将Button
的共同特性定义成一个style
---BtnStyle
;此外,为了键盘美观,通过定义android:layout_margin
属性,增加了每个按钮的间距。
<resources>
......
<style name="BtnStyle"> <item name="android:layout_height">match_parent</item> <item name="android:layout_margin">0.5dp</item> <item name="android:textSize">35sp</item> <item name="android:textColor">#FF000000</item> <item name="android:background">@drawable/button_selector</item> </style>
</resources>
为所有Button
通过style
属性,添加一种BtnStyle
风格;
<TableRow android:layout_weight="1">
<Button android:id="@+id/btn_c" android:text="C" android:onClick="onClick" style="@style/BtnStyle" />
<Button android:id="@+id/btn_del" android:text="DEL" android:onClick="onClick" style="@style/BtnStyle"/>
<Button android:id="@+id/btn_dot" android:text="." android:onClick="onClick" style="@style/BtnStyle"/>
<Button android:id="@+id/btn_add" android:text="+" android:onClick="onClick" style="@style/BtnStyle"/>
</TableRow>
至此,计算器界面美化完成。
安卓系统,支持多国语言。在这一节,我们将添加中文支持。
在res
目录下,点击右键,启动创建android resource的向导;
在File name
栏,输入strings.xml
,再选中下方的locale
,添加到右边;
选中zh
,代表中文;
在创建出来的中文的res\values-zh\strings.xml
文件中,仿照res\values\strings.xml
的内容,添加中文语言;
<resources>
<string name="app_name">计算器</string>
</resources>
这里的stringapp_name
,在AndroidManifest.xml
文件中被使用,它使用android:label
属性,指定了这个应用的名称。
<application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
至此,中文语言的支持,添加完成。在设备上运行程序后,会看到现在“计算器”应用到名称已经变成中文的计算器
了。