项目目录
- 一、项目概述
- 二、开发环境
- 三、详细设计
- 1、布局设计
- 2、主函数
- 2.1、控件定义
- 2.2、控件绑定
- 2.3、控件设置监听器
- 2.4、控件设置点击事件
- 2.5、运行结果
- 四、项目效果
- 五、项目总结
- 六、源码下载
一、项目概述
本次项目主要实现了简单的计算器功能,包括加减乘除基本运算,还有小数点和清零功能,目前可以进行两个数的计算操作。可以算得上是很好的Android界面和按钮点击事件学习实例。刚用模拟器显示hello world的同学或者完全没有接触过Android的同学都可以直接上手。
二、开发环境
Android版本相对之前调整了一下,现在是4.2.1,当然版本不影响,代码语法并不会变,只是构建工具的版本变了而已。代码在任何版本的AS上都可以运行。如果遇到问题,可以参考这两篇经验:
- 快速解决Android项目的Gradle报错问题
- 如何导入gradle版本不同的Android项目
三、详细设计
1、布局设计
在讲布局前我们先介绍GridLayout(网格布局),来说下它的优点:
1、可以自己设置布局中组件的排列方式 |
2、可以自定义网格布局有多少行,多少列 |
3、可以直接设置组件位于某行某列 |
4、可以设置组件横跨几行或者几列 |
下面我们看下计算器的layout代码:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/AliceBlue"
tools:context=".MainActivity"
android:orientation="vertical">
<ImageView
android:layout_gravity="center"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_margin="10dp"
android:background="@drawable/icon"/>
<EditText
android:id="@+id/result"
android:layout_width="match_parent"
android:layout_height="80dp"
android:layout_marginBottom="50dp"
android:textSize="30sp"/>
<GridLayout
android:rowCount="5"
android:columnCount="4"
android:layout_gravity="center"
android:layout_height="match_parent"
android:layout_width="wrap_content">
<Button
android:id="@+id/btn1"
android:layout_margin="5dp"
android:text="1"
android:background="@drawable/button_selector"
android:textSize="25sp"/>
<Button
android:id="@+id/btn2"
android:layout_margin="5dp"
android:text="2"
android:background="@drawable/button_selector"
android:textSize="25sp"/>
<Button
android:id="@+id/btn3"
android:layout_margin="5dp"
android:text="3"
android:background="@drawable/button_selector"
android:textSize="25sp"/>
<Button
android:id="@+id/divide"
android:layout_margin="5dp"
android:text="÷"
android:background="@drawable/button_selector"
android:textSize="25sp"/>
<Button
android:id="@+id/btn4"
android:layout_margin="5dp"
android:text="4"
android:background="@drawable/button_selector"
android:textSize="25sp"/>
<Button
android:id="@+id/btn5"
android:layout_margin="5dp"
android:text="5"
android:background="@drawable/button_selector"
android:textSize="25sp"/>
<Button
android:id="@+id/btn6"
android:layout_margin="5dp"
android:text="6"
android:background="@drawable/button_selector"
android:textSize="25sp"/>
<Button
android:id="@+id/multi"
android:layout_margin="5dp"
android:text="×"
android:background="@drawable/button_selector"
android:textSize="25sp"/>
<Button
android:id="@+id/btn7"
android:layout_margin="5dp"
android:text="7"
android:background="@drawable/button_selector"
android:textSize="25sp"/>
<Button
android:id="@+id/btn8"
android:layout_margin="5dp"
android:text="8"
android:background="@drawable/button_selector"
android:textSize="25sp"/>
<Button
android:id="@+id/btn9"
android:layout_margin="5dp"
android:text="9"
android:background="@drawable/button_selector"
android:textSize="25sp"/>
<Button
android:id="@+id/sub"
android:layout_margin="5dp"
android:text="—"
android:background="@drawable/button_selector"
android:textSize="25sp"/>
<Button
android:id="@+id/point"
android:layout_margin="5dp"
android:layout_columnSpan="1"
android:text="."
android:background="@drawable/button_selector"
android:textSize="25sp"/>
<Button
android:id="@+id/btn0"
android:layout_margin="5dp"
android:text="0"
android:background="@drawable/button_selector"
android:textSize="25sp"/>
<Button
android:id="@+id/clean"
android:layout_margin="5dp"
android:text="C"
android:background="@drawable/button_selector"
android:textSize="25sp"/>
<Button
android:id="@+id/plus"
android:layout_margin="5dp"
android:layout_rowSpan="1"
android:text="+"
android:background="@drawable/button_selector"
android:textSize="25sp"/>
<Button
android:id="@+id/delete"
android:layout_columnSpan="1"
android:layout_rowSpan="2"
android:layout_margin="5dp"
android:text="Del"
android:background="@drawable/button_selector"
android:textSize="25sp"/>
<Button
android:id="@+id/equal"
android:layout_columnSpan="3"
android:layout_gravity="fill"
android:layout_margin="5dp"
android:text="="
android:background="@drawable/button_selector"
android:textSize="25sp"/>
</GridLayout>
</LinearLayout>
代码很简单,首先是个图片框,用来显示计算器的图标。接着是文本框,用来显示输入的计算式。下面就是GridLayout,为每个Button设置了id 、margin 和 background,其中“Del”和“=”按钮横跨两列,其他的都是直接添加的,默认每个组件都是占一行一列。我们来看下界面预览:
2、主函数
2.1、控件定义
定义了很多button,分别代表0-9、加减乘除、小数点、等于和清零,这里变量名一定要简洁易懂,尽可能保证Main里面声明的变量名和layout文件中的控件id相同。不要随意定义变量名,养成好习惯。
//显示结果
private EditText resultText;
//按钮0-9
private Button btn0,btn1,btn2,btn3,btn4,btn5,btn6,btn7,btn8,btn9;
//运算符
private Button plus; // 加号+
private Button sub; // 减号-
private Button multi; // 乘号×
private Button divide; // 除号÷
private Button point; // 小数点.
private Button equal; // 等于=
private Button clean; // 清空
private Button delete; // 删除
2.2、控件绑定
将刚刚定义的变量和已经设置好的控件通过id进行绑定,这样整个变量就代表了这个控件记住,写Android一定要先写layout,再写Main函数。
//绑定运算符控件
plus = findViewById(R.id.plus);
sub = findViewById(R.id.sub);
multi = findViewById(R.id.multi);
divide = findViewById(R.id.divide);
point = findViewById(R.id.point);
equal = findViewById(R.id.equal);
clean = findViewById(R.id.clean);
delete = findViewById(R.id.delete);
//绑定文本框
resultText = findViewById(R.id.result);
2.3、控件设置监听器
将每个控件添加上点击事件,这是最常用的方法,系统监听到你的动作从而给出响应。
plus.setOnClickListener(this);
sub.setOnClickListener(this);
multi.setOnClickListener(this);
divide.setOnClickListener(this);
equal.setOnClickListener(this);
point.setOnClickListener(this);
clean.setOnClickListener(this);
delete.setOnClickListener(this);
2.4、控件设置点击事件
核心的思想如下:如果是数字,那么直接输入;如果是操作符,那么前后加上空格,再放入文本框中;如果有小数点,则结果为浮点数;如果只有后面的操作数,那么默认第一个操作数为0;如果输入的计算式不合法不会给出响应。中间处理逻辑就很像LeetCode中的字符串处理。
String input = resultText.getText().toString();
switch (view.getId()){//选择按钮id
case R.id.btn0:
case R.id.btn1:
case R.id.btn2:
case R.id.btn3:
case R.id.btn4:
case R.id.btn5:
case R.id.btn6:
case R.id.btn7:
case R.id.btn8:
case R.id.btn9:
resultText.setText(input + ((Button)view).getText());
break;
case R.id.point:
if (input.isEmpty() || input.substring(input.length() - 1).equals(" "))
return;//如果最后是空格,无响应
else
resultText.setText(input + '.');
break;
//加减乘除,运算符前后都是空格
case R.id.plus:
case R.id.sub:
case R.id.multi:
case R.id.divide:
resultText.setText(input + " " + ((Button)view).getText() + " ");
break;
case R.id.clean://清除输入框
resultText.setText("");
break;
case R.id.delete://从后往前删除字符
if(!input.isEmpty())
resultText.setText(input.substring(0, input.length() - 1));
break;
case R.id.equal://计算运算结果
getResult();//回调函数
break;
}
}
2.5、运行结果
这部分方法就是计算两个数字运算结果,就是if-else语句,equals( )就是两个对象比较,如果相同则为true,否则为false,contains( ) 就是包含关系,包含为ture,否则为false。
//运算结果的方法
private void getResult(){
//获取文本框的内容
String exp = resultText.getText().toString();
if(exp==null||exp.equals("")){//如果内容为空
return;
}
if(!exp.contains(" ")){//如果不包含运算符
return;
}
double result = 0.0;//返回结果
/***********进行字符串截取**************/
//运算符前的数字,从0下标到第一个空格下标前
String s1 = exp.substring(0,exp.indexOf(" "));
//运算符,第一个空格下标和第二个空格下标之间
String op = exp.substring(exp.indexOf(" ")+1,exp.indexOf(" ")+2);
//运算符后的数字,从第二个空格后全是
String s2 = exp.substring(exp.indexOf(" ")+3);
if(!s1.equals("")&&!s2.equals("")) {//如果数字合法
double d1 = Double.parseDouble(s1);//则数字都是double类型
double d2 = Double.parseDouble(s2);
if (op.equals("+")) //如果是 +
result = d1 + d2;
else if (op.equals("-"))
result = d1 - d2;
else if (op.equals("×"))
result = d1 * d2;
else if (op.equals("÷")) {
if (d2 == 0) //如果被除数是0
Toast.makeText(this,"除数不能为0,请重新输入!",Toast.LENGTH_SHORT).show();
else //否则执行正常是除法运算
result = d1 / d2;
}
if (!s1.contains(".") && !s2.contains(".") && !op.equals("÷")) {//如果都是整型
int r = (int) result;
resultText.setText(r + "");
} else{//如果有浮点型
resultText.setText(result + "");
}
} else if(!s1.equals("") && s2.equals("")){//如果是只输入运算符前的数
return;//直接返回当前文本框的内容
} else if(s1.equals("") && !s2.equals("")){//如果是只输入运算符后面的数
double d2 = Double.parseDouble(s2);
//运算符前没有输入数字
if (op.equals("+"))
result = 0 + d2;
else if (op.equals("-"))
result = 0 - d2;
else if (op.equals("×"))
result = 0;
else if (op.equals("÷"))
result = 0;
if (!s2.contains(".")) {
int r = (int) result;
resultText.setText(r + "");
} else{
resultText.setText(result + "");
}
}else {
resultText.setText("");
}
}
四、项目效果
1、打开模拟器运行,随意输入两个数字进行加减乘除
2、按等于键,得出结果
3、再用上面计算出来的结果做一次乘法
4、按C清空输入框,按Del逐个字符删除
五、项目总结
本次项目是比较基础的考验布局和按钮点击事件的实例,对于初学者来说是非常好的example,可以作为Hello World之后第二个实例,认真消化里面的内容,以后做起来会非常快。
六、源码下载
需要源码学习的同学可以关注我的微信公众号 《萌新加油站》,后台回复:计算器,即可获取源码。还有很多经典的Android项目等你来学习!