阅读本文需要有Java和前端的基础,本文是我学习Android时的笔记。
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 |
一些重要属性
//控制子控件的排列方向
orientation="vertical" //垂直
orientation="horizontal" //水平
//设置权重(权重总和为分母,可用于屏幕按钮的适配)
layout_weight="1"
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 |
该布局为每个加入其中的控件创建一个空白区域(称为一帧,每个控件占据一帧),所以控件默认显示在左上角,先放的在最底层。
Key | Info |
---|---|
foreground | 设置容器 的前景图 |
foregroundGravity | 设置前景图显示位置 |
需要和TableRow
标签配合使用,TableRow
的数量决定表格的行数。
布局属性 | Info |
---|---|
stretchColumns | 设置列可 拉伸 |
shrinkColumns | 设置列可 收缩 |
collapseColumns | 设置列可 隐藏 |
控件属性 | Info |
---|---|
layout_column | 在控件少于单元格的情况下,指定显示的位置 |
layout_span | 默认为1,可指定控件占几个单元格 |
//布局属性
layout_x = "50dp";
layout_y = "100dp";
控件属性 | Info |
---|---|
text | |
textColor | |
textSize | sp |
textStyle | bold,italic |
gravity | 文本位置 |
layout_width | 控件高 |
layout_height | wrap_content , match_parent |
height | 文本域高( 不常用) |
width | 文本域宽( 不常用) |
maxLength | 文本最大长度 |
phoneNumber | 以电话形式显示 |
password | 以密码形式显示 |
控件属性 | Info |
---|---|
hint | 提示文本 |
lines | 设置固定行高 |
maxLines | 最大行数 |
minLines | 最小行数 |
password | 以密码形式显示 |
phoneNumber | 以电话形式显示 |
scrollHorizontally | 水平滚动条 |
capitalize | 首字母大写 |
editable | 是否可编辑 |
background="@null"属性为去掉控件默认的下划线
点击事件的两种实现方法
<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");
//......
}
}
}
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
}
});
//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"/>
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
已被弃用,不建议使用。
AlertDialog.Builder dialog = new AlertDialog.Builder(this)
.setTitle("密码错误")
.setIcon(R.drawable.ic_launcher_background)
.setPositiveButton("确定",null)
.setNegativeButton("取消",null)
.setMessage("123");
dialog.show();
new AlertDialog.Builder(this)
.setTitle("选择性别")
.setSingleChoiceItems(new String[]{"男", "女"}, 0,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
}
})
.setPositiveButton("确定",null)
.show();
setSingleChoiceItems()方法需要设置三个参数:
//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[]
建立数组,参数是否默认选中//轻量级信息提醒机制
//别忘了在最后的show方法
Toast.makeText(this,"hello",Toast.LENGTH_SHORT).show();
Toast.makeText(this,"hello",Toast.LENGTH_LONG).show();
新建一个my_dialog.xml
文件
<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
安卓中的样式类似与网页中CSS样式,可以让设计与内容分离。
在res/values下新建styles.xml。
<resources>
<style name="textStyle_one">
- "android:layout_width"
>match_parent
- "android:layout_height"
>wrap_content
- "android:textColor">#999
- "android:textSize">35sp
style>
<style name="textStyle_two" parent="@style/textStyle_one">
- "android:textSize"
>25sp
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" />
主题是应用到整个Activity和Application的样式,要在AndroidManifest.xml
文件中引用。
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
- "colorPrimary"
>@color/purple_500
- "colorPrimaryDark"
>@color/purple_200
- "colorAccent">@color/purple_700
style>
<style name="grayTheme" parent="Theme.AppCompat.Light.DarkActionBar">
- "android:background"
>#999
style>
在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()方法之后。
让不同国家的人看到不同的效果,就需要用到这个功能。
右键 res文件夹
—> New —> Values resource file —>
文件名 string.xml
,Directory name和type 为values —>
选Locale —> 选国家—>选语言—>确定
在对应的文件下修改对应的资源,就能实现不同语言下看到不同的效果
androidTest是整合测试。可以打包为apk运行在设备上,可以实时查看细节。
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在编辑器的最下面一栏的中间。可以通过限定精确查找。
静态方法 | 级别 | Translate |
---|---|---|
Log.v() | Vebose | 详细信息(低) |
Log.d() | Debug | 调试信息 |
Log.i() | Info | 一般信息 |
Log.w() | Warning | 警告信息 |
Log.e() | Error | 错误信息 |
无 | Assert | 断言(高) |
打断点:单击代码右侧
功能 | 快捷键 | |
---|---|---|
Step Over | 执行下一句 | F8 |
Step Info | 当见到方法,进入此方法 | F7 |
Force Step Info | 用于研究源码 | |
Step Out | 跳出改方法 | |
Resume Program | 执行下一个断点 | F9 |
Stop app | 停止调试 | |
View Breakpoints | 查看所有断点 |
方法 | 状态 | Info |
---|---|---|
onCreate() | 页面创建时 | |
onStart() | 启动状态 | 页面可见时 |
onResume() | 运行状态 | 可获取焦点,与用户交互时 |
onPause() | 暂停状态 | 被其他页面覆盖或锁屏时 |
onStop() | 停止状态 | 页面不可见时 |
onDestroy() | 销毁状态 | 页面销毁时 |
onRestart() | 从停止状态重新启动时 |
在Mainifest.xml
中通过activity
标签的launchMode
属性可以设置启动模式。
Activity
是否重复】Activity
且同时位于堆栈顶端(top)时才会重复处理】Activity
】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);