又到周末了,继续接着上个星期的内容,给大伙讲讲怎么做一个简单的demo,顺便也讲一点组件的应用。
先展示一下最终成功图
页面设计
页面布局
首先,我们点击我们默认的activity文件(一般初始化是activity_main.xml,我这里为了教学演示所以改成了其他的)。进入code模式。
可以看到内容如下,我们将修改布局为线性布局,使用内置的线性布局模板,LinearLayout,修改后的内容如下
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
android:orientation="vertical"
>
</LinearLayout>
简单给大家讲讲其中属性的含义
layout_width:组件的宽度,由于这个组件是整个布局,所以宽度就是手机整个的宽度,下同
background: 背景,背景可以是一个颜色,用#xxxxxx(色值)来定义,或者是提前在资源文件中准备好相应的背景类型(drawable类型).。
orientation: 布局类型,vertical代表纵向,horizontial代表横向,我们这里使用纵向布局就行。
更多属性类型请见LinearLayout组件讲解
为了使整个布局更合理,更便于使用,我们还需要添加一个ScrollView,ScrollView的作用是,当屏幕内容超出手机大小的时候,会自动生成滑动视图。
最后的布局内容如下。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
android:orientation="vertical">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
</LinearLayout>
</ScrollView>
</LinearLayout>
设置内容
我们已经得到了一个布局
现在需要开始填内容了,首先,是整个应用的标题,也就是我们需要一个文本框来显示“简易计算器”这几个字,这时我们可以使用到TextView这个组件,其功能是显示text。这里我给出两种开发模式,供大家参考。
Code开发
在Code中编辑属性和内容配置,得到源码如下:
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="简易计算器"
android:layout_gravity="center"/>
Design开发
使用可视化开发模式,拖动组件进行编辑。
不过一般来说两种开发方式都是混用的,不存在只用某个开发方式的说法~~~
简单介绍一下TextView的内容,其中text,textSize看名字就知道是什么功能,我就不多说了
gravity: 定义组件内部元素的位置,比如center就是居中
更多属性请见TextView文本编辑框
显示框
我们还需要一个框来显示计算的结果内容,同理也使用textView组件实现,这里我直接给出代码了。
<TextView
android:id="@+id/tv_result"
android:layout_width="match_parent"
android:layout_height="129dp"
android:background="@color/white"
android:gravity="right|bottom"
android:text="0"
android:textColor="@color/black"
android:textSize="25sp" />
如果想要增加对比度,可以使用background属性修改文本框的背景,这里就不多演示了。
按钮设置
接下来我们需要设置计算器的按钮,在这之前,为了使按钮的排布更加合理,我们可以使用网格布局进行操作。
网格布局需要使用GridLayout这个组件
代码如下:
<GridLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:columnCount="4"
android:rowCount="6">
</GridLayout>
其中columnCount,rowCount分别规定了网格布局的行和列
此时,我们添加一行(4个)Button组件试试
<Button
android:text="Button"/>
<Button
android:text="Button"/>
<Button
android:text="Button"/>
<Button
android:text="Button"/>
可以看到布局如下
虽然一行确实排满了四个按钮,但是其按钮排列却没有平均占据一行。
此时,我们需要用到layout_columnWeight这个属性,定义每个按钮占据的权重,我们这里定义每个按钮都占权重1,那么最后一个按钮会分得一行的1/4作为占位。
android:layout_columnWeight="1"
除此之外,我们还需要使按钮之间存在间隔,这里我们使用layout_margin这个属性,即控制按钮的间隔。
然后得到的布局如下:
自定义按钮风格
我们可以看到,虽然我们还什么都没干,设置的按钮却已经有自己的风格了,这是怎么回事呢?答案是按钮继承了项目的默认风格。
我们可以在项目工程的res/themes/themes.xml里面找到,安全起见,我们最好使用默认风格,因为每个手机安卓系统的内部配置不同,如果你这里设置了系统风格,在你的调试机上没问,很有可能到别人的手机上就bug了。而且系统风格限制很多,包括我们后文需要对Button修改颜色这些,都只能在默认风格上进行。
详情修改如下
themes.xml
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Base.Theme.MyApplication" parent="Theme.AppCompat">
<!-- Customize your light theme here. -->
<!-- <item name="colorPrimary">@color/my_light_primary</item> -->
</style>
</resources>
配置文件AndroidManifest.xml(位于工程路径中的manifest文件夹下)中,修改这一行
android:theme="@style/Theme.Caculation"
OK,回到原页,可以看到按钮变得又丑又搓,不急,我们慢慢来。
首先,我们给按钮田间background颜色,指定颜色为#00BCD4(当然你完全可以自定义)
设置字体大小,设置内容(暂略)
使用预设
由于我们设置每一组按钮都会定义其大小,宽度,而这些数据是通用的,我们可以直接定义预设变量进行使用,防止后续修改麻烦。操作如下
在res/values/dimens.xml 进行添加(如果没有对应文件可以自己新建),得到内容如下
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="button_font_size">25sp</dimen>
<dimen name="button_height">75dp</dimen>
</resources>
然后我们就可以直接在Button里面通过下列引用进行调用了
@dimen/button_height
@dimen/button_font_size
,最后得到一个如下的代码(第一行)
<Button
android:id="@+id/zero"
android:tag="zero"
android:layout_columnWeight="1"
android:layout_margin="5dp"
android:background="#00BCD4"
android:text="0"
android:height="@dimen/button_height"
android:textSize="@dimen/button_font_size" />
<Button
android:id="@+id/one"
android:tag="one"
android:text="1"
android:height="@dimen/button_height"
android:textSize="@dimen/button_font_size"
android:background="#00BCD4"
android:layout_columnWeight="1"
android:layout_margin="5dp"/>
<Button
android:id="@+id/two"
android:tag="two"
android:text="2"
android:height="@dimen/button_height"
android:textSize="@dimen/button_font_size"
android:background="#00BCD4"
android:layout_margin="5dp"
android:layout_columnWeight="1"/>
<Button
android:id="@+id/three"
android:tag="three"
android:height="@dimen/button_height"
android:textSize="@dimen/button_font_size"
android:background="#00BCD4"
android:layout_columnWeight="1"
android:layout_margin="5dp"
android:text="3"
/>
我们可以看到,我还定义了每个Button的ID和tag属性,这将为后面定义按钮事件起作用,建议大家进行到这一步就先写着,免得后面一个一个添加挺麻烦的。
得到效果如下
ImageButton
如果各位想使按钮里面附加图像,可以使用ImageButton类型,ImageButton类型提供srcCompat接口连接图像,如下:
<ImageButton
android:id="@+id/delete"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:layout_columnWeight="1"
android:layout_margin="10dp"
android:background="#00BCD4"
android:gravity="center"
android:onClick="Calculate"
android:tag="delete"
app:srcCompat="@android:drawable/ic_input_delete" />
最后就是搬砖工作了,按照上面的方法一个一个把按钮填上去吧。(懒得填的可以看后面我发的代码,复制粘贴就行。)
功能实现
搞完页面功能后,我们还需要实现计算器内核功能,即计算功能和输入输出功能。首先我们先跳转到java文件夹下的XXXacivity.java文件,大致内容如下:
package com.example.myapplication;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
public class CalculateActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_calculate);
}
}
由于我这里是零基础开发教程,所以我就不讲特别细的JAVA知识了。
内容显示
首先我们需要获取到计算器显示器的内容,即那个TextView文件,我们先定义一个方法
public void Calculate(View view)
{
}
然后用下列语句获取我们定义的TextView组件,以及其包含的内容
TextView textView=findViewById(R.id.tv_result); //通过id获取组件
String data=textView.getText().toString(); //获取组件内容
然后我们的目标就是根据按钮的类型判断该做什么事情
举个例子就是,如果我按的是“1”,那么显示框中也应该添加一个字符“1"才对。这里我使用的是switch方法,大概就是下面这种逻辑
switch ((String) view.getTag() //根据tag判断我按下的是哪个按钮)
{
case "one":
data=data+"1"; //对字符串进行处理
break;
case "xxx":
.....
}
最后,我们将处理好的新的data重新写回textView上,达到按按钮就增加输入行的效果。
整个方法的框架如下:
public void Calculate(View view)
{
TextView textView=findViewById(R.id.tv_result); //通过id获取组件
String data=textView.getText().toString(); //获取组件内容
switch ((String) view.getTag())
{
case "one":
data=data+"1";
break;
case "xxxx"
......
}
textView.setText(data);//写回
}
有兴趣的小伙伴可以自己写写,当然也可以直接抄我写的。
计算处理
最后我们要处理等号,因为其他操作都是单纯的处理字符串,而等号操作要识别字符串内部的实际含义,然后进行计算。
最开始我想的是,如果Java有Python里面的eval函数就好了,然后我就去网上搜了一下,发现javax包里面确实可以实现eval函数,然而!我们这里不是JDK,而是SDK,所以是用不了滴。(当然网上也有使用javaScript插件的,但是我试过直接崩了,有兴趣的可以去试试)。
还记得学数据结构的时候那个经典的实验吗,用栈结构处理字符串算式。
让我们新建一个类,Caculate.java。写入以下内容。(别把自己的包路径也删了,就是那个package开头的指令。
public class Caculate {
/**
* 判断表达式是不是只有一个数字
*
* @param str 原值
* @return 数字非法性校验结果,失败返回false;
*/
private static boolean isNumber(String str) {
for (int i = 0; i < str.length(); i++) {
if (!Character.isDigit(str.charAt(i)) && str.charAt(i) != '.' && str.charAt(i) != ' ') {
return false;
}
}
return true;
}
/**
* 解析算式,并计算算式结果;
*
* @param str 算式的字符串
* @return double类型的算式结果
*/
public static Double getResult(String str) {
// 递归头
if (str.isEmpty() || isNumber(str)) {
return str.isEmpty() ? 0 : Double.parseDouble(str);
}
//递归体
if (str.contains(")")) {
// 最后一个左括号
int lIndex = str.lastIndexOf("(");
// 对于的右括号
int rIndex = str.indexOf(")", lIndex);
return getResult(str.substring(0, lIndex) + getResult(str.substring(lIndex + 1, rIndex)) + str.substring(rIndex + 1));
}
if (str.contains("+")) {
int index = str.lastIndexOf("+");
return getResult(str.substring(0, index)) + getResult(str.substring(index + 1));
}
if (str.contains("-")) {
int index = str.lastIndexOf("-");
return getResult(str.substring(0, index)) - getResult(str.substring(index + 1));
}
if (str.contains("*")) {
int index = str.lastIndexOf("*");
return getResult(str.substring(0, index)) * getResult(str.substring(index + 1));
}
if (str.contains("/")) {
int index = str.lastIndexOf("/");
return getResult(str.substring(0, index)) / getResult(str.substring(index + 1));
}
// 出错
return null;
}
}
调用这个getResult方法就能处理字符串啦。整合一下所有功能试试吧。
代码附录
页面设计:
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#EEE8E8E8"
android:orientation="vertical"
android:padding="20dp">
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="简单计算器"
android:textColor="@color/black"
android:textSize="20sp" />
<TextView
android:id="@+id/tv_result"
android:layout_width="match_parent"
android:layout_height="129dp"
android:background="@color/white"
android:gravity="right|bottom"
android:text=""
android:textColor="@color/black"
android:textSize="25sp" />
<GridLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:columnCount="4"
android:rowCount="6">
<Button
android:id="@+id/btn_cancel"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:layout_columnWeight="1"
android:layout_margin="10dp"
android:background="#00BCD4"
android:gravity="center"
android:onClick="Calculate"
android:tag="cancel"
android:text="c"
android:textColor="@color/black"
android:textSize="@dimen/button_font_size" />
<ImageButton
android:id="@+id/delete"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:layout_columnWeight="1"
android:layout_margin="10dp"
android:background="#00BCD4"
android:gravity="center"
android:onClick="Calculate"
android:tag="delete"
app:srcCompat="@android:drawable/ic_input_delete" />
<Button
android:id="@+id/zero"
android:tag="zero"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:layout_columnWeight="1"
android:layout_margin="10dp"
android:onClick="Calculate"
android:background="#00BCD4"
android:gravity="center"
android:text="0"
android:textColor="@color/black"
android:textSize="@dimen/button_font_size" />
<Button
android:id="@+id/division"
android:tag="division"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:layout_columnWeight="1"
android:layout_margin="10dp"
android:background="#00BCD4"
android:gravity="center"
android:onClick="Calculate"
android:text="/"
android:textColor="@color/black"
android:textSize="24sp" />
<Button
android:id="@+id/seven"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:layout_columnWeight="1"
android:layout_margin="10dp"
android:background="#00BCD4"
android:gravity="center"
android:tag="seven"
android:onClick="Calculate"
android:text="7"
android:textColor="@color/black"
android:textSize="@dimen/button_font_size" />
<Button
android:id="@+id/eight"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:layout_columnWeight="1"
android:layout_margin="10dp"
android:background="#00BCD4"
android:gravity="center"
android:tag="eight"
android:onClick="Calculate"
android:text="8"
android:textColor="@color/black"
android:textSize="@dimen/button_font_size" />
<Button
android:id="@+id/nine"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:layout_columnWeight="1"
android:layout_margin="10dp"
android:background="#00BCD4"
android:gravity="center"
android:onClick="Calculate"
android:tag="nine"
android:text="9"
android:textColor="@color/black"
android:textSize="@dimen/button_font_size" />
<Button
android:id="@+id/mul"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:layout_columnWeight="1"
android:layout_margin="10dp"
android:background="#00BCD4"
android:gravity="center"
android:onClick="Calculate"
android:tag="mul"
android:text="X"
android:textColor="@color/black"
android:textSize="@dimen/button_font_size" />
<Button
android:id="@+id/four"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:layout_columnWeight="1"
android:layout_margin="10dp"
android:background="#00BCD4"
android:gravity="center"
android:onClick="Calculate"
android:tag="four"
android:text="4"
android:textColor="@color/black"
android:textSize="@dimen/button_font_size" />
<Button
android:id="@+id/five"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:layout_columnWeight="1"
android:layout_margin="10dp"
android:background="#00BCD4"
android:gravity="center"
android:onClick="Calculate"
android:tag="five"
android:text="5"
android:textColor="@color/black"
android:textSize="@dimen/button_font_size" />
<Button
android:id="@+id/six"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:layout_columnWeight="1"
android:layout_margin="10dp"
android:background="#00BCD4"
android:gravity="center"
android:onClick="Calculate"
android:tag="six"
android:text="6"
android:textColor="@color/black"
android:textSize="@dimen/button_font_size" />
<Button
android:id="@+id/sub"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:layout_columnWeight="1"
android:layout_margin="10dp"
android:background="#00BCD4"
android:gravity="center"
android:onClick="Calculate"
android:tag="sub"
android:text="—"
android:textColor="@color/black"
android:textSize="@dimen/button_font_size" />
<Button
android:id="@+id/one"
android:layout_width="0dp"
android:layout_height="74dp"
android:layout_columnWeight="1"
android:layout_margin="10dp"
android:background="#00BCD4"
android:gravity="center"
android:onClick="Calculate"
android:tag="one"
android:text="1"
android:textColor="@color/black"
android:textSize="@dimen/button_font_size" />
<Button
android:id="@+id/two"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:layout_columnWeight="1"
android:layout_margin="10dp"
android:background="#00BCD4"
android:onClick="Calculate"
android:gravity="center"
android:tag="two"
android:text="2"
android:textColor="@color/black"
android:textSize="@dimen/button_font_size" />
<Button
android:id="@+id/three"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:layout_columnWeight="1"
android:layout_margin="10dp"
android:background="#00BCD4"
android:onClick="Calculate"
android:gravity="center"
android:text="3"
android:tag="three"
android:textColor="@color/black"
android:textSize="@dimen/button_font_size" />
<Button
android:id="@+id/add"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:layout_columnWeight="1"
android:layout_margin="10dp"
android:background="#00BCD4"
android:gravity="center"
android:onClick="Calculate"
android:text="+"
android:tag="add"
android:textColor="@color/black"
android:textSize="@dimen/button_font_size" />
<Button
android:id="@+id/dot"
android:tag="dot"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:layout_columnWeight="1"
android:layout_margin="10dp"
android:background="#00BCD4"
android:gravity="center"
android:onClick="Calculate"
android:text="."
android:textColor="@color/black"
android:textSize="@dimen/button_font_size" />
<Button
android:id="@+id/left"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:layout_columnWeight="1"
android:layout_margin="10dp"
android:background="#00BCD4"
android:gravity="center"
android:onClick="Calculate"
android:tag="left"
android:text="("
android:textColor="@color/black"
android:textSize="@dimen/button_font_size" />
<Button
android:id="@+id/right"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:layout_columnWeight="1"
android:layout_margin="10dp"
android:background="#00BCD4"
android:gravity="center"
android:onClick="Calculate"
android:tag="right"
android:text=")"
android:textColor="@color/black"
android:textSize="@dimen/button_font_size" />
<Button
android:id="@+id/equal"
android:tag="equal"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:layout_columnWeight="1"
android:layout_margin="10dp"
android:background="#00BCD4"
android:gravity="center"
android:onClick="Calculate"
android:text="="
android:textColor="@color/black"
android:textSize="@dimen/button_font_size" />
</GridLayout>
</LinearLayout>
</ScrollView>
</LinearLayout>
XXXactivity.java
package com.example.caculation;
import com.example.caculation.Caculate;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
setTheme(R.style.Theme_Caculation);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView=findViewById(R.id.tv_result);
}
public void Calculate(View view)
{
String data=textView.getText().toString();
switch ((String) view.getTag())
{
case "one":
data=data+"1";
break;
case "two":
data=data+"2";
break;
case "three":
data=data+"3";
break;
case "four":
data=data+"4";
break;
case "five":
data=data+"5";
break;
case "six":
data=data+"6";
break;
case "seven":
data=data+"7";
break;
case "eight":
data=data+"8";
break;
case "nine":
data=data+"9";
break;
case "zero":
data=data+"0";
break;
case "double_zero":
data=data+"00";
break;
case "cancel":
data="";
break;
case "delete":
data=data.substring(0,data.length()-1);
break;
case "mul":
data=data+"*";
break;
case "division":
data=data+"/";
break;
case "sub":
data=data+"-";
break;
case "add":
data=data+"+";
break;
case "dot":
if (data.substring(data.length()-1).equals("."))
return;
else
{
data=data+".";
break;
}
case "left":
data=data+"(";
break;
case "right":
data=data+")";
break;
case "equal":
data=String.valueOf(Caculate.getResult(data));
break;
}
textView.setText(data);
}
}