封面画师:画师JW     封面ID:77038942

Android简介

​ 安卓是一种基于Linux内核(不包含GNU组件)的自由及开放源代码的操作系统。主要使用于移动设备,如智能手机和平板电脑,由Google公司和开放手机联盟领导及开发。Android操作系统最初由Andy Rubin开发,主要支持手机。2005年8月由Google收购注资。2007年11月,Google与84家硬件制造商、软件开发商及电信营运商组建开放手机联盟共同研发改良Android系统。随后Google以Apache开源许可证的授权方式,发布了Android的源代码。

​ Android一词的本义指“机器人”,同时也是Google于2007年11月5日宣布的基于Linux平台的开源手机操作系统的名称,该平台由操作系统、中间件、用户界面和应用软件组成。

​ Android一词最早出现于法国作家利尔亚当(Auguste Villiers de l’Isle-Adam)在1886年发表的科幻小说《未来夏娃》(L’ève future)中。他将外表像人的机器起名为Android。

​ Android的Logo是由Ascender公司设计的,诞生于2010年,其设计灵感源于男女厕所门上的图形符号,于是布洛克绘制了一个简单的机器人,它的躯干就像锡罐的形状,头上还有两根天线,Android小机器人便诞生了。其中的文字使用了Ascender公司专门制作的称之为“Droid ” 的字体。Android是一个全身绿色的机器人,绿色也是Android的标志。颜色采用了PMS 376C和RGB中十六进制的#A4C639来绘制,这是Android操作系统的品牌象徵。有时候,它们还会使用纯文字的Logo。

内容摘录于百度百科——Android

Android Studio

Android Studio 是开发 Android 应用程序的官方 IDE,基于 Intellij IDEA。

删除一个Module的方法:选中要删除的Module > Open Module Settings > 选中要删除的Module,然后点击"-" > 坚持磁盘目录下文件是否被删除,如果没有,删除即可。

java节点

  • 如果创建项目后,R文件生成失败被标红处理:

解决:Build —> Clean Project

  • Android Studio卡在“Waiting for target device to come online”:

后续补充:

这些方法没啥卵用,不用看了,可以试试选用Target不带有Google字样的x64模拟器。

解决:每种解决都可以试一下!!参考链接

  1. 将镜像改成x86_64然后新建一个模拟器。
  2. 打开AVD manager找到自己的模拟器,然后右击模拟器,选择Cold Boot Now,模拟器打开并提示一行信息,直接dismiss。
  3. 重启AS,重启系统。(注意:如果你是Win10 系统,重启的时候记得按住 shift 来禁用系统的强制签名)
  4. paltform-tools目录下adb kill-server,然后adb start-server。
  5. SDK tool 或paltform tool有更新,下载更新。
  6. 删除<Your_AVD_Directory>.android\avd\Pixel_XL_API_28.avd目录下.lock文件,然后重新载入。
  7. 打开AVD manager,选中模拟器,右击,wipe data,然后启动模拟器。

res节点

drawable目录

主要用于放置位图文件(PNG,JEPG或者GIF)、9-Patch图片文件、Shape Drawable、Drawable对象等XML资源文件。图片命名不能大写!!

layout目录

用于存储安卓的布局文件。

布局文件就是用于控制窗口中显示哪些内容。

mipmap目录

创建项目后会创建多个子目录(mipmap-mdpi、mipmap-hdpi、mipmap-xhdpi、mipmap-xxhdpi、mipmap-xxxhdpi)。用于储存不同分辨率的启动图标文件。

drawable和mipmap的区别:

  1. 9-Patch图片和Shape资源文件只能放在drawable目录中;
  2. 需要适应屏幕分辨率的图片推荐放在mipmap目录中,可以提高显示性能、占用内存更少;

values目录

主要用于保存字符串资源、样式资源、尺寸资源、颜色资源。

UI布局

View

我们一般不直接使用View类,而是使用View类的子类(比如TextView)。

View类位于android.view包中;View类的子类一般都用于android.widget包中。

常用属性:

  • android:id 为组件设置唯一标识
1
android:id = "@+id/user"
  • android:background 为组件设置背景(可以是图片资源也可以是颜色)
1
android:background = "@mipmap/bg"		//bg为图片资源名称,需要将资源放置于mipmap目录下
  • android:padding 为组件四周设置一样的内边距

衍生属性:

android:paddingLeftandroid:paddingTopandroid:paddingRightandroid:paddingBottom

API 17以后:

android:paddingStart = android:paddingLeft

android:paddingEnd = android:paddingRight

ViewGroup

理解:若将View比作成整个窗户,那么ViewGroup就是窗户框。用于控制View如何摆放。

实际使用中经常使用ViewGroup的子类,如RelativeLayout、LinearLayout等。

ViewGroup控制其子组件分布时依赖的内部类:

ViewGroup.LayoutParams类和ViewGroup.MarginLayoutParams类。

ViewGroup.LayoutParams常用于设置布局高度和宽度。

  • 属性:android:layout_heightandroid:layout_width

  • 属性值:除了可以使用具体的值以外,还可以使用

    FILL_PARENT:根据父容器进行计算,API 8以后 开始将其修改为MATCH_PARENT。

    MATCH_PARENT:根据父容器进行计算

    WRAP_PARENT:根据组件内的内容进行计算

ViewGroup.MarginLayoutParams用于控制子组件的外边距。

  • 属性:android:layout_marginTopandroid:layout_marginBottomandroid:layout_marginLeftandroid:layout_marginRight

    API 17 以后:

    android:layout_marginStart = android:layout_marginLeft

    android:layout_marginEnd = android:layout_marginRight

  • 属性值:通过尺寸变量或具体的值进行设置。

Android UI 组件的层次结构

所有的UI界面都是由View类、ViewGroup类或其子类组合而成的。

ViewGroup中可以包含多个View和ViewGroup,其中的ViewGroup又可以包含多个View和ViewGroup…

禁止套娃!!

控制UI界面

方法:使用XML布局文件控制UI界面(推荐)、在Java代码中控制UI界面、使用XML和Java代码混合控制UI界面、开发自定义的View。

使用XML布局文件控制UI界面

  1. 在Android应用的res/layout目录下编写XML布局文件(如activity_main.xml)
  2. 在Activity中使用以下Java代码显示XML文件中布局的内容
1
setContentView(R.layout.activity_main);

android:layout_gravity 用来设置该view相对与父view 的位置,比如值为center将该view置于父view中间。

RelativeLayout

RelativeLayout:相对布局管理器

1
<RelativeLayout></RelativeLayout>

使用相对布局需要一个参考点,所有的组件以参考点的位置为基准。

如果有根据组件间的相对位置来控制组件的摆放 的设计需求,那么此时就可以使用相对布局。

部分属性参考ViewGroup ,其他属性:

android:gravity 用于设置布局管理器中各个子组件的摆放方式

android:ignoreGravity 指定哪个子组件不受android:gravity的影响

  • 属性值为组件ID。

RelativeLayout.LayoutParams

属性:相对布局管理器组件上设置的属性,而不是布局管理器上设置的属性。

  • 组件相对于参考组件的位置:
属性名 作用
android:layout_above 上方
android:layout_below 下方
android:layout_toLeftOf 左方
android:layout_toRightOf 右方
  • 组件与布局管理器(父容器)哪边对齐:
属性名 作用
android:layout_alignParentBottom 底部对齐
android:layout_alignParentLeft 左对齐
android:layout_alignParentRight 右对齐
android:layout_alignParentTop 顶部对齐
  • 组件与哪个组件的上、下、左、右边界对齐:
属性名 作用
android:layout_alignBottom 底部对齐
android:layout_alignLeft 左对齐
android:layout_alignRight 右对齐
android:layout_alignTop 顶部对齐
  • 设置组件位于布局管理器的哪个位置:
属性名 作用
android:layout_centerHorizontal 位于水平居中
android:layout_centerInparent 位于中间位置
android:layout_centerVertical 位于垂直居中

LinearLayout

LinearLayout:线性布局管理器

1
<LinearLayout></LinearLayout>

将放入其中的组件按照水平或垂直的方向进行排列。

若其内部组件一个挨着一个(按行或列)排列到屏幕的边缘以后,剩下的组件将不会显示出来。

本身属性

android:orientation 设置线性布局内组件的排列方式

1
2
3
//属性值:仅有两个 
horizontal: 水平方向
vertical: 垂直方向

android:gravity 设置线性布局内组件的显示位置

属性值之间可以使用|分割,达到组合的效果,如:

1
android:gravity = "right|bottom"	//使布局管理器位于右下角

子组件属性

android:layout_weight 设置子组件所占的权重,即:组件占父容器剩余空间 的比例 默认值为0

layout_weight

gravitylayout_gravity 的不同处

gravity是设置控件自身内部元素的对齐方式。比如一个TextView,则是设置内部文字的对齐方式。如果是ViewGroup组件如LinearLayout的话,则为设置它内部view组件的对齐方式。

layout_gravity是设置控件自身相当于父容器的对齐方式。比如,一个TextView设置layout_gravity属性,则表示这TextView相对于父容器的对齐方式。

FrameLayout

FrameLayout:帧布局管理器

1
<FrameLayout></FrameLayout>

帧布局容器为每个加入其中的组件创建一个空白的区域 (称为一 ),每个子组件占据一帧,默认是把他们放在这块区域的左上角 ,但是我们也可以通过layout_gravity属性 ,指定到其他的位置。

帧布局会把组件按先后顺序一个一个地叠加在一起,上层的组件会覆盖底层的组件不能 将底层的帧移到上层。

帧布局的大小由组件中最大的子组件决定 ,如果每个组件的大小一样大的话,那么同一时刻只能看到最上面的那个组件。

本身属性

前景图像:始终位于最上层的图像,其他组件无法将它盖住

android:foreground 为当前的帧布局管理器设置一个前景图像

属性值常为图片资源。

android:foregroundGravity 设置前景图像的位置

属性值之间可以使用|分割,达到组合的效果,如:

1
android:foregroundGravity = "right|bottom"	//使前景图像位于右下角

TableLayout

TableLayout:表格布局管理器

1
<TableLayout></TableLayout>

表格布局由TableLayout类代表,其会采用行、列的形式来管理UI组件。

TableLayout通过添加TableRow、其它组件来控制表格的行数和列数,而不需要明确地声明包含多少行、多少列。

每次向TableLayout中添加一个TableRow,该TableRow就是一个表格行,TableRow也是容器,因此它也可以不断地添加其它组件,每添加一个子组件该表格就增加一列。若直接向TableLayout中添加组件,那么这个组件将直接占用一行

在表格布局中,列的宽度由该列中最宽的那个单元格决定,整个表格布局的宽度则取决于父容器的宽度(默认总是占满父容器本身)。

列单元格常用的三种行为方式:

  • Shrinkable。该列的所有单元格的宽度可以被收缩,以保证该表格能适应父容器的宽度
  • Stretchable。该列的所有单元格的宽度可以被拉伸,以保证组件能完全填满表格空余空间
  • Collapsed。该列的所有单元格会被隐藏
1
2
3
4
5
6
7
8
9
<!--定义一个表格布局,指定第2列允许收缩,第3列允许拉伸,第4列允许隐藏。-->
<!--列数是从0开始的-->
<TableLayout
android:id="@+id/tableLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:shrinkColumns="1"
android:stretchColumns="2"
android:collapseColumns="3">

GridLayout

GridLayout:网格布局管理器

1
<GridLayout></GridLayout>

GridLayout 布局是 Android 4.0 以后引入的新布局,和 TableLayout(表格布局) 有点类似,不过它功能更多,也更加好用:

  • 可以自己设置布局中组件的排列方式
  • 可以自定义网格布局有多少行,多少列
  • 可以直接设置组件位于某行某列
  • 可以设置组件横跨几行或者几列

本身属性

android:columnCount 指定网格最大列数

android:orientation 与线性布局属性一样,默认采用水平排列

android:rowCount 指定网格的最大行数

GridLayout .LayoutParams

属性:网格布局管理器组件上设置的属性,而不是布局管理器上设置的属性。

这些属性可以控制网格布局管理器上各子组件的分布。

属性名 含义
android:layout_column 指定子组件位于网格的第几列
android:layout_columnSpan 指定子组件横向跨几列
android:layout_columnWeight 指定子组件在水平方向上的权重
android:layout_gravity 指定子组件以什么方式占据网格空间
android:layout_row 指定子组件位于网格的第几行
android:layout_rowSpan 指定子组件纵向跨几行
android:layout_rowWeight 指定子组件在垂直方向上的权重
1
2
3
4
5
<!--从0开始计算,与表格布局类似-->
<!--设置组件位于第二行-->
android:layout_row = "1"
<!--设置组件位于第三列-->
android:layout_column = "2"

布局管理器的嵌套

嵌套原则

  1. 根布局管理器必须包含xmlns属性;
  2. 在一个布局文件中,最多只能有一个根布局管理器,如果需要有多个还需要使用一个根布局管理器将它们括起来;
  3. 不能嵌套地太深,如果嵌套太深,会影响性能。

不能套娃太深!!

基本UI组件

使用UI组件时注意字母的大小写!

使用UI组件时注意字母的大小写!

使用UI组件时注意字母的大小写!

文本框组件

1
<TextView />

属性

android:text 设置文本框中要显示的内容。

属性值为字符串资源(res/values/string.xml 进行设置)名称。

1
android:text = "@string/demo"		//字符串资源名为demo

android:textSize 设置字体大小,单位为sp

android:textColor 设置字体颜色

android:singleLine 设置文本框单行显示文字 属性值为true时,则单行显示

跑马灯——使用TextView内的属性实现

1
2
3
4
5
6
7
8
9
10
11
12
<!--激活焦点,必须-->
android:focusable="true"
<!--单行显示,必须-->
android:singleLine="true"
<!--这里设置为超出文本后滚动显示,必须-->
android:ellipsize="marquee"
<!--TouchMode模式的焦点激活,必须-->
android:focusableInTouchMode="true"
<!--这个是设置滚动几次,这里是无限循环-->
android:marqueeRepeatLimit="marquee_forever"
<!--横向超出后是否有横向滚动条-->
android:scrollHorizontally="true"

除了添加这些属性外,还需要在对应的Activity中添加:

1
2
3
4
5
6
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView textView = findViewById(R.id.tv);
textView.setSelected(true); //必须
}

这只是简单实现页面中单个跑马灯,如果界面中有EditText等能获取焦点的组件时,这种方法会失效。具体操作可以参考:Android之跑马灯详解

编辑框

1
<EditText />

它是文本框组件的子类。

属性

android:hint 设置默认提示内容,属性值为字符串

android:inputType 设置输入内容类型,如:

1
2
android:inputType = "textPassword"	<!--设置输入类型为密码-->
android:inputType = "number" <!--设置输入类型为数字-->

android:drawableLeft 在编辑框左侧绘制一个图像,常用于图标的设置,属性值为图片资源,如:

1
android:drawableLeft = "@mipmap/mr"	<!--mr为图片资源名-->

android:drawableStart 在API 17后,android:drawableStart等同于android:drawableLeft的使用。

android:drawableBottom 在文字底部绘制图像

android:drawableRight 在文字右侧绘制图像

android:drawableEnd 在API 17后,android:drawableEnd等同于android:drawableRight的使用。

android:drawableTop 在文字顶部绘制图像

android:drawablePadding 设置文字与图像之间的距离,单位dp

android:lines 设置编辑框的最大行数,当超过设置的数值时,自动向上滚动

获取编辑框组件内容

首先需要给编辑框组件设置一个id,假设设置id为et,则在Activity中有:

1
2
3
4
5
protected void onCreate(Bundle saveInstanceState){
...
EditText et = findViewById(R.id.et);
et.getText(); //这样就可以获取到编辑框中的内容
}

普通按钮

1
<Button />

它是文本框组件的子类。

为普通按钮添加点击事件监听器

  • 匿名内部类作为点击事件监听器

首先需要给按钮设置一个id,假设设置id为btn,则在Activity中有:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
protected void onCreate(Bundle savedInstanceState) {
...

//根据Button ID绑定Button
Button mButton = findViewById(R.id.btn);
//按钮点击监听器
mButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//单击按钮后短时间内显示消息提示框
Toast.makeText(MainActivity.this, "单击了按钮", Toast.LENGTH_SHORT).show();
}
});
}
  • 通过onClick属性实现
  1. 在Activity中编写一个包含View类型参数的方法。
1
2
3
4
public void myClick(View view){
//编写要执行的动作代码
Toast.makeText(MainActivity.this, "单击了按钮", Toast.LENGTH_SHORT).show();
}
  1. android:onClick属性指定为步骤(1)中的方法名。
1
android:onClick = "myClick"

图片按钮

1
<ImageButton />

ImageButton和Button的异同:

相同点:

  • 单击时都可以触发onClick事件。即:使用它们两个都可以生成一个可供点击的按钮,且点击时都会触发onClick事件。

不同点:

  • ImageButton没有android:text属性,而Button有。Button上的文字是在代码中指定的,而ImageButton上的文字是在制作图片时加上去的。

基本使用(属性)

android:src设置按钮要显示的图片,属性值为图片资源。假设图片名称为img且在mipmap目录下:

1
android:src = "@mipmap/img"

android:background 为图片按钮设置一个背景。为图片按钮设置透明背景:

1
android:background = "#0000"

全屏显示

设置界面全屏显示:

1
2
3
4
5
6
protected void onCreate(Bundle savedInstanceState) {
...
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
...
}

单选按钮

1
<RadioButton />

基本使用(属性)

android:text 给单选按钮旁设置说明性文字

android:checked 设置单选按钮为默认选中状态 属性值为true,则表示为默认选中。

设置单选按钮组,并获取单选按钮组中选中项的值

如果我们需要设置单选按钮组,我们需要使用<RadioGroup></RadioGroup>将单选按钮们包裹起来:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<RadioGroup
android:id="@+id/radio_1"
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="女"/>
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="保密"/>
</RadioGroup>
  • 通过选中单选按钮来获取单选按钮组选中项的值

前提是需要给RadioGroup设置一个id,然后在对应的Activity中编写:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
RadioGroup radioGroup;
@Override
protected void onCreate(Bundle savedInstanceState) {
...
//根据radioGroup ID绑定radioGroup
radioGroup = findViewById(R.id.radio_1);
//获取单选按钮内容
radioGroup.setOnCheckedChangeListener(new RadioGroup
.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
RadioButton radioButton = findViewById(checkedId);
CharSequence text = radioButton.getText();
Toast.makeText(MainActivity.this,"性别:"+text,
Toast.LENGTH_LONG).show();
}
});
}
  • 通过其他按钮获取单选按钮组选中的单选按钮的值

添加其他按钮,并设置属性:

1
2
3
4
5
6
<Button
android:id="@+id/btn_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="提交"
/>

在对应的Activity中进行编写:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
RadioGroup radioGroup;
protected void onCreate(Bundle savedInstanceState) {
...
radioGroup = findViewById(R.id.radio_1);
Button btn_1 = findViewById(R.id.btn_1);
btn_1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
for (int i = 0;i <radioGroup.getChildCount();i++){
RadioButton r = (RadioButton) radioGroup.getChildAt(i);
if (r.isChecked()){ Toast.makeText(MainActivity.this,r.getText(),Toast.LENGTH_LONG).show();
//当已经找到选中的单选按钮后就跳出循环,提高程序效率
break;
}
}
}
});
}

复选框

1
<CheckBox />

使用(本身属性)

设置多个复选框只需要使用多个<CheckBox />即可

android:text 给复选框旁设置说明性文字

android:checked 设置复选框为默认选中状态 属性值为true,则表示为默认选中。

获取选中的复选框的值

首先需要给要获取值的复选框设置id:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<CheckBox
android:id="@+id/box_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="唱"
/>
<CheckBox
android:id="@+id/box_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="跳"
/>
<CheckBox
android:id="@+id/box_3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="rap"
/>

在对应的Activity中绑定点击响应:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
CheckBox checkBox_1;
protected void onCreate(Bundle savedInstanceState) {
...
//根据id绑定一个复选框 box_1
checkBox_1 = findViewById(R.id.box_1);
checkBox_1.setOnCheckedChangeListener(new CompoundButton.
OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
if (checkBox_1.isChecked()){
//当box_1被选中后,短暂弹出带有复选框值的提示框
Toast.makeText(MainActivity.this,checkBox_1.getText(),
Toast.LENGTH_SHORT).show();
}
}
});
}

日期选择器

1
<DatePicker />

常将日期选择器的长宽设置成根据父容器变化。

如果添加日期选择器后发现日期没有显示完全,应该进入对应的Activity中修改继承的类

将其修改为:Activity而不是默认的AppCompatActivity

选择日期后,相应的给出我们选择的日期

1
2
3
4
<DatePicker
android:id="@+id/datePicker_1"
android:layout_width="match_parent"
android:layout_height="match_parent"/>

这里的Activity继承的是Activity,而不是AppCompatActivity。

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
public class DatepickerActivity extends Activity {
int year, month, day;
DatePicker datePicker;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_datepicker);
datePicker = findViewById(R.id.datePicker_1);
Calendar calendar = Calendar.getInstance();
year = calendar.get(Calendar.YEAR);
month = calendar.get(Calendar.MONTH);
day = calendar.get(Calendar.DAY_OF_MONTH);
datePicker.init(year, month, day, new DatePicker.OnDateChangedListener() {
@Override
public void onDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
DatepickerActivity.this.year = year;
DatepickerActivity.this.month = month;
DatepickerActivity.this.day = day;
show(year,monthOfYear, dayOfMonth);
}
});
}

private void show(int year, int month, int day) {
String str = year + "年" + (month + 1) + "月" + day + "日";
//选择日期后弹出显示日期的提示框
Toast.makeText(DatepickerActivity.this, str, Toast.LENGTH_SHORT).show();
}
}

时间选择器

1
<TimePicker />

常将日期选择器的长宽设置成根据父容器变化。

选择时间后,相应的给出我们选择的时间

1
2
3
4
<TimePicker
android:id="@+id/timePicker_1"
android:layout_width="match_parent"
android:layout_height="match_parent" />
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class TimepickerActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_timepicker);
TimePicker timePicker = findViewById(R.id.timePicker_1);
//设置时间为24小时制
timePicker.setIs24HourView(true);
timePicker.setOnTimeChangedListener(new TimePicker.OnTimeChangedListener() {
@Override
public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {
String str = hourOfDay + "时" + minute + "分";
//选择时间后弹出显示时间的提示框
Toast.makeText(TimepickerActivity.this, str, Toast.LENGTH_SHORT).show();
}
});
}
}

计时器

1
<Chronometer />

它是文本框组件的子类。

计时器默认的样式是 时:分:秒

如果我们想自定义时间格式,我们可以通过android:format属性进行设置。

%s表示时:分:秒的计时器格式

1
android:format = "已用时间:%s"

计时器所需要的方法

方法名 含义
setBase() 设置计时器的起始时间
setFormat() 设置显示时间的格式
start() 指定开始计时
stop() 指定停止时间
setOnChronometerTickListener() 为计时器绑定事件监听器,当计时器改变时触发该监听器

编写一个计数器

1
2
3
4
<Chronometer
android:id="@+id/chronometer_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class ChronometerActivity extends AppCompatActivity {
Chronometer chronometer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chronometer);
chronometer = findViewById(R.id.chronometer_1);
chronometer.setBase(SystemClock.elapsedRealtime());
chronometer.setFormat("%s");
chronometer.start();
chronometer.setOnChronometerTickListener(new Chronometer.
OnChronometerTickListener() {
@Override
public void onChronometerTick(Chronometer chronometer) {
//设置1分钟计时器
if (SystemClock.elapsedRealtime() - chronometer.getBase() >= 60000){
chronometer.stop();
}
}
});
}
}

高级UI组件

使用UI组件时注意字母的大小写!

使用UI组件时注意字母的大小写!

使用UI组件时注意字母的大小写!

进度条

1
<ProgressBar />

安卓提供了两种进度条模式:水平进度条和圆形进度条。默认是圆形进度条。

属性

style 设置进度条的样式。

通过主题属性进行设置,如:

属性值 含义
?android:attr/progressBarStyleHorizontal 细水平长条进度条
?android:attr/progressBarStyleSmall 小圆形进度条
?android:attr/progressBarStyleLarge 大圆形进度条

通过安卓给我定义的样式资源进行设置,如:

属性值 含义
@android:style/Widget.ProgressBar.Horizontal 粗水平长条进度条
@android:style/Widget.ProgressBar.Large 旋转画面的大圆形进度条
@android:style/Widget.ProgressBar.Small 旋转画面的小圆形进度条

android:max 设置进度条的最大值,属性值为具体数值,如:100

android:progress 设置进度条当前进度,属性值为具体数值,如:50

进度条更新流程:

进度条更新流程

模拟进度,实现进度条更新

1
2
3
4
5
6
7
8
<ProgressBar
android:id="@+id/progressBar_1"
style="@android:style/Widget.ProgressBar.Horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="100"
android:layout_alignParentBottom="true"
android:layout_marginBottom="50dp"/>
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
public class MainActivity extends AppCompatActivity {
private ProgressBar progressBar;
private int mProgress;
private Handler mHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
progressBar = findViewById(R.id.progressBar_1);
mHandler = new Handler(){
@Override
public void handleMessage(@NonNull Message msg) {
if (msg.what == 0x111){ //耗时操作未完成
progressBar.setProgress(mProgress);
}else {
Toast.makeText(MainActivity.this, "耗时操作已完成!", Toast.LENGTH_SHORT).show();
progressBar.setVisibility(View.GONE); //设置进度条消失
}
}
};
//模拟耗时操作
new Thread(new Runnable() {
@Override
public void run() {
while (true){
mProgress = doWork();
Message message = new Message();
if (mProgress < 100){
message.what = 0x111; //耗时操作未完成
mHandler.sendMessage(message);
}else {
message.what = 0x110; //耗时操作已完成
mHandler.sendMessage(message);
break;
}
}
}
//模拟进度条更新
private int doWork(){
mProgress += Math.random()*10;
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
return mProgress;
}
}).start();
}
}

拖动条

1
<SeekBar />

它是进度条的子类。

属性

由于它是进度条的子类,因此它可以使用进度条<ProgressBar />的属性,除此之外:

android:thumb 设置拖动条的拖动按钮的样式,属性值可以是我们自定义的图片资源,也可以是安卓给我们提供的值。

拖动拖动条按钮,界面内容实时改变

1
2
3
4
5
6
<SeekBar
android:id="@+id/seekbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="10"
android:progress="5" />
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
public class MainActivity extends AppCompatActivity {
SeekBar seekBar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
seekBar = findViewById(R.id.seekbar);
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
//进度条改变时执行 progress:当前进度
@Override
public void onProgressChanged(SeekBar seekBar,
int progress, boolean fromUser) {
Toast.makeText(MainActivity.this, "进度改变:"+progress, Toast.LENGTH_SHORT).show();
}
//当我们触摸拖动条按钮时执行
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
Toast.makeText(MainActivity.this, "开始触摸", Toast.LENGTH_SHORT).show();
}
//当我们停止触摸拖动条按钮时执行
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
Toast.makeText(MainActivity.this, "停止触摸", Toast.LENGTH_SHORT).show();
}
});
}
}

拓展:设置图片透明度可用setAlpha()方法进行设置,参数为透明度。安卓中透明度最高为255。

图像视图参考下文。

星级评分条

1
<RatingBar />

属性

android:numStars 设置星级评分条中星级的个数。默认星级是5。属性值为整型,如:8。

android:rating 设置点亮星级的个数。属性值为浮点型。

android:stepSize 设置每次评分的步长。属性值为浮点型。默认为0.5。

android:isIndicator 设置RatingBar是否是一个指示器,即用户能否更改星级。默认为false,表示用户可以更改。

获取用户的选中结果

1
2
3
4
5
6
7
<RatingBar
android:id="@+id/ratingbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:numStars="7"
android:rating="2"
android:stepSize="1"/>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class MainActivity extends AppCompatActivity {
RatingBar ratingBar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ratingBar = findViewById(R.id.ratingbar);
//获取星级评分(选中了几颗星)
String rating = String.valueOf(ratingBar.getRating());
Toast.makeText(MainActivity.this, "Rating:"+rating, Toast.LENGTH_SHORT).show();
//获取每次至少改变的星级
String stepSize = String.valueOf(ratingBar.getStepSize());
Toast.makeText(MainActivity.this, "stepSize:"+stepSize, Toast.LENGTH_SHORT).show();
//获取进度
String progress = String.valueOf(ratingBar.getProgress());
Toast.makeText(MainActivity.this, "progress:"+progress, Toast.LENGTH_SHORT).show();
}
}

图像视图

1
<ImageView />

属性

android:src 设置ImageView的内容,属性值是图片的地址。如:其中image1是图片名称

1
android:src="@drawable/image1
  • android:srcandroid:background的区别:
    • background通常指的都是背景,而src指的是内容
    • 当使用src填入图片时,是按照图片大小直接填充,并不会进行拉伸;而使用background填入图片,则是会根据ImageView给定的宽度来进行拉伸

<ImageView />是正方形的。

android:layout_widthandroid:layout_height设置布局宽度和高度。同时可以改变内部图片的大小,而且是等比例缩放,图片不会存在拉伸的情况。

android:scaleType 控制图片如何resized/moved来匹对ImageView的size。属性值:

ImageView.ScaleType / android:scaleType值的意义区别,将属性值转换成下划线分割的大写单词即可。

参考链接:点击查看

属性值 含义
center 按图片的原来size居中显示,当图片长/宽超过View的长/宽,则截取图片的居中部分显示
centerCrop 按比例扩大图片的size居中显示,使得图片长(宽)等于或大于View的长(宽)
centerInside 将图片的内容完整居中显示,通过按比例缩小或原来的size使得图片长/宽等于或小于View的长/宽
fitCenter 把图片按比例扩大/缩小到View的宽度,居中显示
fitEnd 把图片按比例扩大/缩小到View的宽度,显示在View的下部分位置
fitStart 把图片按比例扩大/缩小到View的宽度,显示在View的上部分位置
fitXY 把图片不按比例扩大/缩小到View的大小显示
matrix 用矩阵来绘制,动态缩小放大图片来显示。

android:adjustViewBounds 参考链接:参考链接1 参考链接2

官方表述:Adjust the ImageView’s bounds to preserve the aspect ration of its drawable. 解释:调整ImageView的界限来保持图片纵横比不变。

adjustViewBounds不管是设置成true还是false,都是不会影响图片本身的比例的(长/宽)!

实际上,adjustViewBounds影响的是ImageView的比例(不是图片的比例),所以,对于adjustViewBounds的定义应该是这样:

调整ImageView的边界,使得ImageView和图片有一样的长宽比例。

android:maxWidth/android:maxHeight 设置ImageView可以显示的最大宽/高,但是在Android中,只用当设置android:adjustViewBounds="ture"的时候,maxWidth/maxHeight设置效果才能有效。

adjustViewBounds="ture"的时候,会将这个ImageView的android:scaleType属性设置为fitCenter,但是如果同时在XML文件中设置android:scaleType,则android:scaleType的优先级会更高,adjustViewBounds="ture"中对android:scaleType属性设置将会失效。这种情况,只有在Java代码中设置setAdjustViewBounds(true)的时候,才会生效。

android:tint 安卓着色器。将图片渲染成指定的颜色。

图像切换器

1
<ImageSwitcher />

单击图片切换图片

1
2
3
4
5
<ImageSwitcher
android:id="@+id/imageswitcher"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</ImageSwitcher>
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
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final ImageSwitcher imageSwitcher = findViewById(R.id.imageswitcher);
//设置图片切换淡出
imageSwitcher.setOutAnimation(AnimationUtils.loadAnimation(MainActivity.this,android.R.anim.fade_out));
//设置图片进入
imageSwitcher.setInAnimation(AnimationUtils.loadAnimation(MainActivity.this,android.R.anim.fade_in));
//指定视图工厂
imageSwitcher.setFactory(new ViewSwitcher.ViewFactory() {
@Override
public View makeView() {
ImageView imageView = new ImageView(MainActivity.this);
imageView.setImageResource(R.drawable.image1);
return imageView;
}
});
//指定新的图片显示资源(单击图片切换图片)
imageSwitcher.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
((ImageSwitcher)v).setImageResource(R.drawable.image2);
}
});
}
}

实现左右滑动切换图片

1
2
3
4
5
6
<ImageSwitcher
android:id="@+id/imageswitcher"
android:layout_centerVertical="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</ImageSwitcher>

滑动动画文件,放置于res/anim目录下(anim需要自己新建):

向左推进:push_left_in.xml

1
2
3
4
5
6
7
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="100%p" android:toXDelta="0"
android:duration="500" />
<alpha android:fromAlpha="0.1" android:toAlpha="1.0"
android:duration="500" />
</set>

向左推出:push_left_out.xml

1
2
3
4
5
6
7
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="0" android:toXDelta="-100%p"
android:duration="500" />
<alpha android:fromAlpha="1.0" android:toAlpha="0.1"
android:duration="500" />
</set>

向右推进:push_right_in.xml

1
2
3
4
5
6
7
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="-100%p" android:toXDelta="0"
android:duration="500" />
<alpha android:fromAlpha="0.1" android:toAlpha="1.0"
android:duration="500" />
</set>

向右推出:push_right_out.xml

1
2
3
4
5
6
7
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="0" android:toXDelta="100%p"
android:duration="500" />
<alpha android:fromAlpha="1.0" android:toAlpha="0.1"
android:duration="500" />
</set>

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
public class MainActivity extends AppCompatActivity {
private int[] arrayPic = new int[]{R.drawable.image1,R.drawable.image2,
R.drawable.image3,R.drawable.image4};
private ImageSwitcher imageSwitcher;
private int index;
private float touchDownX;
private float touchUpX;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//设置全屏显示
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
imageSwitcher = findViewById(R.id.imageswitcher);
imageSwitcher.setFactory(new ViewSwitcher.ViewFactory() {
@Override
public View makeView() {
ImageView imageView = new ImageView(MainActivity.this);
imageView.setImageResource(arrayPic[index]);
return imageView;
}
});
//触摸图像切换器,实现图像的切换
imageSwitcher.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
//判断是否为按下
if(event.getAction() == MotionEvent.ACTION_DOWN){
touchDownX = event.getX();
return true;
}else if (event.getAction() == MotionEvent.ACTION_UP){ //判断是否为抬起
touchUpX = event.getX();
if (touchUpX - touchDownX > 100){ //从左往右(向右推)
index = index == 0?arrayPic.length - 1 : index - 1;
imageSwitcher.setInAnimation(AnimationUtils.loadAnimation(MainActivity.this,R.anim.push_right_in)); imageSwitcher.setOutAnimation(AnimationUtils.loadAnimation(MainActivity.this,R.anim.push_right_out));
imageSwitcher.setImageResource(arrayPic[index]);
}else if (touchDownX - touchUpX > 100){ //从右往左(向左推)
index = index == arrayPic.length - 1?0 : index + 1;
imageSwitcher.setInAnimation(AnimationUtils.loadAnimation(MainActivity.this,R.anim.push_left_in)); imageSwitcher.setOutAnimation(AnimationUtils.loadAnimation(MainActivity.this,R.anim.push_left_out));
imageSwitcher.setImageResource(arrayPic[index]);
}
return true;
}
return false;
}
});
}
}

网格视图

1
<GridView />

可应用于相册。

属性

android:numColumns 设置网格布局的列数。属性值可以为整形,也可以是自动排列:auto_fit

android:verticalSpacing 设置垂直间距,单位dp。

android:horizontalSpacing 设置水平间距,单位dp。

android:stretchMode="columnWidth" 缩放与列宽大小同步

android:columnWidth 设置列宽度,单位dp。

适配器

连接后端数据和前端显示的接口,是数据和UI组件的一个重要纽带。主要在View上显示(一般是ListView)。可以看作是界面数据绑定的一种理解。它所操纵的数据一般都是一些比较复杂的数据,如数组,链表,数据库,集合等。适配器就像显示器,把复杂的东西按人可以接受的方式来展现。

使用者:ListView、GridView、Spinner、Gallery、ViewPage等都需要使用适配器来为其设置数据源。

常用的适配器

建议花费一定量的时间学习适配器

ArrayAdapterSimpleAdapterSimpleCursorAdapter 这三个都是继承BaseAdapter,BaseAdapter是一个抽象类,需要子类继承并实现其中的方法才能使用,常用于用户自定义适配器时,显示比较复杂的数据。

ArrayAdapter数组适配器是Android中最简单的适配器,专门用于显示列表控件,只能展示一行字。

SimpleAdapter的扩展性最好,可以定义各种各样的布局,添加ImageView、Button、CheckBox等,可以自定义出各种效果。使用SimpleAdapter的数据用一般都是HashMap构成的List,list的每一节对应ListView的每一行。HashMap的每个键值数据映射到布局文件中对应id的组件上。

SimpleCursorAdapter可以认为是SimpleAdapter对数据库的简单结合,主要用来操作数据库。

BaseAdapter一般用于显示复杂的列表布局,由于BaseAdapter是一个抽象类,使用该类需要自己写一个适配器继承于该类,并重新一些方法。

适配器继承图:

适配器继承图

具体使用和参数意义参考下列链接。

参考链接: 参考链接1 参考链接2 参考链接3

实现网格视图

实现网格视图,使用SimpleAdapter

准备工作:在drawable目录中放入9张图片,并命名为image1 ~image9。

1
2
3
4
5
<GridView
android:id="@+id/gridview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:numColumns="3"/>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class MainActivity extends AppCompatActivity {
private int[] pic = new int[]{R.drawable.image1, R.drawable.image2,
R.drawable.image3, R.drawable.image4, R.drawable.image5,
R.drawable.image6, R.drawable.image7, R.drawable.image8,
R.drawable.image9};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
GridView gridView = findViewById(R.id.gridview);
List<Map<String, Object>> listitem = new ArrayList<Map<String, Object>>();
for (int i = 0; i < pic.length; i++) {
Map<String, Object> map = new HashMap<String, Object>();
map.put("image", pic[i]);
listitem.add(map);
}
SimpleAdapter simpleAdapter = new SimpleAdapter(this, listitem, R.layout.cell, new String[]{"image"}, new int[]{R.id.image});
gridView.setAdapter(simpleAdapter);
}
}

利用网格视图,实现相册界面,使用BaseAdapter

准备工作:在drawable目录中放入9张图片,并命名为image1 ~image9。

1
2
3
4
5
6
7
8
<GridView
android:id="@+id/gridview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:numColumns="auto_fit"
android:verticalSpacing="5dp"
android:columnWidth="100dp"
android:gravity="center"/>

这里的Activity继承的是Activity,而不是AppCompatActivity。

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
public class MainActivity extends Activity {
private int[] pic = new int[]{R.drawable.image1, R.drawable.image2,
R.drawable.image3, R.drawable.image4, R.drawable.image5,
R.drawable.image6, R.drawable.image7, R.drawable.image8,
R.drawable.image9};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
GridView gridView = findViewById(R.id.gridview);
gridView.setAdapter(new ImageAdapter(this));
}

public class ImageAdapter extends BaseAdapter {
private Context context;

public ImageAdapter(Context context) {
this.context = context;
}

@Override
public int getCount() {return pic.length;}

@Override
public Object getItem(int position) {return null;}

@Override
public long getItemId(int position) {return 0;}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
if (convertView == null) {
imageView = new ImageView(context);
//设置图像宽高
imageView.setLayoutParams(new GridView.LayoutParams(100, 90));
//设置图片缩放方式(保持纵横比缩放)
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
} else {
imageView = (ImageView) convertView;
}
//将获取的图片放入imageView
imageView.setImageResource(pic[position]);
return imageView;
}
}
}

下拉列表框

1
<Spinner />

属性

android:entries 为下拉列表框指定列表项,属性值为数组资源。

假设在res/values目录下创建了数组资源文件arrays.xml:

1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="ctype">
<item>全部</item>
<item>电影</item>
<item>图书</item>
<item>游戏</item>
</string-array>
</resources>

则在布局文件中有:

1
2
3
4
5
<Spinner
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:entries="@array/ctype">
</Spinner>

除了这种方式,我们还可以使用适配器对下拉列表框的列表项进行设置

使用适配器对下拉列表框的列表项进行设置,选择列表项后输出显示所选值

首先我们需要为Spinner设置一个id,假设id设置为spinner。

1
2
3
4
5
<Spinner
android:id="@+id/spinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</Spinner>

然后在Activity中进行编写:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String []ctype = new String[]{"全部","音乐","游戏","编程"};
//创建数组适配器
ArrayAdapter<String > adapter = new ArrayAdapter<>(this,android.R.layout.simple_spinner_item,ctype);
//为列表框设置下拉样式
adapter.setDropDownViewResource(android.R.layout.
simple_spinner_dropdown_item);
//将适配器和下拉列表框关联起来
Spinner spinner = findViewById(R.id.spinner);
spinner.setAdapter(adapter);
//获取下拉列表框的选项值
/*String str = spinner.getSelectedItem().toString();
Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show();*/
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view,
int position, long id) {
//根据选中项获取其值
String result = parent.getItemAtPosition(position).toString();
Toast.makeText(MainActivity.this, result, Toast.LENGTH_SHORT).show();
}

@Override
public void onNothingSelected(AdapterView<?> parent) { }
});
}
}

列表视图

1
<ListView />

可应用于用户列表。

和下拉列表框一样,可以使用android:entries来给列表视图设置列表项。

具体步骤参考 下拉列表框 即可。

同样除了这种方式,我们还可以使用适配器对列表视图的列表项进行设置

使用适配器对列表视图的列表项进行设置,点击获得列表项的所选值

首先需要给<ListView />设置一个id。

1
2
3
4
<ListView
android:id="@+id/listview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String[] ctype = new String[]{"全部","音乐","游戏","编程"};
//设置适配器和viewlist的外观形式,可以有多种选择
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,ctype);
ListView listView = findViewById(R.id.listview);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
String str = (String) parent.getItemAtPosition(position);
Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show();
}
});
}
}

滚动视图

1
<ScrollView />

滚动视图可以在xml文件中添加,也可以在java文件中添加。

滚动视图默认是竖直的滚动,但我们也可以设置其他的滚动方式。

如果我们要设置水平方向的滚动,则需要使用<HorizontalScrollView />标记。

在一个滚动视图中,只能放置一个组件,如果想要放置多个,我们需要使用布局管理器把这些组件括起来。

使用xml文件创建滚动视图

准备:创建一个字符串资源,在res/values/strings.xml中创建:

1
2
3
4
5
<resources>
<string name="app_name">scrollview</string>
<string name="content"> 安卓是一种基于Linux内核(不包含GNU组件)的自由及开放源代码的操作系统。主要使用于移动设备,如智能手机和平板电脑,由Google公司和开放手机联盟领导及开发。Android操作系统最初由Andy Rubin开发,主要支持手机。2005年8月由Google收购注资。2007年11月,Google与84家硬件制造商、软件开发商及电信营运商组建开放手机联盟共同研发改良Android系统。随后Google以Apache开源许可证的授权方式,发布了Android的源代码。
Android一词的本义指“机器人”,同时也是Google于2007年11月5日宣布的基于Linux平台的开源手机操作系统的名称,该平台由操作系统、中间件、用户界面和应用软件组成。</string>
</resources>

创建竖直的滚动视图:

1
2
3
4
5
6
7
8
9
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/content"
android:textSize="30sp" />
</ScrollView>

创建水平的滚动视图:注意组件的长、宽设置

1
2
3
4
5
6
7
8
9
<HorizontalScrollView
android:layout_width="wrap_content"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/content"
android:textSize="30sp" />
</HorizontalScrollView>

在滚动视图中创建多个组件:

1
2
3
4
5
6
7
8
9
10
11
12
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!--TextView中属性省略-->
<TextView />
<TextView />
</LinearLayout>
</ScrollView>

使用java文件创建滚动视图

步骤:

  1. 使用构造方法ScrollView(Context c)创建一个滚动视图;
  2. 应用addView()方法添加组件到滚动视图中;
  3. 将滚动视图添加到布局管理器中。

在这里我们回创建一个带有图片和文字的滚动视图,因此需要我们先准备好图片资源和字符串资源。

假设我们已准备好图片资源并命名为image.jpg,同时我们需要把图片资源放置于res/drawable目录下。而我们使用的字符串资源就继续使用上文的content字符串资源。

根布局文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:id="@+id/ll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="16dp"
android:paddingTop="16dp"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:orientation="vertical"
tools:context=".MainActivity">
</LinearLayout>

Activity文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//获取根布局管理器
LinearLayout ll = findViewById(R.id.ll);
//新建一个垂直的线性布局管理器
LinearLayout ll2 = new LinearLayout(MainActivity.this);
ll2.setOrientation(LinearLayout.VERTICAL);
//创建一个滚动视图对象
ScrollView scrollView = new ScrollView(MainActivity.this);
//将视图进行组合
ll.addView(scrollView);
scrollView.addView(ll2);
ImageView imageView = new ImageView(MainActivity.this);
imageView.setImageResource(R.drawable.image);
ll2.addView(imageView);
TextView textView = new TextView(MainActivity.this);
textView.setText(R.string.content);
ll2.addView(textView);
}
}

选项卡

我们不能使用某个具体的组件在xml文件添加选项卡。

使用步骤

  1. 在布局文件中添加TabHostTabWidgetTabContent组件。TabHostTabWidget在布局文件中有具体的标记,而对于TabContent我们需要使用FrameLayout来实现。
  2. 编写各标签页的XML布局文件。(如果我们选项卡有几个标签页,就需要编写几个布局文件,布局文件的内容就是我们需要在选项卡中显示的内容)
  3. 获取并初始化TabHost组件。
  4. TabHost对象添加标签页。

具体实例

准备:我们在选项卡中实现两张图片的切换,因此我们需要两张图片。假设这两张图片命名为image_left.jpg和image_right.jpg,并将它们放置在res/drawable目录下。

**我们首先编写各标签页的XML布局文件:**tab1.xml和tab2.xml

1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/left"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/image_left"/>
</LinearLayout>
1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/right"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/image_right"/>

</LinearLayout>

编写根布局文件:

注意:在根布局文件中,TabHost、TabWidget和FrameLayout的id需要使用Android给我提供的,不能自己随意命名。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?xml version="1.0" encoding="utf-8"?>
<TabHost 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:id="@android:id/tabhost"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TabWidget
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@android:id/tabs"></TabWidget>
<FrameLayout
android:id="@android:id/tabcontent"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
</LinearLayout>
</TabHost>

在Activity文件中初始化TabHost组件,并为其添加标签页:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//获取TabHost对象
TabHost tabHost = findViewById(android.R.id.tabhost);
//对TabHost组件进行初始化
tabHost.setup();
//为TabHost添加标签页
//初始化LayoutInflater
LayoutInflater inflater = LayoutInflater.from(this);
inflater.inflate(R.layout.tab1,tabHost.getTabContentView());
inflater.inflate(R.layout.tab2,tabHost.getTabContentView());
//为TabHost设置标签页及文字内容
tabHost.addTab(tabHost.newTabSpec("tab1").setIndicator("图片1").setContent(R.id.left));
tabHost.addTab(tabHost.newTabSpec("tab2").setIndicator("图片2").setContent(R.id.right));
}
}

Android布局与组件完