Android-移动应用基础
Android-移动应用基础
环境搭建
-
集成工具下载
下载
-
勾选
ADV
勾选 ADV
-
SDK
下载 SDK
全称为 Software Development Kit
意即 软件开发工具包
,他可以将 App
源码编译为可执行的 App
应用 SDK => 427MB
基础项目创建
-
创建
Empty Activity
-
配置
基础环境选则 -
创建内置模拟器
所谓模拟器,
是指在电脑上构造一个演示窗口, 模拟手机屏幕上的 App
运行效果 创建 下载操作系统 选则屏幕角度 启动 成功启动 模拟器
-
切换目录显示结构
显示结构
-
-
日志输出
( Android
采用 Log
工具打印日志, 他将各类日志划分为五个等级) Log.e
: 表示错误信息,比如可能导致程序崩溃的异常 Log.w
: 表示警告信息Log.i
: 表示一般消息Log.d
: 表示调试信息,可把程序运行时的变量值打印出来, 方便跟踪调试 Log.v
: 表示冗余信息
-
开启真机调试
上拉出现,点击 settings
,选则最后一项 再次选则最后一项, 多次点击, 直至出现如下提示
App 工程目录结构
-
App
工程分为两个层次, 第一个层次是 项目
,另一个层次是 模块
-
模块依附于项目,
每个项目至少有一个模块, 也能拥有多个模块 -
一般所言的
编译运行
App 指的是运行某个模块, 而非运行某个项目, 因为模块才对应实际的 App
-
app
app
目录信息 manifests
子目录, 下面只有一个 xml
文件, 即 AndroidManifest.xml
它是 App
的运行配置 java
子目录, 下面有三个 com.xx.xxx
包, 其中第一个存放当前模块的 Java
源代码, 后面两个包存放测试用的 Java
代码 res
子目录, 存放当前模块的资源文件, res
下面又有 4
个子目录 drawable
目录存放图形描述文件与图片文件 layout
:目录存放 App
页面的布局文件 mipmap
: 目录存放App
的启动图标 values
目录存放一些常量定义文件, 例如字符串常量 strings.xml
像素常量 dimens.xml
颜色常量 colors.xml
样式风格定义 style.xml
等
-
Gradle Scripts
下面主要是工程的编译配置文件, 主要有 build.gradle
: 该文件分为项目级与模块两种,用于描述 App
工程的编译规则 proguard-rules.pro
: 该文件用于描述java
代码的混淆规则 gradle.properties
: 该文件用于配置编译工程的命令行参数,一般无需改动 settings.gradle
: 该文件配置需要编译那些模块,初始内容为 include:app
表示只编译 app
模块 local.properties
项目的本地配置文件, 它在工程编译时自动生成, 用于描述开发者电脑的环境配置, 包括 SDK
的本地路径, NDK
的本地路径等
-
Gradel model
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46plugins {
id 'com.android.application'
}
android {
// 指定编译用的 SDK 版本号,比如 30 表示使用 Android 11.0 编译
compileSdk 32
defaultConfig {
// 指定该模块的应用编号 也就是 app 的包名
applicationId "com.coderitl.demo"
// 指定 App 适合运行的最小 SDK 版本号
minSdk 21
// 指定目标设备的 SDK 版本号
targetSdk 32
// 指定 App 的应用版本号
versionCode 1
// 指定Aoode 的应用版本名称
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
// 指定 App 编译的依赖信息
dependencies {
// 指定编译 Android 的高版本支持库,如 AppCompatActivity 必须指定编译的 appcompat
implementation 'androidx.appcompat:appcompat:1.3.0'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
// 指定单元测试编译用的 junit 版本号
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
} -
清单文件
AndroidManifest.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.coderitl.demo">
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.MyApplication"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>-
android:allowBackup="true"
是否允许应用备份,允许用户备份系统应用和第三方应用的apk
安装包和数据,以便在刷机或者数据丢失后恢复应用, 用户即可通过 adb backup
和 adb restore
来进行应用数据的备份和恢复, 为 true
表示允许, 为 false
则表示不允许 -
android:icon="@mipmap/ic_launcher"
指定App
在手机屏幕上显示的图标 -
android:label="@string/app_name"
指定App
在手机屏幕上显示的名称 -
android:roundIcon="@mipmap/ic_launcher_round"
指定App
的圆角图标 -
android:supportsRtl="true"
是否支持阿拉伯语/ 波斯语这种从右往左的文字排列顺序,为 true
表示支持, 为 false
则表示不支持 -
android:theme="@style/Theme.MyApplication"
指定App
的显示风格 application
下面还有个 activity
节点,它是活动页面的注册声明, 只有在 AndroidManifest.xml
中正确配置了 activity
节点, 才能在运行时访问对应的活动页面, 初始配置的 Mainactivity
正是 app
的默认主页, 之所以说该页面是 App
的主页, 是因为它的 activity
节点内部还配置了以下过滤信息 1
2
3
4
5
6
7
8
9<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity> -
activity_main.xml
视图 左上角进行视图切换
-
-
创建新的
App
页面 - 在
layout
目录下创建 XML
文件 - 创建与
XML
文件对应的 Java
代码 - 在
AndroidManifest.xml
中注册页面配置
- 在
-
快速生成页面源码
-
依次选则右键菜单
new -> Activity -> Empty Activity
Empty Activity
-
输入各项信息后,
单机 Finish
输入各项信息后
-
简单控件
文本
-
设置文本的内容
-
在
XML
文件中通过属性 android:text
设置文本 1
2
3
4
5
6
7
8
9
10
11<!--
设置文本: res/values/string =>你好 世界
引用: android:text="@string/hello">
-->
<TextView
android:id="@+id/tv_hello"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello">
</TextView> -
在
Java
代码中调用文本视图对象的 setText
方法设置文本 1
2
3
4
5// 根据 id 获取
TextView tv_hello = findViewById(R.id.tv_hello);
// 设置文本
tv_hello.setText("世界 你好");
-
创建新的布局
创建新的布局
-
设置文本的大小
-
在
java
代码中调用 setTextSize
方法, 指定文本大小 1
2
3
4
5
6
7
8
9
10
11
12
13
public class TestSizeActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test_size);
TextView tv_hello = findViewById(R.id.tv_hello);
// 设置文本字体大小
tv_hello.setTextSize(20);
}
} -
在
XML
文件中则通过属性 android:textSize
指定文本大小, 此时需要指定字号单位 -
px
: 它是手机屏幕的最小单位,与设备的显示屏有关 -
dp
: 它是与设备无关的显示单位,只与屏幕的尺寸有关 -
sp
: 它专门用来设置字体大小,在系统设置中可以调正字体大小 1
2
3
4<TextView
...
<!-- 设置字体大小 需要携带单位 sp(Android推荐使用) -->
android:textSize="30sp">名称 解释 px
也称为图像元素, 是作为图像构成的基本单位, 单个像素的大小并不固定, 跟随屏幕大小和像素数量的关系变化, 一个像素点为 1px
Resolution
是指屏幕的垂直和水平方向的像素数量, 如果分辨率是 1920*1080
那就是垂直方向有 1920
个像素 Dpi
是指屏幕上每英寸 ( 1
)英寸 =2.54cm 距离中有多少个像素点 Density
是指屏幕上每平方英寸 (2.54^2 平方厘米) 中含有的像素点数量 Dip/dp
也可以叫做 dp
长度单位, 同一个单位在不同设备上有不同的显示效果, 具体效果根据设备的密度有关
-
设置文本的颜色
在
Java
代码中调用 setTextColor
方法即可设置文本颜色, 具体颜色值可从 Color
类取
-
Java
设置 1
2
3
4
5
6
7// 设置文字颜色
tv_hello_system.setTextColor(Color.RED);
// 背景颜色设置为红色(颜色非自定义)
tv_hello_system.setBackgroundColor(Color.RED);
// 使用自定义颜色
tv_hello_system.setBackgroundResource(R.color.green); -
XML
设置文本颜色 1
2<!-- @color/purple_700 => 引用自 values/color 中定义的颜色 -->
android:textColor="@color/purple_700"
设置视图的宽高
-
视图的宽高
视图宽度通过属性
android:layout_width
表达 视图高度通过属性
android:layout_heihgt
表达 -
宽高的属性值
match_parent
表示与上级视图保持一致 wrap_content
表示内容自适应 - 以
dp
为单位的具体尺寸
-
在
java
代码中设置视图宽高 首先要确保
XML
中的 宽高
属性值为wrap_content
接着打开该页面对应的 Java
代码, 依次执行如下三个步骤 - 调用控件对象的
getLayoutParams
方法, 获取该控件的布局参数 - 布局参数的
width
属性表示宽度, height
属性表示高度, 修改这两个属性值 - 调用控件对象的
setLayoutParams
方法, 填入修改后的布局参数使之生效
- 调用控件对象的
-
设置视图的间距
-
间距
- 采用
layout_margin
属性, 它指定了当前视图与周围平级视图水平的距离, 包括 layout_margin,layout_marginLeft,layout_marginTop,layout_marginReight,layout_marginBottom
- 采用
padding
属性, 它指定了当前视图与内部下级视图之间的距离, 包括 padding,paddingLeft,paddingTop,paddingRight,paddingBottom
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!-- 设置最外层的布局背景为蓝色 -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#00AAFF"
android:orientation="vertical">
<!-- 设置中间的背景为黄色 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="40dp"
android:background="#F1B80D"
android:padding="40dp">
<!-- 最内层为红色 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FF2424" />
</LinearLayout>
</LinearLayout>渲染效果 - 采用
设置视图的对齐方式
-
对齐方式·
- 采用
layout_gravity
属性, 它指定了当前视图相对于上级视图的对齐方式 - 采用
gravity
属性, 它指定了下级视图相对于当前视图的对齐方式
- 采用
-
layout_gravity
与 gravity
取值包括: left,top,right,bottom
还可以用竖线连接各取值,例如 left|top
左上对齐角 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41<!-- 设置最外层的布局背景为蓝色 -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="300dp"
android:background="#00AAFF"
android:orientation="horizontal">
<LinearLayout
android:layout_width="0dp"
android:layout_height="200dp"
android:layout_gravity="bottom"
android:layout_margin="40dp"
android:layout_weight="1"
android:background="#ff0000"
android:gravity="bottom"
android:padding="10dp">
<!-- 下级视图 -->
<View
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#00ffff" />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="200dp"
android:layout_gravity="top"
android:layout_margin="40dp"
android:layout_weight="1"
android:background="#ff0000"
android:gravity="top"
android:padding="10dp">
<!-- 下级视图 -->
<View
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#00ffff" />
</LinearLayout>
</LinearLayout>视图对齐方式
常用布局
线性布局
-
排列方式
-
orientation
属性值为 horizontal
时, 内部视图在 水平方向
从左往右排列 -
orientation
属性值为 vertical
时, 内部视图在 垂直方向
从上往下排列 -
如果不指定
orientation
属性, 则 LinearLayout
默认水平方向排列 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!-- 水平布局 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="横排文本第一个" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="横排文本第二个" />
</LinearLayout>
<!-- 垂直布局 -->
<!-- 水平布局 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="横排文本第一个" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="横排文本第二个" />
</LinearLayout>
</LinearLayout>线性布局 -
线性布局的权重
- 线性布局权重的概念: 指的是线性布局的下级视图各自拥有多大比例的宽高
- 权重属性名叫
layout_weight
但该属性不在 LinearLayout
节点设置, 而在线性布局的直接下级视图设置, 表示该下级视图占据的宽高比例 layout_width
填 0dp
时, layout_width
表示水平方向的宽度比例 layout_height
填 0dp
时, layout_width
表示垂直方向的高度比例
-
相对布局
-
相对布局: 相对布局的下级视图位置由其他视图决定。用于确定下级视图位置的参照物分为两种
- 与该视图自身平级的视图
- 该视图的上级视图
(也就是它归属的 RelativeLayout
)
如果不设定下级视图的参照物,
那么下级视图默认显示在 RelativeLayout
内部的坐上角 -
layout_centerInParent="true"
1
2
3
4
5
6
7<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="垂直居中位置(中心点)"
android:textColor="@color/red"
android:textSize="16sp"/>layout_centerInParent
-
水平中间
1
2
3
4
5
6
7<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:text="水平中间"
android:textColor="@color/red"
android:textSize="16sp"/>水平中间位置 -
垂直位置
1
2
3
4
5
6
7<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:text="垂直中间"
android:textColor="@color/green"
android:textSize="26sp"/>垂直位置 -
其他取值
其他取值
网格布局
-
网格布局支持多行多列的表格排列
-
网格布局默认从左往右,
从上到下排列, 它新增了两个属性 columnCount
属性, 它指定了网格的列数, 即每行能放多少个视图 rowCount
属性, 它指定了网格的行数, 即每列能放多少个视图
-
创建一个两行两列的布局
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49<!-- GridLayout: 创建一个两行两列的布局 -->
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:columnCount="2"
android:rowCount="2">
<TextView
android:layout_width="0dp"
android:layout_height="60dp"
android:layout_columnWeight="1"
android:background="#ffcccc"
android:gravity="center"
android:text="浅红色"
android:textColor="#000000"
android:textSize="17sp" />
<TextView
android:layout_width="0dp"
android:layout_height="60dp"
android:layout_columnWeight="1"
android:background="#ffaa00"
android:gravity="center"
android:text="橙色"
android:textColor="#000000"
android:textSize="17sp" />
<TextView
android:layout_width="0dp"
android:layout_height="60dp"
android:layout_columnWeight="1"
android:background="#00ff00"
android:gravity="center"
android:text="绿色"
android:textColor="#000000"
android:textSize="17sp" />
<TextView
android:layout_width="0dp"
android:layout_height="60dp"
android:layout_columnWeight="1"
android:background="#660066"
android:gravity="center"
android:text="深紫色"
android:textColor="#000000"
android:textSize="17sp" />
</GridLayout>创建一个两行两列的布局
滚动视图
-
滚动视图有两种
ScrollView
: 它是垂直方向的滚动视图,垂直方向滚动时, layout_width
属性设置为 match_parent,layout_height
属性设置未 wrap_content
HorizontalScrollView
:它是水平方向的滚动视图,水平方向滚动, layout_width
属性值设置为 wrap_content,layout_height
属性值设置为 match_parent
-
练习
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<HorizontalScrollView
android:layout_width="wrap_content"
android:layout_height="200dp">
<!-- 水平方向的线性布局: 两个子视图的颜色分别为青色和黄色 -->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal">
<View
android:layout_width="300dp"
android:layout_height="match_parent"
android:background="#aaffff" />
<View
android:layout_width="300dp"
android:layout_height="match_parent"
android:background="#FAFA43" />
</LinearLayout>
</HorizontalScrollView>
</LinearLayout>水平滚动 -
垂直滚动
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!-- 水平方向的线性布局: 两个子视图的颜色分别为青色和黄色 -->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="vertical">
<View
android:layout_width="match_parent"
android:layout_height="400dp"
android:background="#aaffff" />
<View
android:layout_width="match_parent"
android:layout_height="400dp"
android:background="#FAFA43" />
</LinearLayout>
</ScrollView>
</LinearLayout>
按钮控件-BUTTON
-
BUTTON
:由 TextView
派生而来, 它们之间的区别有 BUTTON
拥有默认的按钮背景, 而 TextView
默认无背景 BUTTON
的内部文本默认居中对齐, 而 TextView
的内部文本默认靠左对齐 BUTTON
会默认将英文字母转换为大写, 而 TextView
保持原始的英文大小写
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextView"
android:textColor="@color/green"
android:textSize="17sp">
</TextView>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Button"
android:textColor="@color/green"
android:textSize="17sp">
</Button>
</LinearLayout>-
与
TextView
相比, Button
增加了两个新属性 -
textAllCaps
属性, 它指定了是否将英文字母转为大写, 为 true
是表示自动转为大写, 为 false
表示不做大写转换 -
onClick
属性, 它用来接管用户的点击动作, 指定了点击按钮时要触发那个方法 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextView"
android:textColor="@color/green"
android:textSize="17sp">
</TextView>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Button"
android:textColor="@color/green"
android:textSize="17sp">
</Button>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="textAllCaps属性使用"
android:textAllCaps="false"
android:textColor="@color/green"
android:textSize="17sp">
</Button>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="指定点击事件"
android:textAllCaps="false"
android:onClick="doClick"
android:textColor="@color/green"
android:textSize="17sp">
</Button>
</LinearLayout>按钮点击事件处理 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class ButtonStyleActivity extends AppCompatActivity {
private TextView showTime;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_button_style);
showTime = findViewById(R.id.showTime);
}
// 按钮点击事件 doClick 处理
public void doClick(View view) {
// 在另一个 TextView 上显示当前时间
String desc = String.format("%s 您点击了按钮: %s", getNowTime(), ((Button) (view)).getText());
// 设置文本信息
showTime.setText(desc);
}
public static String getNowTime() {
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
return sdf.format(new Date());
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextView"
android:textColor="@color/green"
android:textSize="17sp">
</TextView>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Button"
android:textColor="@color/green"
android:textSize="17sp">
</Button>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="textAllCaps属性使用"
android:textAllCaps="false"
android:textColor="@color/green"
android:textSize="17sp">
</Button>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="textAllCaps属性使用和指定点击事件"
android:textAllCaps="false"
android:onClick="doClick"
android:textColor="@color/green"
android:textSize="17sp">
</Button>
<TextView
android:id="@+id/showTime"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="显示当前时间"
android:textColor="@color/green"
android:textSize="17sp">
</TextView>
</LinearLayout>
-
-
点击事件和长按事件
-
监听器,
意思是专门监听控件的动作行为, 只有控件发生了指定动作, 监听器才会触发开关去执行对应的代码逻辑 -
按钮控件有两种常用的监听器
-
点击监听器: 通过
setOnClickListener
方法设置. 按钮被按住少于 500ms
时会触发点击事件 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42package com.coderitl.chapter03;
public class ButtonActivity extends AppCompatActivity {
private TextView show_single_res;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_button);
// 获取按钮
Button button = findViewById(R.id.btn_click_single);
// 获取显示文本
show_single_res = findViewById(R.id.show_single_res);
button.setOnClickListener(new MyOnClickListener(show_single_res));
}
public static String getTime() {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm:ss");
return simpleDateFormat.format(new Date());
}
// 点击事件的回调
static class MyOnClickListener implements View.OnClickListener {
private final TextView show_single_res;
public MyOnClickListener(TextView show_single_res) {
this.show_single_res = show_single_res;
}
public void onClick(View view) {
String desc = String.format("%s 您点击了按钮: %s", getTime(), ((Button) (view)).getText());
show_single_res.setText(desc);
}
}
}
// 也可以指定公共点击事件 public class ButtonActivity extends AppCompatActivity implements View.OnClickListener
// button.setOnClickListener(this);1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/btn_click_single"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="指定单独的点击监听器"
android:textColor="#000000"
android:textSize="20sp"></Button>
<TextView
android:id="@+id/show_single_res"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="显示按钮点击结果"
android:textColor="@color/red"
android:textSize="20dp" />
</LinearLayout> -
长按监听器
L 通过 setonLongClickListener
方法设置. 按钮被按住超过 500ms
时, 会触发长按事件 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37package com.coderitl.chapter03;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import java.text.SimpleDateFormat;
import java.util.Date;
public class LongClickListenerActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_long_click_listener);
// 获取按钮
Button button = findViewById(R.id.btn_long_click);
// 获取文本
TextView show_long_res = findViewById(R.id.show_long_res);
button.setOnLongClickListener(view -> {
// 在另一个 TextView 上显示当前时间
String desc = String.format("%s 您点击了按钮: %s", getNowTime(), ((Button) (view)).getText());
// 设置文本信息
show_long_res.setText(desc);
return true;
});
}
public static String getNowTime() {
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
return sdf.format(new Date());
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/btn_long_click"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="指定长按的点击监听器"
android:textColor="#000000"
android:textSize="20sp"></Button>
<TextView
android:id="@+id/show_long_res"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="5dp"
android:text="显示按钮点击结果"
android:textColor="@color/red"
android:textSize="20dp" />
</LinearLayout>
-
-
-
禁用和回复按钮
-
不可用按钮: 按钮不允许点击,
即使点击也没有反应, 同时按钮文字变为灰色 -
可用按钮: 按钮允许点击,
点击按钮会触发点击事件, 同时按钮文字为正常黑色 -
是否允许点击由
enabled
属性控制, 属性值为 true
时表示允许点击, 为 false
时表示不允许点击 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70package com.coderitl.chapter03;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import java.text.SimpleDateFormat;
import java.util.Date;
public class ButtonEnable extends AppCompatActivity implements View.OnClickListener {
private Button btn_test;
private TextView tv_result;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_button_enable);
// 获取启用按钮
Button btn_enable = findViewById(R.id.btn_enable);
// 获取禁用按钮
Button btn_disable = findViewById(R.id.btn_disable);
// 测试按钮
btn_test = findViewById(R.id.btn_test);
// 显示结果的文本
tv_result = findViewById(R.id.tv_result);
btn_enable.setOnClickListener(this);
btn_disable.setOnClickListener(this);
btn_test.setOnClickListener(this);
}
// 公共点击事件处理
public void onClick(View view) {
switch (view.getId()) {
case R.id.btn_enable:
// 设置 test 按钮可用
btn_test.setEnabled(true);
btn_test.setTextColor(Color.BLACK);
break;
case R.id.btn_disable:
// 设置 test 按钮不可用
btn_test.setEnabled(false);
btn_test.setTextColor(Color.GRAY);
break;
case R.id.btn_test:
// 当按钮可用时,获取相应信息
String desc = String.format("%s 您点击了按钮: %s", getTime(), ((Button) (view)).getText());
tv_result.setText(desc);
break;
}
}
public static String getTime() {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm:ss");
return simpleDateFormat.format(new Date());
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/btn_enable"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="启用按钮"
android:textColor="@color/black"
android:textSize="20dp"></Button>
<Button
android:id="@+id/btn_disable"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="禁用用按钮"
android:textColor="@color/gray"
android:textSize="20dp"></Button>
</LinearLayout>
<Button
android:id="@+id/btn_test"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="测试按钮"
android:enabled="false"
android:textColor="#888888"
android:textSize="20dp"></Button>
<TextView
android:id="@+id/tv_result"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="显示测试按钮点击结果"
android:textColor="@color/red"
android:textSize="20dp"></TextView>
</LinearLayout>
-
图像显示ImageView
-
图像视图展示的图片通常位于
res/drawable
目录,设置图像视图的显示图片有两种方式 -
在
XML
文件中, 通过属性 android:src
设置图片资源, 属性值格式形如 @drawable/
不含扩展名的图片名称 -
在
Java
代码中, 调用 setImageResource
方法设置图片资源, 方法参数格式形如 R.drawable.
不含扩展名的图片名称 1
2
3
4
5
6
7
8
9
10
11
12
13
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/iv_scale"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp">
</ImageView>
</LinearLayout>图片资源 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20// Java 代码设置图片资源
package com.coderitl.chapter03;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ImageView;
public class ImageViewActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_image_view);
// 获取 ImageView
ImageView imageView = findViewById(R.id.iv_scale);
// 设置图片 无后缀
imageView.setImageResource(R.drawable.fish);
}
} -
图像的缩放类型
ImageView
本身默认图片居中显示, 若要改变图片的显示方式, 可通过 scaleType
属性设定, 该属性的取值如下 XML
中的缩放类型 ScaleType
类中的缩放类型 说明 fitXY
FIT_XY
拉伸图片使其正好填满视图 (图片可能被拉伸变形) fitStart
FIT_START
保持宽高比例, 拉伸图片使其位于视图上方或左侧 fitCenter
FIT_CENTER
保持宽高比例, 拉伸图片使其位于视图中间 fitEnd
FIT_END
保持宽高比例, 拉伸图片使其位于试图下方或右侧 center
CENTER
保持图片源尺寸, 并使其位于视图中间 centerCrop
CENTER_CROP
拉伸图片使其充满视图, 并位于视图中间 centerinside
CENTER_INSIDE
保持宽高比例, 缩小图片使之位于视图中间 (只缩小不放大)
-
图像按钮
ImageButton
是显示图片的图像按钮,但它继承自 ImageView
而非继承 Button
ImageButton
和 Button
之间的区别有: Button
即可显示文本也可显示图片, ImageButton
只能显示图片不能显示文本 ImageButton
上的图像可按比例缩放, 而 Button
通过背景设置的图像会拉伸变形 Button
只能靠背景显示一张图片, 而 ImageButton
可分别在前景和背景显示图片, 从而实现两张图片叠加的效果
同时展示文本与图像
-
同时展示文本与图像的可能途径包括
-
利用
LinearLayout
对 ImageView
和 TextView
组合布局 -
通过按钮控件
Button
的 drawable
属性设置文本周围的图标 -
drawableTop
指定文字上方的图片 -
drawableBottom
指定文字下方的图片 -
drawableLeft
指定文字左边的图片 -
drawableRight
指定文字右边的图片 -
drawablePadding
指定图片与文字的间距 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/icon"
android:drawablePadding="5dp"
android:text="文字在左侧"
android:textColor="@color/red">
</Button>
</LinearLayout>
-
-
计算器
-
实现分析
- 线性布局:
计算器的整体布局是从上到下排列着的 - 网格布局: 计算器下半部分的几排按钮,正好成五行四列表格分布,
适合采用 GridLayout
- 滚动视图
ScrollView
: 计算器界面如果超出屏幕大小,就要支持滚动 - 文本视图
TextView
计算结果文本需要使用 TextView
且文字靠下靠右显示 - 按钮
Button
用于 0-9
的数字按键, 以及 加减乘除
等元素按键 - 图像按钮
ImageButton
:开根号的运算符对号
虽然能够打出来,但是右上角少了一横, 所以该按钮要用一张标准的开根号图片显示
- 线性布局:
-
布局结构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#EEEEEE"
android:orientation="vertical"
android:padding="5dp">
<!-- 滚动布局 -->
<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="@string/calculator_title"
android:textColor="@color/black"
android:textSize="20sp"></TextView>
<!-- 计算显示 -->
<TextView
android:id="@+id/tv_result"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:gravity="right|bottom"
android:lines="3"
android:text="0"
android:textColor="@color/black"
android:textSize="25sp">
</TextView>
<!-- 网格布局: 数组按钮与符号 -->
<GridLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:columnCount="4"
android:rowCount="5">
<!-- CE -->
<Button
android:id="@+id/btn_cancel"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:layout_columnWeight="1"
android:layout_margin="5dp"
android:gravity="center"
android:text="@string/cancel"
android:textColor="@color/black"
android:textSize="@dimen/button_font_size" />
<!-- ➗ -->
<Button
android:id="@+id/divide"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:layout_columnWeight="1"
android:layout_margin="5dp"
android:gravity="center"
android:text="@string/divide"
android:textColor="@color/black"
android:textSize="@dimen/button_font_size" />
<!-- x -->
<Button
android:id="@+id/multiply"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:layout_columnWeight="1"
android:layout_margin="5dp"
android:gravity="center"
android:text="@string/multiply"
android:textColor="@color/black"
android:textSize="@dimen/button_font_size" />
<!-- C -->
<Button
android:id="@+id/clear"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:layout_columnWeight="1"
android:layout_margin="5dp"
android:gravity="center"
android:text="@string/clear"
android:textColor="@color/black"
android:textSize="@dimen/button_font_size" />
<!-- 7 -->
<Button
android:id="@+id/seven"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:layout_columnWeight="1"
android:layout_margin="5dp"
android:gravity="center"
android:text="@string/seven"
android:textColor="@color/black"
android:textSize="@dimen/button_font_size" />
<!-- 8 -->
<Button
android:id="@+id/eight"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:layout_columnWeight="1"
android:layout_margin="5dp"
android:gravity="center"
android:text="@string/eight"
android:textColor="@color/black"
android:textSize="@dimen/button_font_size" />
<!-- 9 -->
<Button
android:id="@+id/nine"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:layout_columnWeight="1"
android:layout_margin="5dp"
android:gravity="center"
android:text="@string/nine"
android:textColor="@color/black"
android:textSize="@dimen/button_font_size" />
<!-- + -->
<Button
android:id="@+id/plus"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:layout_columnWeight="1"
android:layout_margin="5dp"
android:gravity="center"
android:text="@string/plus"
android:textColor="@color/black"
android:textSize="@dimen/button_font_size" />
<!-- 4 -->
<Button
android:id="@+id/four"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:layout_columnWeight="1"
android:layout_margin="5dp"
android:gravity="center"
android:text="@string/four"
android:textColor="@color/black"
android:textSize="@dimen/button_font_size" />
<!-- 5 -->
<Button
android:id="@+id/five"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:layout_columnWeight="1"
android:layout_margin="5dp"
android:gravity="center"
android:text="@string/five"
android:textColor="@color/black"
android:textSize="@dimen/button_font_size" />
<!-- 6 -->
<Button
android:id="@+id/six"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:layout_columnWeight="1"
android:layout_margin="5dp"
android:gravity="center"
android:text="@string/six"
android:textColor="@color/black"
android:textSize="@dimen/button_font_size" />
<!-- - -->
<Button
android:id="@+id/minus"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:layout_columnWeight="1"
android:layout_margin="5dp"
android:gravity="center"
android:text="@string/minus"
android:textColor="@color/black"
android:textSize="@dimen/button_font_size" />
<!-- 1 -->
<Button
android:id="@+id/one"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:layout_columnWeight="1"
android:layout_margin="5dp"
android:gravity="center"
android:text="@string/one"
android:textColor="@color/black"
android:textSize="@dimen/button_font_size" />
<!-- 2 -->
<Button
android:id="@+id/two"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:layout_columnWeight="1"
android:layout_margin="5dp"
android:gravity="center"
android:text="@string/two"
android:textColor="@color/black"
android:textSize="@dimen/button_font_size" />
<!-- 3 -->
<Button
android:id="@+id/three"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:layout_columnWeight="1"
android:layout_margin="5dp"
android:gravity="center"
android:text="@string/three"
android:textColor="@color/black"
android:textSize="@dimen/button_font_size" />
<!-- 根号 -->
<ImageButton
android:id="@+id/ib_sqrt"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:layout_columnWeight="1"
android:layout_margin="5dp"
android:scaleType="centerInside"
android:src="@drawable/sqrt" />
<!-- 1/x -->
<Button
android:id="@+id/reciprocal"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:layout_columnWeight="1"
android:layout_margin="5dp"
android:gravity="center"
android:text="@string/reciprocal"
android:textColor="@color/black"
android:textSize="@dimen/button_font_size" />
<!-- 0 -->
<Button
android:id="@+id/zero"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:layout_columnWeight="1"
android:layout_margin="5dp"
android:gravity="center"
android:text="@string/zero"
android:textColor="@color/black"
android:textSize="@dimen/button_font_size" />
<!-- . -->
<Button
android:id="@+id/dot"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:layout_columnWeight="1"
android:layout_margin="5dp"
android:gravity="center"
android:text="@string/dot"
android:textColor="@color/black"
android:textSize="@dimen/button_font_size" />
<!-- = -->
<Button
android:id="@+id/equal"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:layout_columnWeight="1"
android:layout_margin="5dp"
android:gravity="center"
android:text="@string/equal"
android:textColor="@color/black"
android:textSize="@dimen/button_font_size" />
</GridLayout>
</LinearLayout>
</ScrollView>
</LinearLayout> -
常量定义
-
界面信息定义
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25<!-- res/values/string.xml -->
<resources>
<string name="app_name">CalculatorActivity</string>
<!-- 计算器名称 -->
<string name="calculator_title">简易计算器 </string>
<string name="cancel">CE</string>
<string name="divide">÷</string>
<string name="multiply">x</string>
<string name="clear">C</string>
<string name="seven">7</string>
<string name="eight">8</string>
<string name="nine">9</string>
<string name="plus">+</string>
<string name="four">4</string>
<string name="five">5</string>
<string name="six">6</string>
<string name="minus">-</string>
<string name="one">1</string>
<string name="two">2</string>
<string name="three">3</string>
<string name="reciprocal">1/x</string>
<string name="zero">0</string>
<string name="dot">.</string>
<string name="equal">=</string>
</resources> -
尺寸定义
1
2
3
4
5
6<!-- res/values/dimens.xml -->
<resources>
<dimen name="button_font_size">30sp</dimen>
<dimen name="button_height">75dp</dimen>
</resources> -
颜色
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29<!-- res/values/colors.xml -->
<resources>
<color name="purple_200">#FFBB86FC</color>
<color name="purple_500">#FF6200EE</color>
<color name="purple_700">#FF3700B3</color>
<color name="teal_200">#FF03DAC5</color>
<color name="teal_700">#FF018786</color>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
<color name="gray">#D6D7D7</color>
<color name="colorPrimary">#3F51B5</color>
<color name="colorPrimaryDark">#303F9F</color>
<color name="colorAccent">#FF4081</color>
<color name="colorBlue">#729FFA</color>
<color name="colorGrayDark">#807877</color>
<color name="colorGrayLight">#B7A4A1</color>
<color name="colorOrange">#FA8072</color>
<color name="colorOrangeDark">#DA6052</color>
<color name="colorSalmon">#FFA07B</color>
<color name="colorSalmonDark">#D18263</color>
<color name="colorWhite">#FFFFFF</color>
<color name="colorGray">#9A614D</color>
<color name="colorBackground">#F5D3C7</color>
<color name="colorBlackBlue">#4B0082</color>
</resources> -
界面按钮颜色通过修改主题颜色
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.CalculatorActivity" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/gray</item>
<item name="colorPrimaryVariant">@color/colorAccent</item>
<item name="colorOnPrimary">@color/colorBlackBlue</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_700</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
</style>
</resources>
-
-
按钮事件逻辑处理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164package com.coderitl.calculatoractivity;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private TextView tv_result;
// 第一个操作数
private String firstNum = "";
// 运算符
private String operator = "";
// 第二个操作数
private String secondNum = "";
// 当前的计算结果
private String result = "";
// 显示的文本内容
private String showText = "";
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 获取计算器界面的所有信息
// 结果框
tv_result = findViewById(R.id.tv_result);
// CE
findViewById(R.id.btn_cancel).setOnClickListener(this);
// ÷(除号)
findViewById(R.id.divide).setOnClickListener(this);
findViewById(R.id.multiply).setOnClickListener(this);
findViewById(R.id.clear).setOnClickListener(this);
findViewById(R.id.seven).setOnClickListener(this);
findViewById(R.id.eight).setOnClickListener(this);
findViewById(R.id.nine).setOnClickListener(this);
findViewById(R.id.plus).setOnClickListener(this);
findViewById(R.id.four).setOnClickListener(this);
findViewById(R.id.five).setOnClickListener(this);
findViewById(R.id.six).setOnClickListener(this);
findViewById(R.id.minus).setOnClickListener(this);
findViewById(R.id.one).setOnClickListener(this);
findViewById(R.id.two).setOnClickListener(this);
findViewById(R.id.three).setOnClickListener(this);
findViewById(R.id.ib_sqrt).setOnClickListener(this);
findViewById(R.id.reciprocal).setOnClickListener(this);
findViewById(R.id.zero).setOnClickListener(this);
findViewById(R.id.dot).setOnClickListener(this);
findViewById(R.id.equal).setOnClickListener(this);
}
// 公共按钮点击事件处理
public void onClick(View v) {
String inputText;
// 如果是开根号
if (v.getId() == R.id.ib_sqrt) {
inputText = "√";
} else {
// 除了开根号之外的其他按钮使用按钮上的文本
inputText = ((TextView) v).getText().toString();
}
switch (v.getId()) {
// 清除按钮
case R.id.clear:
clear();
break;
// 取消按钮
case R.id.btn_cancel:
break;
// 点击了 = - x /
case R.id.plus:
case R.id.minus:
case R.id.multiply:
case R.id.divide:
// 运算符
operator = inputText;
refreshText(showText + operator);
break;
// 点击了等号
case R.id.equal:
// + - x / 四则运算
double calculate_result = calculateFour();
// 更新下一次结果
refreshOperate(String.valueOf(calculate_result));
refreshText(showText + "=" + result);
break;
// 开根号
case R.id.ib_sqrt:
double sqrt_result = Math.sqrt(Double.parseDouble(firstNum));
refreshOperate(String.valueOf(sqrt_result));
refreshText(showText + "√=" + result);
break;
// 求倒数按钮
case R.id.reciprocal:
double reciprocal_result = 1.0/Double.parseDouble(firstNum);
refreshOperate(String.valueOf(reciprocal_result));
refreshText(showText + "/=" + result);
break;
// 点击了其他按钮 包括数字和小数点
default:
// 上次的运算结果已经出来了
if (result.length() > 0 && operator.equals("")) {
clear();
}
// 无运算符 则继续拼接第一个操作数
if (operator.equals("")) {
firstNum = firstNum + inputText;
} else {
// 有运算符 则继续拼接第二个操作数
secondNum = secondNum + inputText;
}
// 显示结果 整数不需要前面的 0
if (showText.equals("0") && !inputText.equals(".")) {
refreshText(inputText);
} else {
refreshText(showText + inputText);
}
break;
}
}
private double calculateFour() {
switch (operator) {
case "+":
return Double.parseDouble(firstNum) + Double.parseDouble(secondNum);
case "-":
return Double.parseDouble(firstNum) - Double.parseDouble(secondNum);
case "x":
return Double.parseDouble(firstNum) * Double.parseDouble(secondNum);
case "÷":
return Double.parseDouble(firstNum) / Double.parseDouble(secondNum);
}
return 0;
}
// 清除按钮事件
private void clear() {
refreshOperate("");
refreshText("");
}
// 刷新运算结果 9+1=10(result)+3=13
private void refreshOperate(String new_result) {
result = new_result;
firstNum = result;
secondNum = "";
operator = "";
}
// 刷新文本显示
private void refreshText(String text) {
showText = text;
tv_result.setText(showText);
}
} -
界面渲染
界面渲染
Activity 启动与结束
隐藏标题栏
-
配置
1
2ActionBar actionBar = getSupportActionBar();
actionBar.hide();
在活动之间传递消息
-
显示
Intent
和隐式 Intent
Intent
是各个组件之间信息沟通的桥梁,它用于 Android
各组件之间的通信,主要完成下列工作 - 表明本次通信请求从哪里来,到哪里去,要怎么走
- 发起方携带本次通信需要的数据内容,接受方从收
i 到的意图中解析数据 - 发起方若想判断接收方的处理结果,意图就要负责方传回应答的数据内容
-
Intent
的组成部分 元素名称 设置方法 说明与用途 Comonent
setComponent
组件,他指定意图的来源与目标 Action
setAction
动作,它指定意图的动作行为 Data
setData
即 URI
它指定动作要操纵的数据路径 Category
addCategory
类别,它指定意图的操作类别 Type
setType
数据类型,它指定装载的包裹信息 Extras
putExtras
扩展消息,它指定装载的包裹信息 Flags
setFlags
标志位,它指定活动的启动标志 -
显示
Intent
直接指定来源活动与目标活动,属于精确匹配,它有 -
在
Intent
的构造函数中指定 1
2// 创建一个目标确定的意图
Intent intent = new Intent(this,SencondActivity.class); -
调用意图对象的
setClass
方法指定 1
2
3
4// 创建一个新意图
Intent intent = new Intent();
// 设置意图要跳转的目标活动
intent.setClass(this,SencondActivity.class); -
调用意图对象的
setComponent
方法指定 1
2
3
4
5
6// 创建一个新意图
Intent intent = new Intent();
// 创建包含目标活动在内的组件名称对象
ComponentName component = new ComponentName(this,SencondActivity.class);
// 设置意图携带的组件信息
intent.setComponent(component);
-
-
隐式
Intent
,没有明确指定要跳转的目标活动,只给出一个动作字符串让系统自动匹配,属于模糊匹配
向下一个 Activity 发送数据
-
源文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67// 第一个主页面
package com.example.userlogin;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.RadioButton;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private EditText username;
private EditText password;
String sex;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 获取文本框
username = findViewById(R.id.username);
password = findViewById(R.id.password);
// 登录按钮点击事件
findViewById(R.id.toSecondActivity).setOnClickListener(this);
}
public void onClick(View view) {
Log.i("toSecondActivity", "to second activity...........");
// 页面跳转 显示意图
Intent intent = new Intent(this, SencondActivity.class);
// 传输的数据(打包)
Bundle bundle = new Bundle();
bundle.putString("username", username.getText().toString());
bundle.putString("password", password.getText().toString());
bundle.putString("sex", sex);
intent.putExtras(bundle);
startActivity(intent);
}
public void onRadioButtonClicked(View view) {
// Is the button now checked?
boolean checked = ((RadioButton) view).isChecked();
// Check which radio button was clicked
switch (view.getId()) {
case R.id.male:
if (checked) sex = "男";
// Pirates are the best
break;
case R.id.fmale:
if (checked) sex = "女";
// Ninjas rule
break;
}
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127<!-- 主页面布局 -->
<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"
android:background="@color/gray"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginTop="20dp"
android:src="@drawable/blue_people" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="20dp"
android:background="#FFFFFF"
android:gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:text="账号: "
android:textSize="22dp" />
<EditText
android:id="@+id/username"
android:layout_width="300dp"
android:layout_height="70dp"
android:layout_marginLeft="15dp"
android:hint="在此输入账号"
android:textSize="22dp" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="20dp"
android:background="#FFFFFF"
android:gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:text="密码: "
android:textSize="22dp" />
<EditText
android:id="@+id/password"
android:layout_width="300dp"
android:layout_height="70dp"
android:layout_marginLeft="15dp"
android:hint="在此输入账号密码"
android:password="true"
android:textSize="22dp"
tools:ignore="Deprecated" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="20dp"
android:background="#FFFFFF">
<RadioGroup
android:id="@+id/radioGroup"
android:layout_width="380dp"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:text="性别: "
android:textSize="22dp" />
<RadioButton
android:id="@+id/male"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="30dp"
android:gravity="center"
android:text="男"
android:onClick="onRadioButtonClicked"
android:textSize="22dp" />
<RadioButton
android:id="@+id/fmale"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="30dp"
android:gravity="center"
android:text="女"
android:onClick="onRadioButtonClicked"
android:textSize="22dp" />
</RadioGroup>
</LinearLayout>
<Button
android:id="@+id/toSecondActivity"
android:layout_width="150dp"
android:layout_height="65dp"
android:layout_gravity="center"
android:layout_marginTop="20dp"
android:backgroundTint="#03A9F4"
android:text="登录"
android:textSize="22dp" />
</LinearLayout>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29// 第二个 activity
package com.example.userlogin;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.TextView;
public class SencondActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sencond);
// 获取传递进来的数据
TextView show_tv_name = findViewById(R.id.tv_name);
TextView show_tv_psw = findViewById(R.id.tv_psw);
TextView show_tv_sex = findViewById(R.id.tv_sex);
// 从上一个页面传来的意图中获取快读包裹
Bundle bundle = getIntent().getExtras();
String username = bundle.getString("username");
show_tv_name.setText("用户姓名: " + username);
String password = bundle.getString("password");
show_tv_psw.setText("用户密码: " + password);
String sex = bundle.getString("sex");
show_tv_sex.setText("用户性别: " + sex);
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<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">
<LinearLayout
android:layout_width="409dp"
android:layout_height="729dp"
android:orientation="vertical"
tools:layout_editor_absoluteX="1dp"
tools:layout_editor_absoluteY="1dp">
<TextView
android:id="@+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="20dp"
android:layout_marginLeft="15dp"
android:text="欢迎登录"
android:textColor="@color/black"
android:textSize="32dp" />
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:text="用户姓名:"
android:textSize="22dp" />
<TextView
android:id="@+id/tv_psw"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:text="用户密码:"
android:textSize="22dp" />
<TextView
android:id="@+id/tv_sex"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:text="用户性别:"
android:textSize="22dp" />
<Button
android:layout_width="150dp"
android:layout_height="65dp"
android:layout_gravity="center"
android:layout_marginTop="20dp"
android:text="课程调查"
android:textSize="22dp" />
</LinearLayout>
</LinearLayout>
向上一个 Activity 回显数据
-
页面跳转与数据回显
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15// 调查按钮点击事件
public void onClick(View view) {
Intent intent = new Intent(this, ThirdActivity.class);
startActivityForResult(intent, 1);
}
// 后编写
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 1 && resultCode == 2) {
String appraise = data.getStringExtra("appraise");
Toast.makeText(this, appraise, Toast.LENGTH_LONG).show();
}
}点击后跳转 -
携带数据的页面
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48package com.example.userlogin;
public class ThirdActivity extends AppCompatActivity implements View.OnClickListener {
// 评价
private String appraise = "喜欢";
private ActivityResultLauncher<Intent> register;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_third);
// Toast.makeText(Context,"数据",3).show();
findViewById(R.id.to_login_data).setOnClickListener(this);
// startActivityForResult(); 过时: 解决方案
register = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() {
public void onActivityResult(ActivityResult result) {
}
});
}
public void onRadioButtonClicked(View view) {
boolean checked = ((RadioButton) view).isChecked();
switch (view.getId()) {
case R.id.better:
if (checked) appraise = "十分喜欢";
break;
case R.id.like:
if (checked) appraise = "喜欢";
break;
case R.id.dislike:
if (checked) appraise = "不喜欢";
break;
}
}
public void onClick(View view) {
Intent intent = new Intent();
intent.putExtra("appraise", appraise);
setResult(2, intent);
// 关闭当前界面
finish();
}
}将选中的值回传 显示回传数据