封面画师:画师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节点
解决:Build —> Clean Project
- Android Studio卡在“Waiting for target device to come online”:
后续补充:
这些方法没啥卵用,不用看了,可以试试选用Target不带有Google字样的x64模拟器。
解决:每种解决都可以试一下!!参考链接
- 将镜像改成x86_64然后新建一个模拟器。
- 打开AVD manager找到自己的模拟器,然后右击模拟器,选择Cold Boot Now,模拟器打开并提示一行信息,直接dismiss。
- 重启AS,重启系统。(注意:如果你是Win10 系统,重启的时候记得按住 shift 来禁用系统的强制签名)
- paltform-tools目录下adb kill-server,然后adb start-server。
- SDK tool 或paltform tool有更新,下载更新。
- 删除<Your_AVD_Directory>.android\avd\Pixel_XL_API_28.avd目录下.lock文件,然后重新载入。
- 打开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的区别:
- 9-Patch图片和Shape资源文件只能放在drawable目录中;
- 需要适应屏幕分辨率的图片推荐放在mipmap目录中,可以提高显示性能、占用内存更少;
values目录
主要用于保存字符串资源、样式资源、尺寸资源、颜色资源。
UI布局
View
我们一般不直接使用View类,而是使用View类的子类(比如TextView)。
View类位于android.view包中;View类的子类一般都用于android.widget包中。
常用属性:
1
| android:id = "@+id/user"
|
android:background
为组件设置背景(可以是图片资源也可以是颜色)
1
| android:background = "@mipmap/bg"
|
android:padding
为组件四周设置一样的内边距
衍生属性:
android:paddingLeft
、android:paddingTop
、android:paddingRight
、android: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常用于设置布局高度和宽度。
ViewGroup.MarginLayoutParams用于控制子组件的外边距。
-
属性:android:layout_marginTop
、android:layout_marginBottom
、android:layout_marginLeft
、android: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界面
- 在Android应用的res/layout目录下编写XML布局文件(如activity_main.xml)
- 在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的影响
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
gravity 和layout_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
|
<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
|
android:layout_row = "1"
android:layout_column = "2"
|
布局管理器的嵌套
嵌套原则
- 根布局管理器必须包含xmlns属性;
- 在一个布局文件中,最多只能有一个根布局管理器,如果需要有多个还需要使用一个根布局管理器将它们括起来;
- 不能嵌套地太深,如果嵌套太深,会影响性能。
不能套娃太深!!
基本UI组件
使用UI组件时注意字母的大小写!
使用UI组件时注意字母的大小写!
使用UI组件时注意字母的大小写!
文本框组件
属性
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"
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之跑马灯详解
编辑框
它是文本框组件的子类。
属性
android:hint
设置默认提示内容,属性值为字符串
android:inputType
设置输入内容类型,如:
1 2
| android:inputType = "textPassword" android:inputType = "number"
|
android:drawableLeft
在编辑框左侧绘制一个图像,常用于图标的设置,属性值为图片资源,如:
1
| android:drawableLeft = "@mipmap/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(); }
|
普通按钮
它是文本框组件的子类。
为普通按钮添加点击事件监听器
首先需要给按钮设置一个id,假设设置id为btn,则在Activity中有:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| protected void onCreate(Bundle savedInstanceState) { ...
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(); } }); }
|
- 在Activity中编写一个包含View类型参数的方法。
1 2 3 4
| public void myClick(View view){ Toast.makeText(MainActivity.this, "单击了按钮", Toast.LENGTH_SHORT).show(); }
|
- 将
android:onClick
属性指定为步骤(1)中的方法名。
1
| android:onClick = "myClick"
|
图片按钮
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); ... }
|
单选按钮
基本使用(属性)
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 = 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; } } } }); }
|
复选框
使用(本身属性)
设置多个复选框只需要使用多个<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) { ... 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()){ Toast.makeText(MainActivity.this,checkBox_1.getText(), Toast.LENGTH_SHORT).show(); } } }); }
|
日期选择器
常将日期选择器的长宽设置成根据父容器变化。
如果添加日期选择器后发现日期没有显示完全,应该进入对应的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 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); 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(); } }); } }
|
计时器
它是文本框组件的子类。
计时器默认的样式是 时:分:秒
如果我们想自定义时间格式,我们可以通过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) { if (SystemClock.elapsedRealtime() - chronometer.getBase() >= 60000){ chronometer.stop(); } } }); } }
|
高级UI组件
使用UI组件时注意字母的大小写!
使用UI组件时注意字母的大小写!
使用UI组件时注意字母的大小写!
进度条
安卓提供了两种进度条模式:水平进度条和圆形进度条。默认是圆形进度条。
属性
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(); } }
|
拖动条
它是进度条的子类。
属性
由于它是进度条的子类,因此它可以使用进度条<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() { @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。
图像视图参考下文。
星级评分条
属性
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(); } }
|
图像视图
属性
android:src
设置ImageView的内容,属性值是图片的地址。如:其中image1是图片名称
1
| android:src="@drawable/image1
|
android:src
和android:background
的区别:
- background通常指的都是背景,而src指的是内容。
- 当使用src填入图片时,是按照图片大小直接填充,并不会进行拉伸;而使用background填入图片,则是会根据ImageView给定的宽度来进行拉伸。
<ImageView />
是正方形的。
android:layout_width
和android: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 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; } }); } }
|
网格视图
可应用于相册。
属性
android:numColumns
设置网格布局的列数。属性值可以为整形,也可以是自动排列:auto_fit
android:verticalSpacing
设置垂直间距,单位dp。
android:horizontalSpacing
设置水平间距,单位dp。
android:stretchMode="columnWidth"
缩放与列宽大小同步
android:columnWidth
设置列宽度,单位dp。
适配器
连接后端数据和前端显示的接口,是数据和UI组件的一个重要纽带。主要在View上显示(一般是ListView)。可以看作是界面数据绑定的一种理解。它所操纵的数据一般都是一些比较复杂的数据,如数组,链表,数据库,集合等。适配器就像显示器,把复杂的东西按人可以接受的方式来展现。
使用者:ListView、GridView、Spinner、Gallery、ViewPage等都需要使用适配器来为其设置数据源。
常用的适配器
建议花费一定量的时间学习适配器
ArrayAdapter
,SimpleAdapter
,SimpleCursorAdapter
这三个都是继承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.setImageResource(pic[position]); return imageView; } } }
|
下拉列表框
属性
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);
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) { } }); } }
|
列表视图
可应用于用户列表。
和下拉列表框一样,可以使用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[]{"全部","音乐","游戏","编程"}; 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(); } }); } }
|
滚动视图
滚动视图可以在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 /> </LinearLayout> </ScrollView>
|
使用java文件创建滚动视图
步骤:
- 使用构造方法ScrollView(Context c)创建一个滚动视图;
- 应用addView()方法添加组件到滚动视图中;
- 将滚动视图添加到布局管理器中。
在这里我们回创建一个带有图片和文字的滚动视图,因此需要我们先准备好图片资源和字符串资源。
假设我们已准备好图片资源并命名为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文件添加选项卡。
使用步骤
- 在布局文件中添加
TabHost
、TabWidget
和TabContent
组件。TabHost
和TabWidget
在布局文件中有具体的标记,而对于TabContent
我们需要使用FrameLayout
来实现。
- 编写各标签页的XML布局文件。(如果我们选项卡有几个标签页,就需要编写几个布局文件,布局文件的内容就是我们需要在选项卡中显示的内容)
- 获取并初始化
TabHost
组件。
- 为
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 = findViewById(android.R.id.tabhost); tabHost.setup(); LayoutInflater inflater = LayoutInflater.from(this); inflater.inflate(R.layout.tab1,tabHost.getTabContentView()); inflater.inflate(R.layout.tab2,tabHost.getTabContentView()); tabHost.addTab(tabHost.newTabSpec("tab1").setIndicator("图片1").setContent(R.id.left)); tabHost.addTab(tabHost.newTabSpec("tab2").setIndicator("图片2").setContent(R.id.right)); } }
|
Android布局与组件完