封面P站:https://www.pixiv.net/artworks/83342983

注意: 不是零基础

页面布局

一般都在layout文件夹内。

一个布局文件,一般对应一个Activity,在代码中通过

1
setContentView(R.layout.first_layout);

布局的分类

LinearLayout 线性布局

一种使用单个水平行(horizontal)或垂直行(vertical)来组织子项的布局。它会在窗口长度超出屏幕长度时创建一个滚动条

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
<?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">

<!-- 水平布局 -->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="按钮一"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="按钮二"/>
<Button
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">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="按钮三"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="按钮四"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="按钮五"/>
</LinearLayout>

</LinearLayout>

Relative Layout 相对布局

让您能够指定子对象彼此之间的相对位置(子对象 A 在子对象 B 左侧)或子对象与父对象的相对位置(与父对象顶部对齐)。

1
2
3
4
5
6
7
8
9
10
11
android:layout_toLeftOf=""          ——该组件位于引用组件的左方
android:layout_toRightOf="" ——该组件位于引用组件的右方
android:layout_above="" ——该组件位于引用组件的上方
android:layout_below="" ——该组件位于引用组件的下方
android:layout_alignParentLeft="" ——该组件是否对其父组件的左端
android:layout_alignParentRight="" ——该组件是否对其父组件的右端
android:layout_alignParentTop="" ——该组件是否对其父组件的顶部
android:layout_alignParentBottom="" ——该组件是否对其父组件的底部
android:layout_centerInParent="" ——该组件是否相对于父组件居中
android:layout_centerHorizontal="" ——该组件是否横向居中
android:layout_centerVertical="" ——该组件是否垂直居中
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
<?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" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/button1"
android:layout_width="100dp"
android:layout_height="100dp"
android:text="1"
android:layout_alignParentBottom="true"
android:gravity="center"
/>
<Button
android:id="@+id/button2"
android:layout_width="100dp"
android:layout_height="100dp"
android:gravity="center"
android:text="2"
android:layout_above="@+id/button1"
android:layout_toRightOf="@+id/button1"
/>
<Button
android:id="@+id/button3"
android:layout_width="100dp"
android:layout_height="100dp"
android:gravity="center"
android:text="3"
android:layout_above="@+id/button1"
android:layout_toRightOf="@+id/button2"
/>
</RelativeLayout>

</LinearLayout>

FrameLayout 帧布局

帧布局(FrameLayout)直接继承了ViewGroup组件;

帧布局容器为每一个加入其中的组件都创建了一个空白的区域,这个区域我们称之为一帧,所有每个组件都占据一帧,这些都会根据gravity属性执行自动对齐。

常用XML属性及相关的方法:

XML属性相关方法说明
android:foregroundsetForeground(Drawable)设置该帧布局容器的前景图像
android:foregroundGravitysetForegroundGravity(int)定义绘制前景图像的gracity属性

基本控件

字体sp、其他dp

扩展: 设置大小的单位(字体,也包括控件大小)

dp: 设备独立像素,不同设备有不同的显示效果,这个和设备硬件有关,不依赖像素。

px: 像素,在 不同设备显示的效果相同。

pt: 标准的长度单位,简单易用,单位换算1pt=1/72英寸。

sp: 用于字体显示。

TextView

属性

id设置一个组件id,通过findViewById()的方法获取到该对象,然后进行相关设置
layout_width组件宽度 wrap_content: 控件的大小根据里面的内容大小而定,内容越小,则空间越小,反之亦然。 match_parent: 控件大小填满整个父容器
layout_height组件高度
text**设置文本内容 ** 将字符串放置在value文件夹的strings.xml文件下 在activity_main.xml中使用@string/来调用这个字符串资源,”“号代表string定义的name
background背景颜色(或背景图片)
textColor设置字体颜色 将颜色配置在colors.xml文件中 activity_main.xml中,用@color/*进行调用
textStyle设置字体样式
textSize字体大小
gravity内容的对齐方向 center: 居中对齐,位于容器横向和纵向的中央 left: 向左对齐,位于容器左边 right: 向右对齐,位于容器右边 bottom:向底对齐,位于容器底部 top: 向顶对齐,位于容器顶部 center_vertical: 位置置于容器的纵向中央部分 center_horizontal: 位置置于容器的横向中央部分 fill_vertical: 纵向延伸填满容器 fiil_horizontal: 横向延伸填满容器 fiil:纵向和横向延伸填满容器
autoLinkautoLink的属性可以将符合指定格式的文本转换为可单击的超链接形式
drawableTopTextView上部出现一个图片

TextView实现跑马灯的效果

1
2
3
4
5
6
7
8
9
10
11
android:singleLine="true"

android:ellipsize="marquee"

android:marqueeRepeatLimit="marquee_forever"

android:focusable="true"

android:focusableInTouchMode="true" // 不添加这个属性不能成功跑动起来

setSelected(true);

TextView 实现删除线的效果

1
2
3
4
5
textview.getPaint().setFlags(Paint.STRIKE_THRU_TEXT_FLAG ); //中间横线

textview.getPaint().setFlags(Paint.UNDERLINE_TEXT_FLAG);//下划线

textview.getPaint().setAntiAlias(true);// 抗锯齿

TextView 一行,最多显示10个字符,剩余的用…代替:

1
mTitleTxt.setSingleLine();// 单行显示mTitleTxt.setMaxEms(10);// 最大十个字符mTitleTxt.setEllipsize(TextUtils.TruncateAt.END);// 剩余的以...结尾

TextView 展示字母的时候,明明是小写,但界面上看到的都是大写 解决方案

1
2
3
添加属性: 

android:textAllCaps="false"

Button

Java-“this”和”类名.this”以及”类名.class”的区分和详解

组合用法说明
this指代当前对象的引用
类名.class指向每个类对应的唯一类对象(类型为Class)
类名.this内部(可以是匿名内部类)类调用外部类的对象时使用,即在内部类中使用时: 外部类对象是外部类名.this,内部类对象则是this

属性

属性作用
android:text=””设置bottom上显示的文字
android:textSize=””设置bottom上的文字大小
android:textColor=””设置bottom上的文字颜色
android:padding=””设置bottom的内边距
android:weight=””权重
设置边框样式为圆角
设置边框线条粗细及颜色

实现点击后字体颜色改变

这里我们将不同功能用不同的xml文件存放,当编写的代码较多时,这样设置有助于检查和修改代码。

https:////upload-images.jianshu.io/upload_images/18962003-ab2c58dd20ef6d4a.png

activity_main.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
<?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"
android:orientation="vertical">

<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="分享"
android:textColor="@drawable/text_color"
/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="显示的文本"
android:textColor="@drawable/edit_text_color"/>

<Button
android:layout_width="100dp"
android:layout_height="100dp"
android:background="@drawable/shape_rectangle"/>

</LinearLayout>

shape_rectangle.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?xml version="1.0" encoding="utf-8"?>
<!--长方形
corners: 圆角的大小
solid: 填充颜色
stroke: 边框颜色 宽度
gradient:渐变色 UI-拟物化 -扁平化设计
padding: 内间距
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">

<stroke android:color="@color/colorAccent" android:width="1dp" android:dashWidth="2dp"/>
<corners android:radius="10dp"/>
<solid android:color="@color/colorAccent"/>
<gradient android:startColor="#ff0000" android:centerColor="#00ff00" android:endColor="#0000ff" android:gradientRadius="50dp"
android:type="sweep"/>

</shape>

edit_text_color.xml

1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!--高亮状态显示的颜色-->
<item android:color="#0000ff" android:state_focused="true"/>

<!--正常状态显示的颜色-->
<item android:color="#ff0000"/>
</selector>

text_color.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!--注意: 配置有先后顺序
默认的状态放在后面如果放在前面,优先匹配
一旦匹配上了,后面的设置无效-->
<!--按下状态的颜色 pressed-->
<item android:color="#ff0000" android:state_pressed="true"/>

<!--无效 无法点击的颜色 enable-->
<item android:color="#00ff00" android:state_enabled="false"/>

<!--默认状态-->
<item android:color="#000000"/>
</selector>

MainActivity.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.android;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}

按钮点击事件

内部类实现

内部类实现的方法是: 创建一个内部类实现OnClickListener接口并重写onClick()方法,在方法中写入点击事件的逻辑。内部类写完之后需要为按钮设置setOnClickListener(Listener listener)属性,在参数中传入之前创建好的内部类对象即可。使用这种点击事件的好处,当按钮较多时可以在onClick(View v)方法中使用switch语句case属性设置各自不同的点击事件逻辑。

1
2
3
4
5
6
7
8
9
10
11
12
13
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button =(Button)findViewById(R.id.button);
button.setOnClickListener(new MyButton());
}
private class MyButton implements View.OnClickListener{
@Override
public void onClick(View view) {
Toast.makeText(getApplicationContext(),"已点击按钮",Toast.LENGTH_SHORT).show();
}
}

匿名内部类实现

​ 当按钮较少或者只有一个按钮时,就不需要再单独创建一个类实现OnClickListener接口了,可以直接创建OnClickListener的匿名内部类传入按钮的setOnClickListener()参数中。

1
2
3
4
5
6
7
8
9
10
11
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(getApplicationContext(), "已点击按钮", Toast.LENGTH_SHORT).show();
}
});
}
Activity本身实现事件接口

除了以上两种方法,还可以在主类中实现该接口,然后重写onClick()方法,这里需要注意的是,button.setOnCLickListener(this);方法中接收了一个参数this,这个this代表的是该Activity的引用。由于Activity实现了OnClickListener接口,所以这里this代表了OnClickListener的引用,在方法中传入this就代表该控件绑定了点击事件的接口。

1
2
3
4
5
6
7
8
9
10
11
12
13
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(this);
}
@Override
public void onClick(View view) {
Toast.makeText(getApplicationContext(),"已点击按钮",Toast.LENGTH_SHORT).show();
}
}

EditText

属性

hint输入框显示的提示文本
textColorHint输入框显示的提示文本的颜色
inputType限制用户的输入类型
capitalize英文大写设置
minLines最小行数
maxLines最大行数
SingleLine单行不换行

注意

inputType: 限制用户的输入类型

值如下:

text普通字符
textCapCharacters普通字符
none普通字符
textCapSentences字符串中的第一个字母大写
textCapWords字符串中的每个单词的首字母大写
textMultiLine多行输入
textImeMultiLine输入法多行
textUri格式为: URI
textShortMessage格式为: 短消息
textShortMessage格式为: 长消息
textEmailAddress格式为: 电子邮件地址
textEmailSubject格式为: 邮件主题
textPostalAddress格式为: 邮政
textPersonName格式为: 姓名
textPassword格式为: 不可见密码
textVisiblePassword格式为: 可见密码
textFilter格式为: 文本筛选
textWebEditText格式为: 作为网页表单的文本
number格式为: 数字
numberSigned格式为: 有符号数字
numberDecimal格式为: 浮点数
textPhonetic格式为: 拼音输入
phone键盘为: 拨号
date或者datetime键盘为: 日期
time键盘为: 时间
textAutoCorrect前两个自动完成
textAutoComplete前两个自动完成
textNoSuggestions不进行提示

capitalize:英文大写设置

sentences字符串的第一个字母大写
words字符串中用空格区分单词,每个单词的首字母大写
characters字符串中每一个英文字母都大写

RadioButton和RadioGroup

RadioGroup基本属性

1)orientation: 排列方式

1
2
3
4
5
6
7
若值为horizontal,则为横向,水平排列: 

android:orientation="horizontal"

若值为vertical,则为纵向,垂直排列。

android:orientation="vertical"

2)checkedButton: 默认选中

直接调用已经放入在radiogroup中且已有id的radiobutton即可默认选中此项。    

RadioButton基本属性

1)checked: 选中状态

若为true则默认被选中,false则默认不被选中。

2)text等相关属性:

text是按钮的文本内容;

textSize是文本字体大小;

textColor是文本字体颜色······

这些属性和TextView一致。

3)button: 按钮属性

若button的值设为”@null”则不显示前面的圆形按钮,只显示文本内容本身

android:button=”@null”

CheckBox

属性

checkbox和radiobutton的属性基本一致。

1)checked: 是否被默认选中

android:checked=”true”

2)text等相关属性:

3)button: 按钮属性

若button的值设为”@null”则不显示前面的方形按钮,只显示文本内容本身

**CheckBox和RadioButton区别: **

RadioButtonCheckBox
选中后,通过点击无法变为未选中选中后,通过点击可以变为未选中
只能同时选中一个能同时选中多个
大部分UI框架中,默认圆形表示大部分UI框架中,默认方形表示

ImageView

属性

属性名关联方法描述
:adjustViewBoundssetAdjustViewBounds(boolean)设置该属性为真可以在ImageView调整边界时保持图片的纵横比例.需要与maxWidth、MaxHeight一起使用,否则单独使用没有效果.
:baselinesetBaseline(int)视图内基线的偏移量.
:baselineAlignBottomsetBaselineAlignBottom(boolean)如果为true,将父视图基线与ImageView底部边缘对齐.
:cropToPaddingsetCropToPadding(boolean)如果为真,会剪切图片以适应内边距的大小,与ImageView的paddingXXX和scrollX|Y属性配合使用.
:maxHeightsetMaxHeight(int)视图最大高度.
:android:maxWidthsetMaxWidth(int)视图最大宽度.
:scaleTypesetScaleType(ImageView.ScaleType)控制为了使图片适合 ImageView 的大小,应该如何变更图片大小或移动图片.
:srcsetImageResource(int)设置可绘制对象作为 ImageView 显示的内容.
:tintsetImageTintList(ColorStateList)为图片设置渲染颜色.
android:tintModesetImageTintMode(PorterDuff.Mode)图片渲染的混合模式.

注意:

scaleType缩放类型设置:

1
2
3
4
5
6
7
8
fitXY:对图像的横向与纵向进行独立缩放,使得该图片完全适应ImageView,但是图片的横纵比可能会发生改变
fitStart:保持纵横比缩放图片,知道较长的边与Image的编程相等,缩放完成后将图片放在ImageView的左上角
fitCenter:同上,缩放后放于中间;
fitEnd:同上,缩放后放于右下角;
center:保持原图的大小,显示在ImageView的中心。当原图的size大于ImageView的size,超过部分裁剪处理。
centerCrop:保持横纵比缩放图片,知道完全覆盖ImageView,可能会出现图片的显示不完全
centerInside:保持横纵比缩放图片,直到ImageView能够完全地显示图片
matrix:默认值,不改变原图的大小,从ImageView的左上角开始绘制原图,原图超过ImageView的部分作裁剪处理

导入网络图片

在bulid.gradle中添加

1
2
3
4
5
6
7
8
9
10
repositories
{
mavenCentral()
google()
}

dependencies {
implementation 'com.github.bumptech.glide:glide:4.11.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'
}

最后

1
Glide.with(this).load(图片地址).into(图片控件);

ListView

属性

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
// transcript模式: 当ListView显示完成之后,新增一条新Item,ListView的处理模式(不显示新Item/自动滚动到新Item)。  
// disabled: 禁用
// normal: 默认状态,如果当前的最后一个Item在ListView 显示范围内,adapter 数据集内容变化时就从滚动底部;否则不滚动到底部
// alwaysScroll: 总是滚动到最新一条, 强制从ListView 的底部开始刷新
android:transcriptMode="alwaysScroll"

// 设置listview的拖动背景色,该处为去掉拖动背景色
android:cacheColorHint="#00000000"

// listView的item选中时的颜色。默认为橙黄底色。
android:listSelector="@color/pink"

// 分割线颜色
android:divider="#cccccc"

// 分割线间距
android:dividerHeight="1dp"

// 不显示滚动条
android:scrollbars="none"

// 去掉上边和下边黑色的阴影
android:fadingEdge="none"

// 设置Item之间无间隙
android:divider="#00000000"
// 设置分割线的图片资源
android:divider="@drawable/list_driver"
// 不想显示分割线
android:divider="@drawable/@null"

// 设置为true就可以实现滚动条的自动隐藏和显示
android:fadeScrollbars="true"

// 加快滑动速度,如果设为true,会在右侧显示快速滚动条
android:fastScrollEnabled="false"

// 点击某一条记录,颜色会显示在最上面,记录上的文字被遮住,所以点击文字不放,文字就看不到
android:drawSelectorOnTop="true"
// 点击某条记录不放,颜色会在记录的后面,成为背景色,但是记录内容的文字是可见的
android:drawSelectorOnTop="false"
  • 需要自定义适配器继承BaseAdapter、重写方法

GridView

属性

android:columnWidth每列的宽度
android:numColumns=”auto_fit”列数根据屏幕大小自动适应
android:verticalSpacing垂直方向的间距(行间距)
android:horizontalSpacing水平方向间距(列间距)
android:stretchMode=”columnWidth|spacingWidth”表示缩放模式(与列宽大小同步和行宽大小同步)
android:cacheColorHint=”#00000000”去除拖动时默认的黑色背景
android:listSelector=”#00000000”去除选中时的黄色底色
android:scrollbars=”none”隐藏GridView的滚动条
android:fadeScrollEnabled=”true”设置为true就可以实现滚动条的自动隐藏和显示
android:fastScrollEnabled=”true”GridView出现快速滚动的按钮(至少滚动4页才会显示)
android:numColumns=””设置列数
  • 需要自定义适配器继承BaseAdapter、重写方法

ScrollView与HorizontalScrollView

属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
android:scrollbars
设置滚动条显示。none(隐藏),horizontal(水平),vertical(垂直)。
android:scrollbarFadeDuration
设置滚动条淡出效果(从有到慢慢的变淡直至消失)时间,以毫秒为单位。Android2.2中滚动条滚动完之后会消失,再滚动又会出来,在1.5、1.6版本里面会一直显示着。
android:scrollbarSize
设置滚动条的宽度。
android:scrollbarStyle
设置滚动条的风格和位置。设置值: insideOverlay、insideInset、outsideOverlay、outsideInset
android:scrollbarThumbHorizontal
设置水平滚动条的drawable。
android:scrollbarThumbVertical
设置垂直滚动条的drawable.
android:scrollbarTrackHorizontal
设置水平滚动条背景(轨迹)的色drawable
android:soundEffectsEnabled
设置点击或触摸时是否有声音效果

RecyclerView

RecyclerView 的基本用法

打开 app/build.gradle 文件,在 dependencies 闭包中添加如下内容(会爆红,但没没事)

1
implementation 'com.android.support:design:28.0.0'

基本操作

1
2
3
4
5
6
7
8
9
10
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);  
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
//设置布局管理器
recyclerView.setLayoutManager(layoutManager);
//设置为垂直布局,这也是默认的
layoutManager.setOrientation(OrientationHelper.VERTICAL);
//设置Adapter
recyclerView.setAdapter(recycleAdapter);
//设置分隔线
recyclerView.addItemDecoration(new DividerGridItemDecoration(this));

可以看到对RecylerView的设置过程,比ListView要复杂一些,这也是RecylerView高度解耦的表现,虽然代码抒写上有点复杂,但它的扩展性是极高的。

在了解了RecyclerView的一些控制之后,紧接着来看看它的Adapter的写法,RecyclerView的Adapter与ListView的Adapter还是有点区别的,RecyclerView.Adapter,需要实现3个方法:

①onCreateViewHolder()

这个方法主要生成为每个Item inflater出一个View,但是该方法返回的是一个ViewHolder。该方法把View直接封装在ViewHolder中,然后我们面向的是ViewHolder这个实例,当然这个ViewHolder需要我们自己去编写。直接省去了当初的convertView.setTag(holder)和convertView.getTag()这些繁琐的步骤。

②onBindViewHolder()

这个方法主要用于适配渲染数据到View中。方法提供给你了一个viewHolder,而不是原来的convertView。

③getItemCount()

这个方法就类似于BaseAdapter的getCount方法了,即总共有多少个条目。

看这篇文章:https://blog.csdn.net/qq_39539367/article/details/80338177

WebView

简介

WebView是一个基于webkit引擎、展现web页面的控件。

Android的Webview在低版本和高版本采用了不同的webkit版本内核,4.4后直接使用了Chrome。


作用

  • 显示和渲染Web页面
  • 直接使用html文件(网络上或本地assets中)作布局
  • 可和JavaScript交互调用

WebView控件功能强大,除了具有一般View的属性和设置外,还可以对url请求、页面加载、渲染、页面交互进行强大的处理。


使用介绍

一般来说Webview可单独使用,可联合其工具类一起使用,所以接下来,我会介绍:

  • Webview类自身的常见方法
  • Webview的最常用的工具类: WebSettings类、WebViewClient类、WebChromeClient类
  • Android 和 Js的交互
Webview类常用方法

加载url

加载方式根据资源分为三种

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//方式1. 加载一个网页: 
webView.loadUrl("http://www.google.com/");

//方式2: 加载apk包中的html页面(创建assets文件)
webView.loadUrl("file:///android_asset/test.html");

//方式3: 加载手机本地的html页面
webView.loadUrl("content://com.android.htmlfileprovider/sdcard/test.html");

// 方式4: 加载 HTML 页面的一小段内容
WebView.loadData(String data, String mimeType, String encoding)
// 参数说明:
// 参数1: 需要截取展示的内容
// 内容里不能出现 ’#’, ‘%’, ‘\’ , ‘?’ 这四个字符,若出现了需用 %23, %25, %27, %3f 对应来替代,否则会出现异常
// 参数2: 展示内容的类型
// 参数3: 字节码
WebView的状态
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//激活WebView为活跃状态,能正常执行网页的响应
webView.onResume() ;

//当页面被失去焦点被切换到后台不可见状态,需要执行onPause
//通过onPause动作通知内核暂停所有的动作,比如DOM的解析、plugin的执行、JavaScript执行。
webView.onPause();

//当应用程序(存在webview)被切换到后台时,这个方法不仅仅针对当前的webview而是全局的全应用程序的webview
//它会暂停所有webview的layout,parsing,javascripttimer。降低CPU功耗。
webView.pauseTimers()
//恢复pauseTimers状态
webView.resumeTimers();

//销毁Webview
//在关闭了Activity时,如果Webview的音乐或视频,还在播放。就必须销毁Webview
//但是注意: webview调用destory时,webview仍绑定在Activity上
//这是由于自定义webview构建时传入了该Activity的context对象
//因此需要先从父容器中移除webview,然后再销毁webview:
rootLayout.removeView(webView);
webView.destroy();
关于前进 / 后退网页
1
2
3
4
5
6
7
8
9
10
11
12
13
//是否可以后退
Webview.canGoBack()
//后退网页
Webview.goBack()

//是否可以前进
Webview.canGoForward()
//前进网页
Webview.goForward()

//以当前的index为起始点前进或者后退到历史记录中指定的steps
//如果steps为负数则为后退,正数则为前进
Webview.goBackOrForward(intsteps)

常见用法: Back键控制网页后退

  • 问题: 在不做任何处理前提下 ,浏览网页时点击系统的”Back”键,整个 Browser 会调用 finish()而结束自身
  • 目标: 点击返回后,是网页回退而不是推出浏览器
  • 解决方案: 在当前Activity中处理并消费掉该 Back 事件
1
2
3
4
5
6
7
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ((keyCode == KEYCODE_BACK) && mWebView.canGoBack()) {
mWebView.goBack();
return true;
}
return super.onKeyDown(keyCode, event);
}
清除缓存数据
1
2
3
4
5
6
7
8
9
10
//清除网页访问留下的缓存
//由于内核缓存是全局的因此这个方法不仅仅针对webview而是针对整个应用程序.
Webview.clearCache(true);

//清除当前webview访问的历史记录
//只会webview访问历史记录里的所有记录除了当前访问记录
Webview.clearHistory();

//这个api仅仅清除自动完成填充的表单数据,并不会清除WebView存储到本地的数据
Webview.clearFormData();

常用工具类

WebSettings类
  • 作用: 对WebView进行配置和管理
  • 配置步骤 & 常见方法:

配置步骤1: 添加访问网络权限(AndroidManifest.xml)

这是前提!这是前提!这是前提!

1
<uses-permission android:name="android.permission.INTERNET"/>

配置步骤2: 生成一个WebView组件(有两种方式)

1
2
3
4
5
//方式1: 直接在在Activity中生成
WebView webView = new WebView(this)

//方法2: 在Activity的layout文件里添加webview控件:
WebView webview = (WebView) findViewById(R.id.webView1);

配置步骤3: 进行配置-利用WebSettings子类(常见方法)

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
//声明WebSettings子类
WebSettings webSettings = webView.getSettings();

//如果访问的页面中要与Javascript交互,则webview必须设置支持Javascript
webSettings.setJavaScriptEnabled(true);
// 若加载的 html 里有JS 在执行动画等操作,会造成资源浪费(CPU、电量)
// 在 onStop 和 onResume 里分别把 setJavaScriptEnabled() 给设置成 false 和 true 即可

//支持插件
webSettings.setPluginsEnabled(true);

//设置自适应屏幕,两者合用
webSettings.setUseWideViewPort(true); //将图片调整到适合webview的大小
webSettings.setLoadWithOverviewMode(true); // 缩放至屏幕的大小

//缩放操作
webSettings.setSupportZoom(true); //支持缩放,默认为true。是下面那个的前提。
webSettings.setBuiltInZoomControls(true); //设置内置的缩放控件。若为false,则该WebView不可缩放
webSettings.setDisplayZoomControls(false); //隐藏原生的缩放控件

//其他细节操作
webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); //关闭webview中缓存
webSettings.setAllowFileAccess(true); //设置可以访问文件
webSettings.setJavaScriptCanOpenWindowsAutomatically(true); //支持通过JS打开新窗口
webSettings.setLoadsImagesAutomatically(true); //支持自动加载图片
webSettings.setDefaultTextEncodingName("utf-8");//设置编码格式

常见用法: 设置WebView缓存

  • 当加载 html 页面时,WebView会在/data/data/包名目录下生成 database 与 cache 两个文件夹
  • 请求的 URL记录保存在 WebViewCache.db,而 URL的内容是保存在 WebViewCache 文件夹下
  • 是否启用缓存:
1
2
3
4
5
6
7
8
9
10
//优先使用缓存: 
WebView.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
//缓存模式如下:
//LOAD_CACHE_ONLY: 不使用网络,只读取本地缓存数据
//LOAD_DEFAULT: (默认)根据cache-control决定是否从网络上取数据。
//LOAD_NO_CACHE: 不使用缓存,只从网络获取数据.
//LOAD_CACHE_ELSE_NETWORK,只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据。

//不使用缓存:
WebView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
  • 结合使用(离线加载)
1
2
3
4
5
6
7
8
9
10
11
12
if (NetStatusUtil.isConnected(getApplicationContext())) {
webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);//根据cache-control决定是否从网络上取数据。
} else {
webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);//没网,则从本地获取,即离线加载
}

webSettings.setDomStorageEnabled(true); // 开启 DOM storage API 功能
webSettings.setDatabaseEnabled(true); //开启 database storage API 功能
webSettings.setAppCacheEnabled(true);//开启 Application Caches 功能

String cacheDirPath = getFilesDir().getAbsolutePath() + APP_CACAHE_DIRNAME;
webSettings.setAppCachePath(cacheDirPath); //设置 Application Caches 缓存目录

注意:每个 Application 只调用一次 WebSettings.setAppCachePath(),WebSettings.setAppCacheMaxSize()

WebViewClient类
  • 作用: 处理各种通知 & 请求事件
  • 常见方法:

常见方法1: shouldOverrideUrlLoading()

  • 作用: 打开网页时不调用系统浏览器, 而是在本WebView中显示;在网页上的所有加载都经过这个方法,这个函数我们可以做很多操作。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//步骤1. 定义Webview组件
Webview webview = (WebView) findViewById(R.id.webView1);

//步骤2. 选择加载方式
//方式1. 加载一个网页:
webView.loadUrl("http://www.google.com/");

//方式2: 加载apk包中的html页面
webView.loadUrl("file:///android_asset/test.html");

//方式3: 加载手机本地的html页面
webView.loadUrl("content://com.android.htmlfileprovider/sdcard/test.html");

//步骤3. 复写shouldOverrideUrlLoading()方法,使得打开网页时不调用系统浏览器, 而是在本WebView中显示
webView.setWebViewClient(new WebViewClient(){
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
});

常见方法2: onPageStarted()

  • 作用: 开始载入页面调用的,我们可以设定一个loading的页面,告诉用户程序在等待网络响应。
1
2
3
4
5
6
  webView.setWebViewClient(new WebViewClient(){
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
//设定加载开始的操作
}
});

常见方法3: onPageFinished()

  • 作用: 在页面加载结束时调用。我们可以关闭loading 条,切换程序动作。
1
2
3
4
5
6
  webView.setWebViewClient(new WebViewClient(){
@Override
public void onPageFinished(WebView view, String url) {
//设定加载结束的操作
}
});

常见方法4: onLoadResource()

  • 作用: 在加载页面资源时会调用,每一个资源(比如图片)的加载都会调用一次。
1
2
3
4
5
6
  webView.setWebViewClient(new WebViewClient(){
@Override
public boolean onLoadResource(WebView view, String url) {
//设定加载资源的操作
}
});

常见方法5: onReceivedError()

  • 作用: 加载页面的服务器出现错误时(如404)调用。

App里面使用webview控件的时候遇到了诸如404这类的错误的时候,若也显示浏览器里面的那种错误提示页面就显得很丑陋了,那么这个时候我们的app就需要加载一个本地的错误提示页面,即webview如何加载一个本地的页面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//步骤1: 写一个html文件(error_handle.html),用于出错时展示给用户看的提示页面
//步骤2: 将该html文件放置到代码根目录的assets文件夹下

//步骤3: 复写WebViewClient的onRecievedError方法
//该方法传回了错误码,根据错误类型可以进行不同的错误分类处理
webView.setWebViewClient(new WebViewClient(){
@Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl){
switch(errorCode)
{
case HttpStatus.SC_NOT_FOUND:
view.loadUrl("file:///android_assets/error_handle.html");
break;
}
}
});

常见方法6: onReceivedSslError()

  • 作用: 处理https请求

webView默认是不处理https请求的,页面显示空白,需要进行如下设置:

1
2
3
4
5
6
7
8
9
10
11
12
13
webView.setWebViewClient(new WebViewClient() {    
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
handler.proceed(); //表示等待证书响应
// handler.cancel(); //表示挂起连接,为默认方式
// handler.handleMessage(null); //可做其他处理
}
});

// 特别注意: 5.1以上默认禁止了https和http混用,以下方式是开启
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
mWebView.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
}
WebChromeClient类
  • 作用: 辅助 WebView 处理 Javascript 的对话框,网站图标,网站标题等等。
  • 常见使用:

常见方法1: onProgressChanged()

  • 作用: 获得网页的加载进度并显示
1
2
3
4
5
6
7
8
9
10
webview.setWebChromeClient(new WebChromeClient(){

@Override
public void onProgressChanged(WebView view, int newProgress) {
if (newProgress < 100) {
String progress = newProgress + "%";
progress.setText(progress);
} else {
}
});

常见方法2: onReceivedTitle()

  • 作用: 获取Web页中的标题

每个网页的页面都有一个标题,比如www.baidu.com这个页面的标题即”百度一下,你就知道”,那么如何知道当前webview正在加载的页面的title并进行设置呢?

1
2
3
4
5
6
webview.setWebChromeClient(new WebChromeClient(){

@Override
public void onReceivedTitle(WebView view, String title) {
titleview.setText(title);
}

常见方法3: onJsAlert()

  • 作用: 支持javascript的警告框

一般情况下在 Android 中为 Toast,在文本里面加入\n就可以换行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
webview.setWebChromeClient(new WebChromeClient() {

@Override
public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
new AlertDialog.Builder(MainActivity.this)
.setTitle("JsAlert")
.setMessage(message)
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
result.confirm();
}
})
.setCancelable(false)
.show();
return true;
}

常见方法4: onJsConfirm()

  • 作用: 支持javascript的确认框
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
webview.setWebChromeClient(new WebChromeClient() {

@Override
public boolean onJsConfirm(WebView view, String url, String message, final JsResult result) {
new AlertDialog.Builder(MainActivity.this)
.setTitle("JsConfirm")
.setMessage(message)
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
result.confirm();
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
result.cancel();
}
})
.setCancelable(false)
.show();
// 返回布尔值: 判断点击时确认还是取消
// true表示点击了确认;false表示点击了取消;
return true;
}

常见方法5: onJsPrompt()

  • 作用: 支持javascript输入框

点击确认返回输入框中的值,点击取消返回 null。

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
webview.setWebChromeClient(new WebChromeClient() {
@Override
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, final JsPromptResult result) {
final EditText et = new EditText(MainActivity.this);
et.setText(defaultValue);
new AlertDialog.Builder(MainActivity.this)
.setTitle(message)
.setView(et)
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
result.confirm(et.getText().toString());
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
result.cancel();
}
})
.setCancelable(false)
.show();

return true;
}

WebView与JavaScript的交互

具体请看我写的文章: 最全面 & 最详细的 Android WebView与JS的交互方式 汇总

注意事项: 如何避免WebView内存泄露?

不在xml中定义 Webview ,而是在需要的时候在Activity中创建,并且Context使用 getApplicationgContext()

1
2
3
4
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
mWebView = new WebView(getApplicationContext());
mWebView.setLayoutParams(params);
mLayout.addView(mWebView);

在 Activity 销毁( WebView )的时候,先让 WebView 加载null内容,然后移除 WebView,再销毁 WebView,最后置空。

1
2
3
4
5
6
7
8
9
10
11
12
@Override
protected void onDestroy() {
if (mWebView != null) {
mWebView.loadDataWithBaseURL(null, "", "text/html", "utf-8", null);
mWebView.clearHistory();

((ViewGroup) mWebView.getParent()).removeView(mWebView);
mWebView.destroy();
mWebView = null;
}
super.onDestroy();
}

实例
  • 目标: 实现显示”www.baidu.com“、获取其标题、提示加载开始 & 结束和获取加载进度
  • 具体实现:

步骤1: 添加访问网络权限

这是前提!这是前提!这是前提!

AndroidManifest.xml

1
<uses-permission android:name="android.permission.INTERNET"/>

步骤2: 主布局
activity_main.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
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
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.carson_ho.webview_demo.MainActivity">


<!-- 获取网站的标题-->
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""/>

<!--开始加载提示-->
<TextView
android:id="@+id/text_beginLoading"
android:layout_below="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""/>

<!--获取加载进度-->
<TextView
android:layout_below="@+id/text_beginLoading"
android:id="@+id/text_Loading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""/>

<!--结束加载提示-->
<TextView
android:layout_below="@+id/text_Loading"
android:id="@+id/text_endLoading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""/>

<!--显示网页区域-->
<WebView
android:id="@+id/webView1"
android:layout_below="@+id/text_endLoading"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginTop="10dp" />
</RelativeLayout>

步骤3: 根据需要实现的功能从而使用相应的子类及其方法(注释很清楚了)
MainActivity.java

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
package com.example.carson_ho.webview_demo;

import android.graphics.Bitmap;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.KeyEvent;
import android.view.ViewGroup;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.TextView;


public class MainActivity extends AppCompatActivity {
WebView mWebview;
WebSettings mWebSettings;
TextView beginLoading,endLoading,loading,mtitle;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);


mWebview = (WebView) findViewById(R.id.webView1);
beginLoading = (TextView) findViewById(R.id.text_beginLoading);
endLoading = (TextView) findViewById(R.id.text_endLoading);
loading = (TextView) findViewById(R.id.text_Loading);
mtitle = (TextView) findViewById(R.id.title);

mWebSettings = mWebview.getSettings();

mWebview.loadUrl("http://www.baidu.com/");


//设置不用系统浏览器打开,直接显示在当前Webview
mWebview.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
});

//设置WebChromeClient类
mWebview.setWebChromeClient(new WebChromeClient() {


//获取网站标题
@Override
public void onReceivedTitle(WebView view, String title) {
System.out.println("标题在这里");
mtitle.setText(title);
}


//获取加载进度
@Override
public void onProgressChanged(WebView view, int newProgress) {
if (newProgress < 100) {
String progress = newProgress + "%";
loading.setText(progress);
} else if (newProgress == 100) {
String progress = newProgress + "%";
loading.setText(progress);
}
}
});


//设置WebViewClient类
mWebview.setWebViewClient(new WebViewClient() {
//设置加载前的函数
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
System.out.println("开始加载了");
beginLoading.setText("开始加载了");

}

//设置结束加载函数
@Override
public void onPageFinished(WebView view, String url) {
endLoading.setText("结束加载了");

}
});
}

//点击返回上一页面而不是退出浏览器
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && mWebview.canGoBack()) {
mWebview.goBack();
return true;
}

return super.onKeyDown(keyCode, event);
}

//销毁Webview
@Override
protected void onDestroy() {
if (mWebview != null) {
mWebview.loadDataWithBaseURL(null, "", "text/html", "utf-8", null);
mWebview.clearHistory();

((ViewGroup) mWebview.getParent()).removeView(mWebview);
mWebview.destroy();
mWebview = null;
}
super.onDestroy();
}
}
Demo地址

源代码: Carson_Ho的Github-WebviewDemo


总结
  • 本文全面介绍了Webview,总结如下

https://upload-images.jianshu.io/upload_images/944365-6e249d5a3cc7d343.png

​ 示意图
链接: https://www.jianshu.com/p/3c94ae673e2a

Toast

使用Toast来显示消息提示框非常简单,只需要一下三个步骤:

创建一个Toast对象。通常有两种方法: 一种是使用构造方式进行创建;

1
Toast toast=new Toast(this);

另一种是调用Toast类的makeText()方法创建。

1
Toast toast=Toast.makeText(this,"要显示的内容",Toast.LENGTH_SHORT);

调用Toast类提供的方法来设置该消息提示框的对齐方式、页边距、显示的内容等等。

常用的方法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//用于设置消息提示框持续的时间,参数通常使用Toast.LENGTH_LONG或Toast.LENGTH_SHORT
setDuration(int duration)

//用于设置消息提示框的位置,参数grivaty用于指定对齐方式: xOffset和yOffset用于指定具体的偏移值
setGravity(int gravity,int xOffset,int yOffset)

//用于设置消息提示的页边距
setMargin(float horizontalMargin,float verticalMargin)

//用于设置要显示的文本内容
setText(CharSequence s)

//用于设置将要在提示框中显示的视图
setView(View view)

AlertDialog

AlertDialog的六种实现方式

1、创建AlertDialog.Builder对象

2、调用Builder对象的setTitle方法设置标题,setIcon方法设置图标

3、调用Builder相关方法如setMessage方法、setItems方法、setSingleChoiceItems方法、setMultiChoiceItems方法、setAdapter方法、setView方法设置不同类型的对话框内容。

4、调用setPositiveButton、setNegativeButton、setNeutralButton设置多个按钮

5、调用Builder对象的create()方法创建AlertDialog对象

6、调用AlertDialog对象的show()方法将对话框显示出来

创建AlertDialog.Builder对象

import android.support.v7.app.AppCompatActivity;

import android.support.v7.app.ApplyDialog;

实例化对象的方法:

AlertDialog.Builder builder =newAlertDialog.Builder(this);//实例化

调用Builder对象的setTitle方法设置标题,setIcon方法设置图标

builder.setTitle(“Material Design Dialog”);

builder.setIcon(R.mipmap.ic_launcher);

调用Builder不同方法设置不同类型的对话框内容。

1.setMessage() 设置对话框内容为简单文本内容

builder.setMessage(“Hello World”);

https://upload-images.jianshu.io/upload_images/9724079-98e8da21451f7a88.png

简单文本弹窗

2.setItems() 设置文本框内容为简单列表项

finalString [] Items = {“google”,”twitter”,”line”,”QQ”,”weixin”};

builder.setItems(Items, null);

https://upload-images.jianshu.io/upload_images/9724079-e5e61ba0aa6ccdb6.png

简单列表项弹窗

3.setSingleChoiceItems() 设置对话框内容为单选列表项

finalString [] Items = {“google”,”twitter”,”line”,”QQ”,”weixin”};

builder.setSingleChoiceItems(Items, 0,null); //0 为默认选中哪个

https://upload-images.jianshu.io/upload_images/9724079-27a69dc9adfa9cba.png

单选列表项弹窗

4.setMultiChoiceItems() 设置对话框内容为多选项列表

finalString [] Items = {“google”,”twitter”,”line”,”QQ”,”weixin”};

builder.setMultiChoiceItems(Items, new boolean[]{true, false, false, false, false},null); //设置一个数组代表是否勾选

https://upload-images.jianshu.io/upload_images/9724079-6838f7c6c7d7eb0d.png

多选列表项弹窗

5.setAdapter() 设置对话框内容为自定义列表项

finalString [] Items = {“google”,”twitter”,”line”,”QQ”,”weixin”};

builder.setAdapter(newArrayAdapter(MainActivity.this,android.R.layout.activity_list_item,android.R.id.text1,Items),null);//此处涉及到系统自带布局和自定义布局,以后详述,此处使用系统自带布局activity_list_item为一个列表布局)

https://upload-images.jianshu.io/upload_images/9724079-0215d85ceea3059a.png

自定义列表项弹窗

6.setView() 设置对话框为自定义View

Viewview =View.inflate(MainActivity.this,R.layout.login,null);

builder.setView(view);

https://upload-images.jianshu.io/upload_images/9724079-662b1a888760dd8c.png

自定义View弹窗

调用setPositiveButton、setNegativeButton、setNeutralButton设置多个按钮

三个按钮跟普通按钮没有什么区别,只是名字有不同,从上到下分别代表确定,否定,和中立

builder.setPositiveButton(“确定”, null);

builder.setNegativeButton(“取消”, null);

builder.setNeutralButton(“跳过”,null);

调用Builder对象的create()方法创建AlertDialog对象

builder.create();

调用AlertDialog对象的show()方法将对话框显示出来

builder.show();

链接: https://www.jianshu.com/p/d3874b8e3ee5

ProgressBar与ProgressDialog

ProgressBar

ProgressBar是Android下的进度条,也是为数不多的直接继承于View类的控件,直接子类有AbsSeekBar和ContentLoadingProgressBar,其中AbsSeekBar的子类有SeekBar和RatingBar

ProgressBar的使用注意:
  • 1、ProgressBar有两个进度,一个是android:progress,另一个是android:secondaryProgress。后者主要是为缓存需要所涉及的,比如在看网络视频时候都会有一个缓存的进度条以及还要一个播放的进度,在这里缓存的进度就可以是android:secondaryProgress,而播放进度就是android:progress。
  • 2、ProgressBar分为确定的和不确定的,上面说的播放进度、缓存等就是确定的。相反地,不确定的就是不清楚、不确定一个操作需要多长时间来完成,这个时候就需要用的不确定的ProgressBar了。这个是由属性android:indeterminate来控制的,如果设置为true的话,那么ProgressBar就可能是圆形的滚动条或者水平的滚动条(由样式决定)。默认情况下,如果是水平进度条,那么就是确定的。
  • 3、ProgressBar的样式设定其实有两种方式,在API文档中说明的方式如下:
    • Widget.ProgressBar.Horizontal
    • Widget.ProgressBar.Small
    • Widget.ProgressBar.Large
    • Widget.ProgressBar.Inverse
    • Widget.ProgressBar.Small.Inverse
    • Widget.ProgressBar.Large.Inverse

使用的时候可以这样: style=”@android:style/Widget.ProgressBar.Small”。另外还有一种方式就是使用系统的attr,上面的方式是系统的style:

  • style=”?android:attr/progressBarStyle”
  • style=”?android:attr/progressBarStyleHorizontal”
  • style=”?android:attr/progressBarStyleInverse”
  • style=”?android:attr/progressBarStyleLarge”
  • style=”?android:attr/progressBarStyleLargeInverse”
  • style=”?android:attr/progressBarStyleSmall”
  • style=”?android:attr/progressBarStyleSmallInverse”
  • style=”?android:attr/progressBarStyleSmallTitle”
ProgressBar几种比较常用的属性:

布局中设置:

1
2
3
android:progress="50"——第一显示进度
android:secondaryProgress="80"——第二显示进度
android:indeterminate="true"——设置是否精确显示,true表示不精确显示进度,false表示精确显示进度

使用Java代码设置:

1
2
3
4
5
6
7
setProgress(int) //设置第一进度
setSecondaryProgress(int) //设置第二进度
getProgress() //获取第一进度
getSecondaryProgress() //获取第二进度
incrementProgressBy(int) //增加或减少第一进度
incrementSecondaryProgressBy(int) //增加或减少第二进度
getMax() //获取最大进度
ProgressBar常见的几种样式
  • 横向progressBarStyleHorizontal
1
2
3
4
5
6
7
8
<ProgressBar
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="240dp"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="10dp"
android:max="100"
android:progress="50" />

效果图:

https://upload-images.jianshu.io/upload_images/8077710-64c9683e319a801a.png

  • 横向Widget.ProgressBar.Horizontal
1
2
3
4
5
6
7
8
<ProgressBar
style="@android:style/Widget.ProgressBar.Horizontal"
android:layout_width="240dp"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="10dp"
android:max="100"
android:progress="50" />

效果图:

https://upload-images.jianshu.io/upload_images/8077710-7e11fecb254949e5.png

  • 圆形:progressBarStyleLarge
1
2
3
4
5
6
7
8
<ProgressBar
android:layout_gravity="center_horizontal"
android:layout_marginTop="10dp"
android:id="@+id/progressBar1"
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>

效果图:

https://upload-images.jianshu.io/upload_images/8077710-85316f164892ab66.png

  • 圆形:普通
1
2
3
4
5
6
<ProgressBar
android:layout_marginTop="10dp"
android:id="@+id/progressBar2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>

效果图:

https://upload-images.jianshu.io/upload_images/8077710-99788da628dd73d9.png

  • 圆形:progressBarStyleSmall
1
2
3
4
5
6
7
8
<ProgressBar
android:layout_marginTop="10dp"
android:layout_gravity="center_horizontal"
android:id="@+id/progressBar3"
style="?android:attr/progressBarStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>

效果图:

https://upload-images.jianshu.io/upload_images/8077710-15f5cdfbcb9bd6f0.png

自定义进度条修改进度的颜色

在布局文件中的style属性就是设置进度条样式的

1
2
3
4
<ProgressBar
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

实际上面的背景文件是位于@android:style/Widget.ProgressBar.Horizontal,既上面的布局可以写成

1
2
3
4
<ProgressBar
style="@android:style/Widget.ProgressBar.Horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

查看系统中的水平进度条风格文件

1
2
3
4
5
6
7
8
<style name="Widget.ProgressBar.Horizontal">
<item name="indeterminateOnly">false</item>
<item name="progressDrawable">@drawable/progress_horizontal</item>
<item name="indeterminateDrawable">@drawable/progress_indeterminate_horizontal</item>
<item name="minHeight">20dip</item>
<item name="maxHeight">20dip</item>
<item name="mirrorForRtl">true</item>
</style>

上面的android:progressDrawable属性是设置进度条背景,进入查看

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
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2008 The Android Open Source Project

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

<item android:id="@android:id/background">
<shape>
<corners android:radius="5dip" />
<gradient
android:startColor="#ff9d9e9d"
android:centerColor="#ff5a5d5a"
android:centerY="0.75"
android:endColor="#ff747674"
android:angle="270"
/>
</shape>
</item>

<item android:id="@android:id/secondaryProgress">
<clip>
<shape>
<corners android:radius="5dip" />
<gradient
android:startColor="#80ffd300"
android:centerColor="#80ffb600"
android:centerY="0.75"
android:endColor="#a0ffcb00"
android:angle="270"
/>
</shape>
</clip>
</item>

<item android:id="@android:id/progress">
<clip>
<shape>
<corners android:radius="5dip" />
<gradient
android:startColor="#ffffd300"
android:centerColor="#ffffb600"
android:centerY="0.75"
android:endColor="#ffffcb00"
android:angle="270"
/>
</shape>
</clip>
</item>

</layer-list>

可以看到,上面文件中的3个item标签分别是设置: 进度条、第二进度条、第一进度条的背景色。这里我们在drawable文件夹下新建一个pb_pd_sp_blog.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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- 进度条背景色 -->
<item android:id="@android:id/background">
<shape>
<corners android:radius="5dip" />
<gradient
android:startColor="#ff9d9e9d"
android:centerColor="#ff5a5d5a"
android:centerY="0.75"
android:endColor="#ff747674"
android:angle="270"
/>
</shape>
</item>

<!-- 第二进度条 -->
<item android:id="@android:id/secondaryProgress">
<clip>
<shape>
<corners android:radius="5dip" />
<gradient
android:startColor="#b9a4ff"
android:centerColor="#c6b7ff"
android:centerY="0.75"
android:endColor="#c3b2ff"
android:angle="270"
/>
</shape>
</clip>
</item>

<!-- 第二进度条 -->
<item android:id="@android:id/progress">
<clip>
<shape>
<corners android:radius="5dip" />
<gradient
android:startColor="#57e8ff"
android:centerColor="#74ebff"
android:centerY="0.75"
android:endColor="#8eefff"
android:angle="270"
/>
</shape>
</clip>
</item>
</layer-list>

https:////upload-images.jianshu.io/upload_images/8077710-577bc82764f7413e.png

自定义进度条多种属性

我们不但可以修改进度的颜色,也可以修改其他属性我们可以自定义实现如下效果
布局中的属性设置

1
2
3
4
5
6
7
8
9
10
11
<ProgressBar
style="@android:style/Widget.ProgressBar.Horizontal"
android:layout_width="240dp"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="10dp"
android:max="100"
android:progress="100"
android:maxHeight="12dp"
android:minHeight="12dp"
android:progressDrawable="@drawable/pb_pd_sp_download" />

drawable文件夹下的pb_pd_sp_downloadxml定义

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
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- 进度条背景色 -->
<item android:id="@android:id/background">
<shape>
<corners android:radius="6dp" />
<solid
android:color="@color/c_ffffff"
/>
<size
android:height="12dp"
/>
<stroke
android:width="2dp"
android:color="@color/c_c4e9ff"
/>
<!-- <gradient
android:startColor="#ff9d9e9d"
android:centerColor="#ff5a5d5a"
android:centerY="0.75"
android:endColor="#ff747674"
android:angle="270"
/>-->
</shape>
</item>

<!-- 第二进度条 -->
<item android:id="@android:id/secondaryProgress">
<clip>
<shape>
<corners android:radius="6dp" />
<gradient
android:startColor="#b9a4ff"
android:centerColor="#c6b7ff"
android:centerY="0.75"
android:endColor="#c3b2ff"
android:angle="270"
/>
<size
android:height="12dp"
/>
</shape>
</clip>
</item>

<!-- 第一进度条 -->
<item android:id="@android:id/progress">
<clip>
<shape>
<corners android:radius="6dp" />
<!--<solid
android:color="@color/c_0061dd"
/>-->
<gradient

android:startColor="@color/c_5cacff"
android:centerColor="@color/c_0061dd"
android:endColor="@color/c_0061dd"
android:angle="45"
/>
<size
android:height="12dp"
/>
<stroke
android:width="2dp"
android:color="@android:color/transparent"
/>
<!--<gradient
android:startColor="#57e8ff"
android:centerColor="#74ebff"
android:centerY="0.75"
android:endColor="#8eefff"
android:angle="270"
/>-->
</shape>
</clip>
</item>
</layer-list>

效果图:

https://upload-images.jianshu.io/upload_images/8077710-e7863485c7666ac9.png
链接: https://www.jianshu.com/p/f613571addb5

ProgressDialog

ProgressDialog的创建方式有两种,一种是new ProgressDialog,一种是调用ProgressDialog的静态方法show()创建并显示,这种进度条只能是圆形条。

https://upload-images.jianshu.io/upload_images/11881598-4513061544a34ed3.png

1
ProgressDialog dialog = ProgressDialog.show(this, "提示", "正在登陆中…", true, false, null);
常用方法
  • setProgressStyle: 设置进度条风格,风格为圆形,旋转的。

  • setTitlt: 设置标题

  • setMessage: 设置提示信息;

  • setIcon: 设置标题图标;

  • setIndeterminate: 设置ProgressDialog 的进度条是否不明确;这个属性对于ProgressDailog默认的转轮模式没有实际意义,默认下设置为true,它仅仅对带有ProgressBar的Dialog有作用。修改这个属性为false后可以实时更新进度条的进度。

  • setCancelable: 设置ProgressDialog 是否可以按返回键取消;

  • cancelListner:当前Dialog强制取消之后将会被执行,通常用来清理未完成的任务。

  • setButton: 设置ProgressDialog 的一个Button(需要监听Button事件);

  • show: 显示ProgressDialog。

  • cancel: 删除progressdialog

  • dismiss: 删除progressdialog 作用和cancel相同

  • setMax(int)、getMax: 设置最大进度条的值

  • setProgress(int)、getProgress: 更新进度条,当然一般都需要Handler的结合来更新进度条

  • incrementProgressBy(int)增加进度条

  • setProgressDrawable: 设置progress发生变化时的进度指示条的背景图

链接: https://www.jianshu.com/p/a9855cdc4712

延伸: 自定义Dialog

https://blog.csdn.net/sakurakider/article/details/80735400

PopupWindow的相关函数
构造函数:
1
2
3
4
5
6
7
8
9
10
11
//方法一: 
public PopupWindow (Context context)

//方法二:
public PopupWindow(View contentView)

//方法三:
public PopupWindow(View contentView, int width, int height)

//方法四:
public PopupWindow(View contentView, int width, int height, boolean focusable)

首要注意: 看这里有四个构造函数,但要生成一个PopupWindow最基本的三个条件是一定要设置的: View contentView,int width, int height ;少任意一个就不可能弹出来PopupWindow!!!!

所以,如果使用方法一来构造PopupWindow,那完整的构造代码应该是这样的:

1
2
3
4
5
6
7
8
9
View contentView = LayoutInflater.from(MainActivity.this).inflate(R.layout.popuplayout, null);

PopupWindwo popWnd = PopupWindow (context);

popWnd.setContentView(contentView);

popWnd.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT);

popWnd.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);

有关为什么一定要设置width和height的原因,我们后面会讲,这里说一下为什么样强制设置contentView;很简单的原因是因为PopupWindow没有默认布局,它不会像AlertDialog那样只setTitle,就能弹出来一个框。PopupWindow是没有默认布局的,它的布局只有通过我们自己设置才行。由于方法三中,含有了这三个必备条件,不用单独设置contentview或者width、height,所以构造方法三是用的最多的一个构造方法。
最后,方法四中的focusable变量不是必须的,有关它的方法和意义,我们会在下一篇中细讲。

显示函数

显示函数主要使用下面三个:

1
2
3
4
5
6
7
8
//相对某个控件的位置(正左下方),无偏移
showAsDropDown(View anchor):

//相对某个控件的位置,有偏移;xoff表示x轴的偏移,正值表示向左,负值表示向右;yoff表示相对y轴的偏移,正值是向下,负值是向上;
showAsDropDown(View anchor, int xoff, int yoff):

//相对于父控件的位置(例如正中央Gravity.CENTER,下方Gravity.BOTTOM等),可以设置偏移或无偏移
showAtLocation(View parent, int gravity, int x, int y):

这里有两种显示方式:
1、显示在某个指定控件的下方
showAsDropDown(View anchor):
showAsDropDown(View anchor, int xoff, int yoff);
2、指定父视图,显示在父控件的某个位置(Gravity.TOP,Gravity.RIGHT等)
showAtLocation(View parent, int gravity, int x, int y);

其它函数
1
2
3
4
5
6
7
8
9
public void dismiss()
//另外几个函数,这里不讲其意义,下篇细讲
public void setFocusable(boolean focusable)

public void setTouchable(boolean touchable)

public void setOutsideTouchable(boolean touchable)

public void setBackgroundDrawable(Drawable background)

这几个函数里,这篇只会用到dismiss(),用于不需要的时候,将窗体隐藏掉。

基本组件

Activity

生命周期

典型情况下生命周期

https://img-blog.csdn.net/20180610102358370

(1)onCreate: 表示Activity正在被创建,做一些初始化动作,只在创建时调用一次。
(2)onStart: 表示Activity正在被启动,这时Activity已经可见,但不在前台,用户看不到也无法交互。
(3)onResume: 表示Activity已经可见,并出现在前台开始活动。
(4)onPause: 表示Activity正在停止,做一些快速的轻量级回收任务。因为新Activity的onResume方法要等当前Activity的onPause方法调用之后才会调用。此时用户回到原Activity的话,onResume方法会被调用,但在onPause方法停留时间极短,用户很难重现这一场景。当前Activity被部分遮挡时,如弹出一个弹窗,onPause方法被调用,onStop方法不被调用(这一情况经验证,没有看到onPause被调用)。
(5)onStop: 表示Activity即将停止,做一些快速的轻量级回收任务。Activity采用透明主题时,onStop方法不会被调用。
(6)onDestroy: 表示Activity即将被销毁,做一些回收工作和最终的资源释放,只调用一次。
(7)onRestart: 表示Activity正在重新启动,一般是在Activity从不可见变为可见时调用。区别于onStart方法,否则不能知道是正常流程还是从onPause方法恢复的。一般是用户行为导致的,如按Home键返回桌面,或者打开了一个新的Activity,然后又切换回原来的Activity。

(1)运行状态
当一个活动处于返回栈栈顶时,它就处于运行状态。极端情况下系统才会回收这种状态的活动,因为回收运行状态的活动,将会带来极差的用户体验。
(2)暂停状态
当一个活动不处于栈顶,且部分可见时(如在它之上有一个对话框显示),它处于暂停状态。一般情况下系统也是不愿意回收暂停状态的活动的,因为它仍旧部分可见,回收它,也会造成极差的用户体验。
(3)停止状态
当一个活动不处于栈顶,且完全不可见时,进入停止状态。这时系统仍然会为这种活动保存相应的状态和成员变量,但这是不安全的,因为当需要内存时,暂停状态的活动随时可能被回收。
(4)销毁状态
  当一个活动被移除返回栈后,它就进入了销毁状态。系统最倾向于回收这种状态的活动,以保证内存充足。

(1)完整生存期
活动在onCreate()到onDestroy()方法之间所经历的,就是完整生存期。一般情况下,一个活动会在onCreate()方法中完成各种初始化操作,在onDestroy()方法中完成释放内存的操作。
(2)可见生存期
活动在onStart()方法和onStop()方法之间所经历的,就是可见生存期。在可见生存期内,活动对于用户总是可见的,即使有可能无法和用户交互。我们可以通过这两个方法,合理地管理那些对用户可见的资源,如在onStart()方法中对资源进行加载,在onStop()方法中,对资源进行释放,从而保证处于停止状态的活动不会占用过多内存。
(3)前台生存期
活动在onResume()到onPause()之间的所经历的,就是前台生存期。在前台生存期内,活动总是处于运行状态,是可以与用户交互的。

standard模式正常回调过程:
onCreate –> onStart –> onResume –> Activity运行 –> onPause –> onStop –> onDestroy

onCreat-onDestroy对:
在Activity创建和销毁时调用,只调用一次。

onStart-onStop对:
可见不在前台时调用onStart方法,不可见且不在前台时调用onStop方法。随着用户操作或者屏幕亮灭,这两个方法可能会被多次调用。在onStop状态,让Activity重新回到前台,如果应用没有因为内存不足被杀死,那么调用
onRestart-> onStart->onResume->Activity运行。如果应用进程被系统杀死了,那么要从onCreate方法重新开始。

onResume-onPause对:
可见且在前台时调onResume方法,可见不在前台时调onPause方法。随着用户操作或者屏幕亮灭,这两个方法可能会被多次调用。在onPause状态,让Activity重新回到前台,那么只调用onResume方法,即onResume->Activity运行。

惯性:
onCreate->onStart->onResume->Activity运行,会按顺序执行到Activity运行。停止时会执行onPause->onStop,onDestroy方法用户操作时调用。(questionNo: onDestroy方法在结束进程时会调用吗?是惯性到onDestroy吗?answer: 手动结束应用进程时,会onPause->onStop,但不会调用onDestroy方法。 )

详情: https://blog.csdn.net/hystudio_lzu/article/details/80629571

Fragment

Fragement 概述

Fragement 与 Activity 生命周期关系 : Fragement 嵌入到 Activity 组件中才可以使用, 其生命周期与 Activity 生命周期相关.

stop 与 destroy 状态 : Activity 暂停 或者 销毁的时候, 其内部嵌入的所有的 Fragement 也会执行 暂停 或者 销毁 操作;

活动状态: 只有当 Activity 处于活动状态的时候, 我们才能操作 Fragement;

Fragement 特征 :

  • Fragement 与 Activity 交互 : Fragement 调用 getActivity() 获取其 所嵌入的 Activity, Activity 获取 FragementManager 的findFragementById() 或 findFragementByTag() 获取 Fragement;

  • Activity 增删 Fragement : Activity 调用 Fragement 的 add(), remove(), replace() 等方法 添加 删除 替换 Fragement;

  • Fragement 与 Activity 对应关系 : 一个 Activity 中可以嵌入多个 Fragement, 一个 Fragement 可以嵌入多个 Activity;

-生命周期受 Activity 影响: Fragement 的生命周期 受 Activity 生命周期控制;

Fragement 作用 : Fragement 是为了 Android 中 平台电脑 UI 设计, 开发者不用设计 非常负责的 界面, 只需要设计好模块, 对UI 组件进行分组和 模块化的设计和开发, 简化了 UI 组件;

Fragement 可复用性 : 同一个 app 应用, 可以在不同的 Activity 中加载同一个 Fragement;

Fragement 类 和 方法介绍
Fragement 相关类介绍

Fragement 子类 :

DialogFragement : 对话框界面的 Fragement, 显示一个浮动的对话框, 这个对话框可以方便的与 Activity 进行交互, Activity 可以管理这个 Fragment;

  • ListFragement : 列表界面的 Fragement, 显示一个条目列表, 该列表可以设置一个适配器, 提供了许多管理 列表的函数;

  • PerformanceFragement : 选项设置界面的 Fragement, 该Fragment 创建 类似与 设置 应用程序时很管用;

  • WebViewFragement : WebView 界面的 Fragement;

Fragement 生命周期相关方法介绍

onCreate() :

1
onCreate(Bundle savedInstanceState) 
  • 回调时机 : 在创建 Fragement 的时候回调;

  • 参数解析 : Bundle savedInstance, 用于保存 Fragment 参数 , Fragement 也可以 重写 onSaveInstanceState(Bundle outState) 方法, 保存Fragement状态;

  • 执行的动作 : 获取 Frgement 显示的内容, 以及 启动Fragment 传入的参数 , 调用 getArguments() 获取键值对;

onCreateView() :

1
onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState); 
  • 回调时机 : Fragement 绘制界面组件 的时候回调, 该方法返回 View, 这个View就是 Fragement 本身;

  • 参数解析 : inflater 布局加载器, 是上下文传入, 不用自己创建; container 加载组件的父容器;

  • 执行的操作 : 使用 inflate 布局加载器 加载布局文件, 并未组件设置显示的值 ;

onPause() :

  • 回调时机 : Fragement 暂停的时候, 即进入后台的时候 回调;

Fragment 创建

Fragment 创建 :

  • 参数准备 : 创建一个 Bundle 对象, 并向其中设置参数 :
1
2
Bundle bundle = new Bundle();  
bundle.putString("key", "value");
  • 创建 Fragment 对象 : 使用 new MyFragment() 创建对象, 并 调用 myFragment.setArguments(bundle) 方法传入参数;
  1. MyFragment myFragment = new MyFragment();
  2. myFragment.setArguments(bundle);

Fragment嵌入Activity方式 : Fragment 添加到 Activity 中才能显示, 以下是将 Fragment 嵌入 Activity 的方式;

  • 布局文件嵌入 : 在布局文件中 使用元素, 通过定义 android:name = “com.example.MyFragment” 属性指定 Fragment 类;

  • 代码方式嵌入 : 调用 FragmentTransaction 对象的 add() 方法向 Activity 中添加 Fragment;

Fragment 与 Activity 通信

Fragment 获取 Activity : 调用 Fragment 对象的 getActivity()方法, 即可获取 Fragment 嵌入的 Activity 对象;

Activity 获取 Fragment :

  • Fragment 属性 : 在布局文件中, 可以为元素指定 android:id 和 android:tag 属性;

  • 获取方法 : 调用 Activity 的 findFragmentById(int id) 或者 findFragmentByTag(String tag)方法;

Fragment 向 Activity 传递数据 : 将 Activity 当作 接口子类对象 , Fragment 中调用 Activity 中的接口方法;

  • Fragment 定义接口 : 在 Fragment 内部定义一个 Callback 接口 ;

  • Activity 实现该接口 : MyActivity extends Activity implement MyFragment.Callback ;

  • Fragment 中获取该接口对象 : 在Fragment 中定义一个 Callback 全局变量, 然后在 onAttach(Activity activity) 方法中, 将 activity 强转为 Callback 对象 ;

  • 调用接口方法 : 上面获取了 Callback 对象, 即Activity对象, 调用 Activity 中的 接口方法 , 就能在 Fragment 中调用 Activity 对应的方法了;

Activity 向 Fragment 传递数据 :

  • 创建 Bundle 数据包 : 创建一个 Bundle 对象, 把要存放的键值对 放到这个对象中;

  • 设置 Bundle 对象给 Fragment : 调用 Fragment 对象的 setArguments(Bundle bundle) 方法, 将 Bundle 对象设置给 Fragment;

Fragment 事务管理

FragmentManager 功能 : FragmentManager 对象 可以通过 activity.getFragmentManager()获取;

  • 获取指定 Fragment : 通过 findFragmentById() 或者 findFragmentByTag() 方法获取指定 Fragment;

  • 弹出栈 : 通过调用 popBackStack(), 将 Fragment 从后台的 栈 中弹出;

  • 监听栈 : 通过调用 addOnBackStackChangeListener 注册监听器, 监听 后台栈变化;

FragmentTransaction 对象获取途径 :

  • 获取 FragmentManager 对象 : 调用 Activity 的 getFragmentManager() 获取 FragmentManager 对象;

  • 获取 FragmentTansaction 对象 : 调用 FragmentManager 对象的 beginTransaction() 方法获取 FragmentTransaction 对象;

FragmentTransaction(Fragment 事务)作用 : 对 Fragement 进行 增, 删 , 改 操作需要 FragmentTransaction 对象进行操作, 开启 这个事务, 获取 事务对象, 然后执行对 Fragment 的操作, 最后提交事务;

  • 开启事务 : 调用 Fragement 对象的 beginTransaction() 方法可以获取 FragementTransaction 对象;

  • 操作碎片 : FragmentTransaction 对象 中 包含了 add(), remove(), replace() 等方法;

  • 提交操作 : 当执行完 Fragement 的操作之后, 可以调用 FragementTransaction 对象的 commit() 方法提交修改;

addToBackStack()方法作用 : 该方法是 FragementTransaction 的方法, 在提交事务前调用该方法, 可以将 事务中执行的操作 添加到 back 栈中, 用户按下 回退键, 修改过的 Fragement 会 回退到 事务执行之前的状态 ;

Fragment 生命周期
Fragment 状态

活动状态 : Fragment 处于前台, 可见 , 可以获取焦点 ;

暂停状态 : Fragment 嵌入的Activity 也处于暂停状态, 即 Fragment 处于后台, 可见 , 失去焦点 ;

停止状态 : Fragement 嵌入的 Activity 处于停止状态, 不可见 , 失去焦点 ;

销毁状态 : Fragement 所在的 Activity 被销毁, 执行了 onDestroy() 方法, 此时 Fragement 被 完全删除 ;

Fragement 生命周期相关方法

https://img-blog.csdn.net/20140802132139900

红色方法 与 Activity 相对应, 蓝色方法 是 自身对应的方法, 棕色方法 单独对应;

onAttach() : 嵌入, Fragement 被嵌入到 Activity 时回调该方法, 只会调用一次;

onCreate() : 创建, Fragement 创建的时候回调该方法, 只会回调一次;

onCreateView() : 绘制, 在 Fragement 绘制的时候回调该方法, 该方法会返回 绘制的 View 组件;

onActivityCreated() : 界面创建, Fragement 所嵌入的 Activity 创建完成回调该方法;

onStart() : 启动, Fragement 启动时回调, 此时Fragement可见;

onResume() : 激活, Fragement 进入前台, 可获取焦点时激活;

onPause() : 暂停, Fragement 进入后台, 不可获取焦点时激活;

onStop() : 停止, Fragement 不可见时回调;

onestroyView() : 销毁组件, 销毁 Fragement 绘制的 View 组件时回调;

onDestroy() : 销毁, 销毁 Fragement 回调;

onDetach() : 移除, Fragement 从 Activity 中移除的时候回调;

https://blog.csdn.net/dai_zhenliang/article/details/38554273