Android安卓开发笔记
1,简介
安卓版本
安卓技术架构
2,环境搭建
-
官网下载androidStudio,https://developer.android.google.cn/studio
-
下载完成之后直接安装并下载相应的SDK
3,hello word
-
创建一个新项目
-
选中空模板
-
填写app信息
-
创建一个穿戴展示设备,Android8.0
-
选择手机型号
-
选择系统镜像
-
下载相关证书(证书下载失败的多试几次)
-
选中镜像
-
横竖屏选择
-
这时候就创建好了一个演示虚拟机
-
直接启动我们的helloword程序
-
运行后会启动程序并生成应用在虚拟机桌面上
4,Android应用项目的开发过程
开发流程图
应用的xml文件相当于我们web开发的html、jsp等等,作为视图层的使用,而Java就作为我们web的controller,作为控制层,是整个应用的核心
新建一个app项目 (MainActivity)
主启动类解读
启动类:MainActivity.java
package com.hai.mainactivity;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//程序启动时通过R.Layout这个资源类调用相应的视图
setContentView(R.layout.activity_main);
}
}
源视图层:activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<!--命名空间引入-->
<!--android:layout_width="match_parent"
android:layout_height="match_parent"
设置宽高,match_parent代表继承父元素的宽高-->
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<!--
文字位置
android:layout_width="340dp"
android:layout_height="142dp"
文字内容
android:text="Hello World!"
文字颜色
android:textColor="@color/black"
文字大小
android:textSize="50sp"
//四面边距
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
-->
<TextView
android:layout_width="340dp"
android:layout_height="142dp"
android:text="Hello World!"
android:textColor="@color/black"
android:textSize="50sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
我们可以通过代码来写视图页面,也可以通过可视化布局直接添加
添加后会生成相应的代码
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_cons<?xml version="1.0" encoding="utf-8"?>
<!--命名空间引入-->
<!--android:layout_width="match_parent"
android:layout_height="match_parent"
设置宽高,match_parent代表继承父元素的宽高-->
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<!--
文字位置
android:layout_width="340dp"
android:layout_height="142dp"
文字内容
android:text="Hello World!"
文字颜色
android:textColor="@color/black"
文字大小
android:textSize="50sp"
//四面边距
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
-->
<TextView
android:layout_width="340dp"
android:layout_height="142dp"
android:text="Hello World!"
android:textColor="@color/black"
android:textSize="50sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<!--这是添加按钮后生成的代码-->
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="发送"
tools:layout_editor_absoluteX="273dp"
tools:layout_editor_absoluteY="378dp"
tools:ignore="MissingConstraints" />
</androidx.constraintlayout.widget.ConstraintLayout>traintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
我们的这些展示的文本消息可以提取到value这个包下的string.xml
这种方式就相当于定义了变量给多处使用
接下来就是调用我们定义的变量(直接通过@类型/变量名调用)
然后展示一下效果
真是丑得一麻批,发送键没有作用,我们实现定义
按钮事件触发
在发送键上做一个事件绑定
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/btn_name"
tools:layout_editor_absoluteX="273dp"
tools:layout_editor_absoluteY="378dp"
tools:ignore="MissingConstraints"
//onClick做为点击时地处理函数,value则是它的方法名,方法定义在处理类里面
android:onClick="sendMsg"/>
函数
/*
需要一个view视图参数
*/
public void sendMsg(View view){
//相应按钮的事件
//通过findViewById这个方法传参找到对应的控件,R是一个资源类,id代表通过id查找,phone是我们在是视图层定义的控件id名字
EditText editTex = findViewById(R.id.phone);
//获得这个输入框中的值
Editable text = editTex.getText();
//转换为字符串
String msg = text.toString();
//打印到控制台
System.err.println(msg);
}
运行测试
控制台讲我们输入的值打印了出来,但是文字太多,我们不易发现,应该使用其他的打印方式
日志查看的分级显示
//info信息显示
Log.i("tag","itag");
//debug信息显示
Log.d("tag","dtag");
//error信息显示
Log.e("tag","etag");
//警告信息显示
Log.w("tag","wtag");
展示
5,项目文档结构
编辑
6,Intent显示调用
在当前项目下新建一个activity
名字及视图名填写
修改第一个AndroidManifest.xml文件
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.hai.mainactivity">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.MainActivity">
<activity android:name=".SecondActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
在第二个activity的视图文件展示文字
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".SecondActivity">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="535dp"
android:text="@string/intent"
app:layout_constraintBottom_toBottomOf="parent"
tools:layout_editor_absoluteX="137dp"
tools:ignore="MissingConstraints" />
</androidx.constraintlayout.widget.ConstraintLayout>
实现两个视图之间的跳转(跳转的方式有三种,这里就不过多阐述)
//this代表当前的activity,然后是目标的activity的class对象
Intent intent = new Intent(this,SecondActivity.class);
Intent [] it = {intent};
//需要的参数是一个数组,将intent对象封装为数组
//开始跳转
this.startActivities(it);
测试跳转
7,Intent隐式调用
在前面的显示调用中,我们的第二个activity在桌面创建了应用,这显然是不合理的,我们通过隐式调用来解决
修改AndroidManifest.xml文件(将LAUNCHER修改为DEFAULT)
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.hai.mainactivity">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.MainActivity">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".SecondActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</application>
</manifest>
这样在多个activity的情况下就不会出现创建桌面应用图标的问题,在隐式调用中,我们可以通过AndroidManifest文件中的action的name进行调用
<activity android:name=".SecondActivity">
<intent-filter>
<action android:name="action.twoActivity" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
调用代码
Intent intent = new Intent();
intent.setAction("action.twoActivity");
Intent [] it = {intent};
this.startActivities(it);
测试
8,activity的生命周期
测试代码
package com.hai.mainactivity;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.inputmethodservice.ExtractEditText;
import android.os.Bundle;
import android.text.Editable;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//info信息显示
/*Log.i("tag","itag");
//debug信息显示
Log.d("tag","dtag");
//error信息显示
Log.e("tag","etag");
//警告信息显示
Log.w("tag","wtag");*/
Log.e("life","onCreate");
}
@Override
protected void onStart() {
super.onStart();
Log.e("life","onStart");
}
@Override
protected void onRestart() {
super.onRestart();
Log.e("life","onRestart");
}
@Override
protected void onPause() {
super.onPause();
Log.e("life","onPause");
}
@Override
protected void onResume() {
super.onResume();
Log.e("life","onResume");
}
@Override
protected void onStop() {
super.onStop();
Log.e("life","onStop");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.e("life","onDestroy");
}
/*
需要一个view视图参数
*/
public void sendMsg(View view){
//相应按钮的事件
//通过findViewById这个方法传参找到对应的控件,R是一个资源类,id代表通过id查找,phone是我们在是视图层定义的控件id名字
EditText editTex = findViewById(R.id.phone);
//获得这个输入框中的值
Editable text = editTex.getText();
//转换为字符串
String msg = text.toString();
//打印到控制台
System.err.println(msg);
/* Intent intent = new Intent(this,SecondActivity.class);
Intent [] it = {intent};
this.startActivities(it);*/
Intent intent = new Intent();
intent.setAction("action.twoActivity");
Intent [] it = {intent};
this.startActivities(it);
}
}
测试
可以看到,程序首次启动时,执行了oncreate,onstart,onresume三个方法,
当程序被挂到后台时,执行了onpause,onstop方法,重新切回程序时执行,restart,onstart,onresume函数
程序被清理掉时执行ondestory方法
生命周期执行顺序
多个activity时的执行顺序
9,APP页面布局
有前端web开发经验可直接跳过
页面布局就是页面设置,怎样摆放控件能更好看
相对布局relativeLayout
+++
测试代码:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="相对布局"
android:textSize="50sp"
/>
<!--
相对于目标控件控件,使用此元素将处于目标控件的下方
android:layout_below="@id/textView"
-->
<EditText
android:id="@+id/et1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/textView"
/>
<!--
代表是否贴近父元素的最右侧
android:layout_alignParentRight="true"
-->
<Button
android:id="@+id/login"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="登录"
android:layout_below="@id/et1"
android:layout_alignParentRight="true"
/>
<!--
贴近已知控件的左侧
android:layout_toLeftOf="@id/login"
-->
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="退出"
android:layout_below="@id/et1"
android:layout_toLeftOf="@id/login"
android:layout_marginRight="10sp"
/>
</RelativeLayout>
测试展示
线性布局LinearLayout
+++
测试代码:
<?xml version="1.0" encoding="utf-8"?>
<!--
android:orientation="vertical
代表垂直布局
android:gravity="center"
代表当前布局内的元素剧中显示,多个值用|分开
android:layout_gravity="center"
代表当前布局居中显示
线性布局可嵌套使用
android:layout_weight="1"
代表为此控件添加权重
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
android:layout_gravity="center"
>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="按钮1"
android:layout_weight="1"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="按钮2"
android:layout_weight="2"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="按钮3"
/>
<!--
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
android:layout_gravity="center"
>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="按钮4"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="按钮5"
/>
</LinearLayout>-->
</LinearLayout>
测试效果:
表格布局TableLayout
+++
测试代码:
<?xml version="1.0" encoding="utf-8"?>
<!--
android:shrinkColumns="1"
代表这个按钮是可压缩的,屏幕不能全部显示时,会压缩大小
android:stretchColumns="1"
代表这个按钮你是可拉伸的,会填满一整行
android:collapseColumns="2"
代表这个元素会被隐藏
-->
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:shrinkColumns="1"
android:stretchColumns="1"
android:collapseColumns="3">
<Button
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="按钮1"
/>
<TableRow>
<Button
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="按钮1"
/>
<Button
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="按钮1"
/>
<Button
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="按钮1"
/>
<Button
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="按钮1"
/>
<Button
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="按钮1"
/>
</TableRow>
</TableLayout>
展示效果
网格布局GridLayout
+++
网格布局就是将整个页面进行划分,然后确定控件摆在那行哪列
测试代码:
<?xml version="1.0" encoding="utf-8"?>
<!--
android:rowCount="6"
android:columnCount="4"
将整个页面划分为6行4列的五子棋棋盘
-->
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:columnCount="4"
android:rowCount="6"
android:layout_gravity="center">
<!--
android:layout_columnSpan="4"
代表此控件占用4列
-->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_columnSpan="4"
android:text="0"
android:textSize="50sp" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="清除"
android:layout_columnSpan="4"
/>
<Button android:text="1" android:textSize="26sp"/>
<Button android:text="2" android:textSize="26sp"/>
<Button android:text="3" android:textSize="26sp"/>
<Button android:text="+" android:textSize="26sp"/>
<Button android:text="4" android:textSize="26sp"/>
<Button android:text="5" android:textSize="26sp"/>
<Button android:text="6" android:textSize="26sp"/>
<Button android:text="-" android:textSize="26sp"/>
<Button android:text="7" android:textSize="26sp"/>
<Button android:text="8" android:textSize="26sp"/>
<Button android:text="9" android:textSize="26sp"/>
<Button android:text="*" android:textSize="26sp"/>
<Button android:text="." android:textSize="26sp"/>
<Button android:text="0" android:textSize="26sp"/>
<Button android:text="=" android:textSize="26sp"/>
<Button android:text="/" android:textSize="26sp"/>
</GridLayout>
效果展示
帧布局FrameLayout
+++
最简单的布局,所有元素叠加在一起
测试代码:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".FrameLayout">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:layout_editor_absoluteX="145dp"
tools:layout_editor_absoluteY="253dp">
<TextView
android:layout_width="200sp"
android:layout_height="200sp"
android:background="#f0f"
/>
<TextView
android:layout_width="100sp"
android:layout_height="100sp"
android:background="#f00"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="next"
android:layout_gravity="right"
/>
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
测试:
控件提取
我们有很多控件需要重复使用,但是我们肯定不会重复写它,我们可以将它象变量一样提取出来直接包含使用
在layout目录下新建一个layout文件
将控件提取到我们新建的这个文件中
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="清除"
/>
</LinearLayout>
通过include引用
<include layout="@layout/layout_text"></include>
展示
10,主题及样式
主题是整个activity共享的
样式可能是作用于某一个控件
colors文件定义了颜色,styles直接引用这个颜色
colors.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="purple_200">#FFBB86FC</color>
<color name="purple_500">#6699FF</color>
<color name="purple_700">#003399</color>
<color name="teal_200">#FF03DAC5</color>
<color name="teal_700">#FF018786</color>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
</resources>
styles.xml
<resources>
<style name="AppCompat" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="colorPrimary">@color/purple_700</item>
<item name="colorPrimaryDark">@color/purple_500</item>
<item name="colorAccent">@color/purple_200</item>
</style>
</resources>
实现
可以通过AndroidManifest文件实现对主题的切换
在styles中定义样式
<style name="myFont" parent="TextAppearance.AppCompat.Medium">
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_width">wrap_content</item>
<item name="android:textSize">50sp</item>
<item name="android:textColor">#F00</item>
</style>
在视图层中调用
<TextView
style="@style/myFont"
android:text="nihao"/>
测试
11,屏幕适配
不同的设备屏幕的大小和分辨率不一样,我们要怎样做到在不同设备上正常运行我们的程序呢?
我们可以在AndroidManifest.xml文件中声明
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.hai.layouts">
<!--
android:smallScreens="false"
不能再小屏幕上正常显示,如果要显示会已兼容模式运行
android:compatibleWidthLimitDp="320"
如果设备的最小宽度小于320,就不能正常显示,已兼容模式运行
android:largestWidthLimitDp="1080"
屏幕分辨率大于1080就采用兼容模式显示
-->
<supports-screens
android:smallScreens="false"
android:compatibleWidthLimitDp="320"
android:largestWidthLimitDp="1080"
>
</supports-screens>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppCompat">
<activity android:name=".GridLayout" />
<activity android:name=".TableLayout" />
<activity android:name=".RelativeLayout" />
<activity android:name=".FrameLayout" />
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
应用名及应用图标更换
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
//应用名
android:label="@string/app_name"
//应用图标
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppCompat">
<activity android:name=".GridLayout" />
<activity android:name=".TableLayout" />
<activity android:name=".RelativeLayout" />
<activity android:name=".FrameLayout" />
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
12,Fragment
1,Fragment介绍
Fragment就是一个占位符,通过Java去控制这个占位标签的显示内容
再展示页创建一个fragment
<?xml version="1.0" encoding="utf-8"?>
<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"
tools:context=".MainActivity">
<fragment
android:id="@+id/txt1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
将我们要展示的内容提取为一个layout资源
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
/>
</LinearLayout>
编写一个类继承fragment类并重写onCreateView方法
package com.hai.fragmentdemo;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
public class FragmentTextView extends Fragment {
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
//这个方法的参数是,资源,容器,和是否跟主界面进行同步
return inflater.inflate(R.layout.fragment_textview,container,false);
}
}
再展示页的占位符fragment中,通过name属性全限定类名进行绑定
<?xml version="1.0" encoding="utf-8"?>
<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"
tools:context=".MainActivity">
<fragment
android:id="@+id/fragment_text"
android:name="com.hai.fragmentdemo.FragmentTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
启动测试
Fragment的特点:
他必须放在activity中使用,不能独立存在,具有自己的生命周期,同时声明周期页直接受所在的activity生命周期影响
一个activity中可以包含多个Fragment,每个Fragment都定义自己的布局,并在生命周期中的回调方法中定义的动作
fragment之间是相互独立的
代码复用,适用于模块化开发,一个Fragment可以被多个Activity嵌套,有个共同的业务模块就可以复用了
2,Fragment生命周期
Fragment的回调函数
Activity和Fragment生命周期的影响
代码:
package com.hai.fragmentdemo;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
public class FragmentImage extends Fragment {
//当Fragment被加载时调用
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
}
//当Fragment被初始化时调用
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
//当Fragment加载界面时调用
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_image, container, false);
}
//当Activity完成所有的Fragment加载时调用
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
}
3,Fragment动态添加
为什么说是动态添加呢,在前面介绍Fragment时我们演示过了Fragment的添加,只不过那是静态添加,那两者有何区别,区别仅仅在于,静态的直接通过name属性的全限定类名进行了绑定,动态的则通过代码控制
创建好fragment占位和相关的资源后,在启动类中用代码绑定
package com.hai.fragmentdemo;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.FragmentManager;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentManager manager = getSupportFragmentManager();
manager.beginTransaction().add(R.id.fragment_list,new FragmentImage()).commitNow();
}
}
注意,占位符不能是Fragment且必须提交
4,动态Fragment的移除
可以动态添加的同时,也能动态删除,
多个图片滚动布局使用HorizontalScrollView布局
上代码:
package com.hai.fragmentdemo;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import android.os.Bundle;
import android.util.DisplayMetrics;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//获得手机屏幕的宽高
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
//高度
int heightPixels = displayMetrics.heightPixels;
//宽度
int widthPixels = displayMetrics.widthPixels;
//横屏
FragmentManager manager = getSupportFragmentManager();
Fragment fragment = manager.findFragmentById(R.id.fragment_list);
if (widthPixels > heightPixels) {
if (fragment != null) {
//横屏时删除fragment
manager.beginTransaction().remove(fragment).commitNow();
}
} else {
//竖屏
if (fragment == null)
//竖屏时添加
manager.beginTransaction().add(R.id.fragment_list, new FragmentImage()).commitNow();
}
}
}
演示:
竖屏
横屏
5,事件处理
事件处理主要有两种,一种是前面说过的onClick点击与函数名绑定,这里主要说另一种,
用接口的方式处理函数,说白了就是为被点击的控件绑定一个函数
创建一个activity在展示页面添加文本和一个点击按钮
<?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:orientation="vertical">
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="这是一段话"
android:textSize="30sp"
android:layout_margin="100sp"
android:layout_gravity="center"
/>
<Button
android:id="@+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="点击我"
android:layout_gravity="center"
/>
</LinearLayout>
在主函数中为这个按钮绑定一个事件
package com.hai.fragmentdemo;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class EventActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_event);
//找到按钮
Button button=findViewById(R.id.btn);
//添加事件
button.setOnClickListener(v -> {
//找到文本
TextView textView = findViewById(R.id.text);
//设置新标题
this.setTitle("这是一个新标题");
//设置新的文本内容
textView.setText("点我干嘛");
});
}
}
启动测试
点击后
常用事件
13,常用基本控件
TextView
展示代码:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/text"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Java控制代码
package com.hai.controdemo;
import androidx.appcompat.app.AppCompatActivity;
import android.graphics.Color;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView textView = findViewById(R.id.text1);
textView.setTextColor(Color.BLUE);
textView.setTextSize(30);
}
}
效果
Button
代码:
<?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">
<!-- <TextView
android:id="@+id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/text"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />-->
<!--普通按钮-->
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="start" />
<!--图片按钮-->
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="40sp"
android:src="@drawable/ic_launcher_foreground" />
<!--图片加文字按钮-->
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/ic_launcher_foreground"
android:text="stop" />
<!--点击时按钮文字变化按钮-->
<ToggleButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textOff="stop"
android:textOn="start" />
<!--开关按钮-->
<Switch
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textOff="关"
android:textOn="开" />
<!--单选框-->
<RadioGroup
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="男"
/>
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="女"
/>
</RadioGroup>
</LinearLayout>
展示:
20,Action和Data启动系统程序
Action
Data
通过Action和Data实现启动手机通讯录,打开一个网页
定义三个按钮
<?xml version="1.0" encoding="utf-8"?>
<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:orientation="vertical"
>
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="打开百度"
tools:ignore="MissingConstraints"
android:onClick="execute"
/>
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="打开通讯录"
tools:ignore="MissingConstraints"
android:onClick="execute"
/>
<Button
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="获取第一个联系人"
tools:ignore="MissingConstraints"
android:onClick="execute"
/>
</LinearLayout>
触发的Java函数
public void execute(View view){
//打开百度
if (view.getId()==R.id.button1) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("http://www.muzicy.xyz"));
startActivity(intent);
}
//打开通讯录。
if (view.getId()==R.id.button2) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("content://com.android.contacts/contacts"));
startActivity(intent);
}
//打开第一个联系人
if (view.getId()==R.id.button3) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("content://com.android.contacts/contacts/1"));
startActivity(intent);
}
}
测试
其他相关调用请参考此博客 Intent调用
Category参数博客参考 category调用
21,Intent实现数据传递
实现数据传递要使用Bundle这个类,存放一个HashMap在多个Activity共享这个数据
-
创建两个Activity
-
在第一个Activity的Main入口函数添加本Activity获得的值
public void go(View view){ //获取文本框数据 TextView text1 = findViewById(R.id.text1); TextView text2 = findViewById(R.id.text2); //创建意图 Intent intent = new Intent(); ComponentName componentName = new ComponentName(this, SecondActivity.class); intent.setComponent(componentName); //添加数据到Bundle进行传递 Bundle bundle = new Bundle(); bundle.putString("text1",text1.getText().toString()); bundle.putString("text2",text2.getText().toString()); intent.putExtras(bundle); startActivity(intent); }
-
在第二个Activity获取数据
@SuppressLint("SetTextI18n") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_second); TextView textView = findViewById(R.id.textview); textView.setText(this.getIntent().getExtras().getString("text1")+"和"+this.getIntent().getExtras().getString("text2")); }
-
测试
获得数据
22,Broadcast广播
静态注册广播
定义一个Receiver接收器,接收器的onReceiver方法就是接收到广播后要做出的动作
package com.hai.broadcastdemo;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class Receiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.e(intent.getAction(),intent.getStringExtra("msg"));
}
}
在配置文件中配置广播
<receiver android:name=".Receiver">
<intent-filter>
<action android:name="com.hai.BROADCAST"/>
</intent-filter>
</receiver>
Main函数开始发送广播
package com.hai.broadcastdemo;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = findViewById(R.id.btn);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.hai.broadcastdemo","com.hai.broadcastdemo.Receiver"));
intent.setAction("com.hai.BROADCAST");
intent.putExtra("msg","这是一条广播");
sendBroadcast(intent);
}
});
}
}
测试
动态注册广播
动态和静态有何区别,不需要再配置文件中配置,可注册可取消,更灵活方便
定义接收器
package com.hai.registerreceiver;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.e(intent.getAction(),intent.getStringExtra("msg"));
}
}
开启接收器
package com.hai.registerreceiver;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//发送广播
Button button1 = findViewById(R.id.btn1);
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction("start");
intent.putExtra("msg","发送了广播");
sendBroadcast(intent);
}
});
//注册
MyReceiver receiver = new MyReceiver();
Button button2 = findViewById(R.id.btn2);
button2.setOnClickListener(v -> {
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("start");
registerReceiver(receiver,intentFilter);
});
//取消注册
Button button3 = findViewById(R.id.btn3);
button3.setOnClickListener(v->{
unregisterReceiver(receiver);
});
}
}
测试
常见的系统广播
23,Notification通知管理
什么是通知,就是女朋友发的消息你没回,堆在顶部状态栏的消息提示就叫通知,明白了吗憨憨
定义一个发送通知按钮
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="发送通知!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:onClick="sendNotification"/>
</androidx.constraintlayout.widget.ConstraintLayout>
定义一个通知目标activity
<?xml version="1.0" encoding="utf-8"?>
<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"
tools:context=".NotificationTwo"
android:layout_margin="130sp"
android:orientation="vertical"
>
<ImageView
android:layout_width="120sp"
android:layout_height="120sp"
android:src="@drawable/notification"
tools:ignore="MissingConstraints" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30sp"
android:text="我是彭于晏\n真的是"
tools:ignore="MissingConstraints" />
</LinearLayout>
代码实现
public void sendNotification(View view){
//1.创建一个通知管理器
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
//2.建立一个通知Android8.0后需要构建通道
//创建管道
String id = "mChannel";
Notification notification = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationChannel notificationChannel = new NotificationChannel(id,"通道1",NotificationManager.IMPORTANCE_MIN);
notificationManager.createNotificationChannel(notificationChannel);
//构建通知
notification = new Notification.Builder(this,id)
//通知大图
.setLargeIcon(BitmapFactory.decodeResource(this.getResources(),R.drawable.notification))
//通知小图
.setSmallIcon(R.drawable.ic_baseline_assignment_24)
//通知标题
.setContentTitle("猛料来袭")
//通知内容
.setContentText("贵州彭于晏")
//通知时间
.setWhen(System.currentTimeMillis())
//点击后关闭通知
.setAutoCancel(true)
//3.绑定对应的Activity
.setContentIntent(PendingIntent.getActivity(this,1,new Intent(this,NotificationTwo.class),PendingIntent.FLAG_CANCEL_CURRENT))
//完成构建
.build();
}else {
//Android8.0之前的通知
}
//4.发送通知
notificationManager.notify(0,notification);
}
测试