阅读本文需要有Java和前端的基础,本文是我学习Android时的笔记。
一、UI开发
AS快捷键
| Info | Key |
|---|---|
| 复制行 | Ctrl+D |
| 删除行 | Ctrl+Y |
| 注释 | Ctrl+/ |
| 注释2 | Ctrl+Shift+/ |
| 撤销 | Ctrl+Z |
| 恢复 | Ctrl+Shift+Z |
| 显示结构 | Ctrl+F12 |
| 格式化代码 | Ctrl+Alt+L |
| 打开设置 | Ctrl+Alt+S |
| 自动补全代码 | Ctrl+Shift+Space |
| 自动导包 | Alt+Enter |
布局
1.线性布局(LinearLayout)
一些重要属性
//控制子控件的排列方向
orientation="vertical" //垂直
orientation="horizontal" //水平
//设置权重(权重总和为分母,可用于屏幕按钮的适配)
layout_weight="1"
2.相对布局(RelaviteLayout)
Layout下的控件属性:
| 控件位置 | Info |
|---|---|
| layout_centerInParent | 位于 父的 正中央 |
| layout_centerVertical | 位于 父的 垂直中 |
| layout_centerHorizontal | 位于 父的 水平中 |
| layout_above | 位于 某的 上 |
| layout_below | 位于 某的 下 |
| layout_toLeftOf | 位于 某的 左 |
| layout_toRightOf | 位于 某的 右 |
| layout_alignParentTop | 是否与父 顶 对齐 |
| layout_alignParentLeft | 是否与父 左 对齐 |
| layout_alignParentRight | 是否与父 右 对齐 |
| layout_alignParentBottom | 是否与父 底 对齐 |
| layout_alignTop | 与某的 上 对齐 |
| layout_alignLeft | 与某的 左 对齐 |
| layout_alignRight | 与某的 下 对齐 |
| layout_alignBottom | 与某的 右 对齐 |
与前端CSS类似
| 控件间距(Margin) | 布局内边距(Padding) |
|---|---|
| layout_marginTop | paddingTop |
| layout_marginBottom | paddingBottom |
| layout_marginLeft | paddingLeft |
| layout_marginRight | paddingRight |
| padding |
3.针布局(FrameLayout)
该布局为每个加入其中的控件创建一个空白区域(称为一帧,每个控件占据一帧),所以控件默认显示在左上角,先放的在最底层。
| Key | Info |
|---|---|
| foreground | 设置容器的前景图 |
| foregroundGravity | 设置前景图显示位置 |
4.表格布局(TableLayout)
需要和TableRow标签配合使用,TableRow的数量决定表格的行数。
| 布局属性 | Info |
|---|---|
| stretchColumns | 设置列可 拉伸 |
| shrinkColumns | 设置列可 收缩 |
| collapseColumns | 设置列可 隐藏 |
| 控件属性 | Info |
|---|---|
| layout_column | 在控件少于单元格的情况下,指定显示的位置 |
| layout_span | 默认为1,可指定控件占几个单元格 |
5.绝对布局(AbsoluteLayout)
//布局属性
layout_x = "50dp";
layout_y = "100dp";
常用控件
1.TextView
| 控件属性 | Info |
|---|---|
| text | |
| textColor | |
| textSize | sp |
| textStyle | bold,italic |
| gravity | 文本位置 |
| layout_width | 控件高 |
| layout_height | wrap_content , match_parent |
| height | 文本域高( 不常用) |
| width | 文本域宽( 不常用) |
| maxLength | 文本最大长度 |
| phoneNumber | 以电话形式显示 |
| password | 以密码形式显示 |
2.EditView
| 控件属性 | Info |
|---|---|
| hint | 提示文本 |
| lines | 设置固定行高 |
| maxLines | 最大行数 |
| minLines | 最小行数 |
| password | 以密码形式显示 |
| phoneNumber | 以电话形式显示 |
| scrollHorizontally | 水平滚动条 |
| capitalize | 首字母大写 |
| editable | 是否可编辑 |
background="@null"属性为去掉控件默认的下划线
3.Button
点击事件的两种实现方法
<Button
android:id="@+id/btn1"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
//onClick方法已经弃用了
<Button
android:id="@+id/btn2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="click"/>
//lambda表达式
btn1.setOnClickListener(view -> {
btn1.setText("btn1");
});
public void click(View v){
btn2.setText("btn2");
}
按钮点击事件较多的情况下,实现OnClickListener接口,重写onClick方法:
public class MainActivity implements View.OnClickListener{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
//TODO 初始化N个控件...
}
@Override
public void onClick(View v){
switch(v.getId()){
case R.id.btn1:
btn1.setText("btn1");
case R.id.btn2:
btn1.setText("btn2");
//......
}
}
}
4.RadioButton
Radiobutton 需要与 RadioGroup 配合使用
//RadioGroup控件的属性 控制子控件的排列方向
orientation="vertical" //垂直
orientation="horizontal" //水平
//RadioButtion控件的属性 设置按钮默认为选中状态
checked="ture"
监听事件(setOnCheckedChangeListener)
radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup radioGroup, int i) {
if(i == R.id.rbtn){
//TODO
}else{
//TODO
}
});
5.ImageView
//background是背景,会根据控件大小进行伸缩
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/bg"/>
//src是前景,以原图大小显示
<ImageButton
android:layout_width="100dp"
android:layout_height="100dp"
android:background="@drawable/ic_launcher_background"
android:src="@drawable/ic_launcher_foreground"/>
6.ProgressBar
ProgressBar的属性
| Key | Info |
|---|---|
| indeterminate | 不确定模式,动画无限循环 |
| indeterminateDrawable | 设置不确定模式是否可drawable |
| max | 进度的最大值 |
| maxHeight | 进度Widget最大高 |
| maxWidth | 进度Widget最大宽 |
| minHeight | 进度Widget最小高 |
| minWidth | 进度Widget最小宽 |
| progress | 进度默认值,0~max |
| progressBackgroundTint | 背景颜色 |
| secondaryProgress | 定义二级进度值,0~max |
ProgressBar的方法
| Function | Info |
|---|---|
| getMax() | 返回最大值 |
| getProgress() | 返回进度 |
| getSecondaryProgressBy() | 返回次要进度 |
| incrementProgressBy() | 指定增长的进度,正数增加,负数减少 |
| isIndeterminate() | 是否为不确定模式 |
| setLndeterminate() | 设置为不确定模式 |
系统提供的样式
| style=“@andorid:style/*” | Info |
|---|---|
| Widget.progressBar.Horizontal | 水平进度条 |
| Widget.progressBar.Inverse | 普通环形(默认) |
| Widget.progressBar.Large | 大环形 |
| Widget.progressBar.Small | 小环形 |
自定义进度条比较复杂,不展开
另外,对话框形式的进度条ProgressDialog已被弃用,不建议使用。
常见对话框
1.AlertDialog
AlertDialog.Builder dialog = new AlertDialog.Builder(this)
.setTitle("密码错误")
.setIcon(R.drawable.ic_launcher_background)
.setPositiveButton("确定",null)
.setNegativeButton("取消",null)
.setMessage("123");
dialog.show();
2.单选(AlertDialog)
new AlertDialog.Builder(this)
.setTitle("选择性别")
.setSingleChoiceItems(new String[]{"男", "女"}, 0,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
}
})
.setPositiveButton("确定",null)
.show();
setSingleChoiceItems()方法需要设置三个参数:
- 建立数组,用于显示选项内容
- 参数是否默认选中:0表示选中第一个,-1表示默认不选中
- 设立监听,允许对话框被点击
3.多选(AlertDialog)
//lambda表达式
new AlertDialog.Builder(this)
.setTitle("选择性别")
.setMultiChoiceItems(new String[]{"a", "b", "c", "d", "e", "f"},
new boolean[]{true, true, false, false, true, true},
((dialogInterface, i, b) -> {
}))
.setPositiveButton("确定",null)
.show();
setMultiChoiceItems()方法需要设置三个参数:
String[]建立数组,用于显示选项内容boolean[]建立数组,参数是否默认选中- 设立监听,允许对话框被点击(相比单选多了一个boolean参数)
4.消息对话框(Toast)
//轻量级信息提醒机制
//别忘了在最后的show方法
Toast.makeText(this,"hello",Toast.LENGTH_SHORT).show();
Toast.makeText(this,"hello",Toast.LENGTH_LONG).show();
5.自定义对话框
新建一个my_dialog.xml文件
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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:layout_gravity="center"
android:background="#fff"
android:orientation="vertical">
<TextView
android:id="@+id/tv_title"
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="#08F"
android:gravity="center"
android:text="自定义对话框"
android:textColor="#fff"
android:textSize="18sp"
android:visibility="visible"/>
<LinearLayout
android:id="@+id/ll_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center">
<TextView
android:id="@+id/tv_msg"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:minHeight="100dp"
android:paddingTop="15dp"
android:paddingRight="20dp"
android:paddingBottom="15dp"
android:paddingLeft="20dp"
android:textColor="#4e5052"
android:textSize="16sp"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_gravity="bottom"
android:background="#EEE"
android:gravity="center"
android:orientation="horizontal">
<Button
android:id="@+id/btn_ok"
android:layout_width="114dp"
android:layout_height="40dp"
android:layout_marginLeft="20dp"
android:background="#6200ee"
android:gravity="center"
android:text="确定"
android:textColor="#FFF"
android:textSize="15sp"/>
<Button
android:id="@+id/btn_cancel"
android:layout_width="114dp"
android:layout_height="40dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:background="#d0d0d0"
android:gravity="center"
android:text="取消"
android:textColor="#666"
android:textSize="15sp"/>
</LinearLayout>
</LinearLayout>
</FrameLayout>
PS:按钮的颜色改不了,就在values/themes.xml中修改
<style name="Theme.Textbook_test01" parent="Theme.MaterialComponents.DayNight.DarkActionBar.Bridge">
新建MyDialog.java文件,继承Dialog类
public class MyDialog extends Dialog {
private String dialogMessage;
private TextView tvMsg;
private Button btnOK;
private Button btnCancel;
//构造方法
public MyDialog(Context context,String dialogMessage){
super(context);
this.dialogMessage = dialogMessage;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//去除标题
requestWindowFeature(Window.FEATURE_NO_TITLE);
//引入自定义对话框布局
setContentView(R.layout.my_dialog);
tvMsg=findViewById(R.id.tv_msg);
btnOK=findViewById(R.id.btn_ok);
btnCancel=findViewById(R.id.btn_cancel);
//设置自定义对话框显示内容
tvMsg.setText(dialogMessage);
btnOK.setOnClickListener(view -> {
//TODO 确认后的操作
});
btnCancel.setOnClickListener(view -> {
dismiss();//关闭当前对话框
});
}
}
在MainActivity.java中创建对象
new MyDialog(this,"我是自定义的Dialog").show();
样式和主题
当style和theme的属性发生冲突时,style的优先级要高于theme
1.样式(styles.xml)
安卓中的样式类似与网页中CSS样式,可以让设计与内容分离。
在res/values下新建styles.xml。
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="textStyle_one">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textColor">#999</item>
<item name="android:textSize">35sp</item>
</style>
<style name="textStyle_two" parent="@style/textStyle_one">
<item name="android:textSize">25sp</item>
</style>
</resources>
其中name属性是样式名称,parent属性表示继承某个样式
通过标签定义样式。
在布局文件中引用样式:
<TextView
android:id="@+id/tv1"
style="@style/textStyle_one"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="test样式1"
tools:ignore="MissingConstraints" />
<TextView
style="@style/textStyle_two"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="test样式2"
app:layout_constraintTop_toBottomOf="@+id/tv1"
tools:ignore="MissingConstraints" />
2.主题(themes.xml)
主题是应用到整个Activity和Application的样式,要在AndroidManifest.xml文件中引用。
<!-- themes.xml 自定义的主题 -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="colorPrimary">@color/purple_500</item>
<item name="colorPrimaryDark">@color/purple_200</item>
<item name="colorAccent">@color/purple_700</item>
</style>
<style name="grayTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="android:background">#999</item>
</style>
在AndroidManifest.xml中应用主题
<!-- AndroidManifest.xml -->
<activity
android:name=".SelectTraActivity"
android:theme="@style/grayTheme"
android:exported="false" />
注意,在定义主题时,需用到parent属性去继承"Theme.AppCompat.Light.DarkActionBar"来保证兼容性。
注意,在java代码中也可以引用主题,需在onCreate()方法内添加.setTheme(R.style.grayTheme)方法,该方法通常放在setContentView()方法之后。
国际化(I18N)
让不同国家的人看到不同的效果,就需要用到这个功能。
右键 res文件夹 —> New —> Values resource file —>
文件名 string.xml ,Directory name和type 为values —>
选Locale —> 选国家—>选语言—>确定
在对应的文件下修改对应的资源,就能实现不同语言下看到不同的效果
程序调试
androidTest是整合测试。可以打包为apk运行在设备上,可以实时查看细节。
test是单元测试类。运行在本地开发机上,速度快。
单元测试(test 模块)
要测试的方法直接写在test模块的类里,要加上@Test
public class ExampleUnitTest {
@Test
public void addition_isCorrect() {
assertEquals(4, 2 + 2);
}
@Test
public void test() throws Exception{
final int expected =2;
final int reality =2;
//断言,expected期望的参数值与reality相同
assertEquals(expected,reality);
}
}
LogCat
Logcat在编辑器的最下面一栏的中间。可以通过限定精确查找。
| 静态方法 | 级别 | Translate |
|---|---|---|
| Log.v() | Vebose | 详细信息(低) |
| Log.d() | Debug | 调试信息 |
| Log.i() | Info | 一般信息 |
| Log.w() | Warning | 警告信息 |
| Log.e() | Error | 错误信息 |
| 无 | Assert | 断言(高) |
Debug
打断点:单击代码右侧
| 功能 | 快捷键 | |
|---|---|---|
| Step Over | 执行下一句 | F8 |
| Step Info | 当见到方法,进入此方法 | F7 |
| Force Step Info | 用于研究源码 | |
| Step Out | 跳出改方法 | |
| Resume Program | 执行下一个断点 | F9 |
| Stop app | 停止调试 | |
| View Breakpoints | 查看所有断点 |
二、Activity
生命周期
| 方法 | 状态 | Info |
|---|---|---|
| onCreate() | 页面创建时 | |
| onStart() | 启动状态 | 页面可见时 |
| onResume() | 运行状态 | 可获取焦点,与用户交互时 |
| onPause() | 暂停状态 | 被其他页面覆盖或锁屏时 |
| onStop() | 停止状态 | 页面不可见时 |
| onDestroy() | 销毁状态 | 页面销毁时 |
| onRestart() | 从停止状态重新启动时 |
四种启动模式
在Mainifest.xml中通过activity标签的launchMode属性可以设置启动模式。
- standard模式:【不会检测
Activity是否重复】 - singleTop模式:【相同
Activity且同时位于堆栈顶端(top)时才会重复处理】 - singleTask模式:【一个堆栈仅可以有可以实例的task,顶出其他
Activity】 - singlesrance模式:【一个系统仅仅一个这样的
Activity】
页面跳转
-
显式跳转
Intent intent =new Intent(); intent.setClass(this,目标页面.class); startActivity(intent); //简化 startActivity(new Intent(this,目标页面.class)); -
隐式跳转
通过指定的action和category寻找目标Activity,使用隐式intent还可以启动其他app中的Activity。
Intent intent = new Intent(); intent.setAction("action"); startActivity(intent); //简化 startActivity(new Intent("action"));
案例(打开浏览器)
//MainActivity.xml
//在按钮的点击事件中
Intent intent = new Intent();
//这是安卓系统内置的Action,通过这个Action可以和浏览器进行匹配
intent.setAction("android.intent.action.VIEW");
//设置要打开的网址
//Uri.parse()方法把 网址字符串 解析成 Uri对象 ,传入setData()方法。
intent.setData(Uri.parse("http://www.baidu.com"));
startActivity(intent);
数据传递
//页面1.xml
Intent intent = new Intent();
intent.setClass(LoginActivity.this,SelectTraActivity.class);
intent.putExtra("n1","我是要传递的数据");
intent.putExtra("n2",123);
startActivity(intent);
//页面2.xml
String n1 = getIntent().getStringExtra("n1");
String n2 = getIntent().getIntExtra("n2");
数据回传
目前 startActivityForResult() 已被弃用,替代方案为 Activity Result API 组件,这里不展开。
startActivityForResult(Intent intent,int requestCode);
该方法也用于启动Activity,并且能在页面销毁时返回数据。
实际应用:微信发朋友圈时,进入图库选好照片后,会返回到发表状态页面并带回所选的图片信息。
//页面1.xml
Intent intent = new Intent(this,Activity02.class);
startActivityForResult(intent,1);
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == 1){
if (resultCode ==1){
String str = data.getStringExtra("name");
}
}
}
//页面2.xml
Intent intent = new Intent();
intent.putExtra("name","abcdefg");
setResult(1,intent);


&spm=1001.2101.3001.5002&articleId=127018047&d=1&t=3&u=839fa01758434102a8a3e745241256e0)
3565

被折叠的 条评论
为什么被折叠?



