一.UI组件之布局管理器
布局管理器可以根据运行平台来调整组件的大小,而我们要做的就是为容器选择合适的布局管理器。
所有布局都可以作为容器类使用,因此可以调用多个重载的addView()向布局管理器中添加组件。
1.线性布局LinearLayout
LinearLayout包含的所有子元素都受LinearLayout.LayoutParams控制,因此LinearLayout包含的子元素可以额外指定如下属性:
<?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:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="top|center_horizontal"
tools:context=".MainActivity">
<Button
android:id="@+id/bn1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/bn1"/>
<Button
android:id="@+id/bn2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/bn2"/>
<Button
android:id="@+id/bn3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/bn3"/>
<Button
android:id="@+id/bn4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/bn4"/>
<Button
android:id="@+id/bn5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/bn5"/>
</LinearLayout>
2.表格布局TableLayout
3.帧布局FrameLayout
4.相对布局RelativeLayout
5.网格布局GridLayout
6.绝对布局AbsoluteLayout
二.UI组件之TextView及其子类
1.文本框TextView与编辑框EditText的功能和用法
TextView提供了大量的XML属性,这些XML属性大部分不仅可适用于TextView,而且可适用它的子类(EditText,Button等)。
实例:圆角边框,渐变背景的TextView
在默认情况下,TextView是不带边框的,如果想为TextView添加边框,只能通过为TextView设置一个背景Drawable,该Drawable只是一个边框,这样就实现了带边框的TextView。
Activity_main.xml
<?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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<!-- 通过android:background指定背景 -->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="带边框的文本"
android:textSize="24pt"
android:background="@drawable/bg_border"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="圆角边框、渐变背景的文本"
android:textSize="24pt"
android:background="@drawable/bg_border2"/>
</LinearLayout>
上面的界面布局文件中定义了两个TextView,其中一个指定了背景,第二个定义文本框时指定使用圆角边框,渐变背景。
第一个文本框所指定的背景有xml文件定义的,该文件放在drawable文件夹下,该xml文件也可当成Drawable使用,
<?xml version="1.0" encoding="UTF-8" ?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<!--设置背景色为透明色-->
<solid android:color="#0000"/>
<!--设置红色边框-->
<stroke android:width="4px"
android:color="#f00"/>
</shape>
第二个文本框所指定的背景是由XML文件定义的,将该文件放在drawable文件夹内,该XML文件也可当成Drawable使用,
<?xml version="1.0" encoding="UTF-8" ?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<!-- 指定圆角矩形的4个圆角的半径 -->
<corners android:topLeftRadius="20px"
android:topRightRadius="5px"
android:bottomRightRadius="20px"
android:bottomLeftRadius="5px"/>
<!-- 指定边框线条的宽度和颜色 -->
<stroke android:width="4px" android:color="#f0f" />
<!-- 指定使用渐变背景色,使用sweep类型的渐变
颜色从红色→绿色→蓝色 -->
<gradient android:startColor="#f00"
android:centerColor="#0f0"
android:endColor="#00f"
android:type="sweep"/>
</shape>
结果:
2.EditText的功能和用法
EditText组件最重要的属性是inputType,EditText还派生了如下两个子类:
AutoCompleteTextView:带有自动完成功能的EditText,该类通常需要与Adapter结合使用。
ExtractEditText:它并不是UI组件,而是EditText组件的底层服务类,负责提供全屏输入法支持。
实例:用户友好的输入界面
实现一个友好的输入界面,接受用户输入的文本框内默认会提示用户如何输入;当用户把焦点切换到输入框时,输入框自动选中其中已输入的内容,避免用户删除已有内容;当用户把焦点切换到只接受电话号码的输入框时,输入法自动切换到数字键盘。
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:stretchColumns="1"
tools:context=".MainActivity">
<TableRow>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="用户名"
android:textSize="16sp"
/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请填写登录账号"
android:selectAllOnFocus="true"/>
</TableRow>
<TableRow>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="密码:"
android:textSize="16sp"/>
<!--inputtype只能接受数字密码-->
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="numberPassword"/>
</TableRow>
<TableRow>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="年龄:"
android:textSize="16sp"/>
<!--数值输入框-->
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="number"/>
</TableRow>
<TableRow>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="生日:"
android:textSize="16sp"/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="date"/>
</TableRow>
<TableRow>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="电话号码:"
android:textSize="16sp"/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入您的电话号码"
android:selectAllOnFocus="true"
android:inputType="phone"/>
</TableRow>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="注册"/>
</TableLayout>
界面布局的第一个文本框通过android:hint指定了文本框的提示信息,请填写登录账号-----这是该文本框默认的提示。当用户还没有输入时,该文本框内默认显示这段信息。
3.按钮(Button)组件的功能与用法
Button继承了TextView,它主要是在UI界面上生成一个按钮,该按钮可以供用户单击,当用户单击按钮时,按钮会触发一个onClick事件。
实例:按钮,圆形按钮,带文字的图片按钮
为了定义图片随着用户动作改变的按钮,可以考虑使用XML资源文件来定义Drawable对象,再将Drawable对象设为Button的android:background属性值,或设为ImageButton的android:src属性值。
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- 文字带阴影的按钮 -->
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="文字带阴影的按钮"
android:textSize="12pt"
android:shadowColor="#EEEE4B"
android:shadowRadius="8"
android:shadowDx="10"
android:shadowDy="10"/>
<!-- 普通文字按钮 -->
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/red"
android:text="普通按钮"
android:textSize="12pt"/>
<!-- 带文字的图片按钮-->
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/button_selector"
android:textSize="18px"
android:text="带文字的图片按钮"/>
</LinearLayout>
button_selector.xml
<?xml version="1.0" encoding="UTF-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 指定按钮按下时的图片 -->
<item android:state_pressed="true"
android:drawable="@drawable/red"
/>
<!-- 指定按钮松开时的图片 -->
<item android:state_pressed="false"
android:drawable="@drawable/purple"
/>
</selector>
第二个按钮通过background属性配置了背景图片,因此该按钮将会显示为背景图片形状的按钮。
第三个按钮指定了android:background属性为@drawable/button_selector,该属性值引用一个Drawable资源,该资源对应如上的button_selector.xml文件。
上面资源文件使用<selector…/>元素定义了一个StateListDrawable对象。
4.单选钮(RadioButton)和复选钮(CheckBox)的功能和用法
单选钮,复选钮,状态开关按钮(ToggleButton)和开关(Switch)是用户界面中最普通的UI组件,它们都继承了Button类,因此都可以直接使用Button支持的各种属性和方法。
RadioButton和CheckBox都可额外指定一个android:checked属性,该属性用于指定RadioButton,CheckBox初始时是否被选中。
实例:利用单选钮,复选框获取用户信息
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TableRow>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="性别:"/>
<!--定义一组单选钮-->
<RadioGroup android:id="@+id/rg"
android:orientation="horizontal"
android:layout_gravity="center_horizontal">
<!--定义两组单选框-->
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/male"
android:text="男"
android:checked="true"/>
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/female"
android:text="女"/>
</RadioGroup>
</TableRow>
<TableRow>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="喜欢的颜色:"/>
<!--定义一个垂直的线性布局-->
<LinearLayout
android:layout_gravity="center_horizontal"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<!--定义三个复选框-->
<CheckBox android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="红色"
android:checked="true"/>
<CheckBox android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="蓝色"/>
<CheckBox android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="绿色"/>
</LinearLayout>
</TableRow>
<TextView
android:id="@+id/show"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:textSize = "50sp"
android:textColor="@color/colorAccent"/>
</TableLayout>
为了监听单选钮,复选框的勾选状态的改变,可以为他们添加事件监听器。例如下面Activity为RadioGroup添加了事件监听器,该监听器可以监听这组单选钮的勾选状态的改变。
package com.example.checkbutton;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.RadioGroup;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
RadioGroup rg;
TextView show;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//获取界面上rg show两个组件
rg=(RadioGroup)findViewById(R.id.rg);
show = (TextView)findViewById(R.id.show);
//为RadioGroup组件的Oncheckedchanged事件绑定事件监听器
rg.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
String tip = checkedId == R.id.male ? "您的性别是男人":"您的性别是女人";
//修改show组件中的文本
show.setText(tip);
}
});
}
}
5.状态开关按钮(ToggleButton)和开关(Switch)的功能与用法
ToggleButton,Switch通常用于切换程序中的某种状态。其中ToggleButton所支持的XML属性及相关方法。
实例:动态控制布局
在页面中增加一个ToggleButton,随着该按钮状态的改变,界面布局中的LinearLayout布局的方向在水平布局,垂直布局之间切换,
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- 定义一个ToggleButton按钮 -->
<ToggleButton android:id="@+id/toggle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textOff="横向排列"
android:textOn="纵向排列"
android:checked="true"/>
<Switch android:id="@+id/switcher"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textOff="横向排列"
android:textOn="纵向排列"
android:thumb="@drawable/check"
android:checked="true"/>
<!-- 定义一个可以动态改变方向的线性布局 -->
<LinearLayout android:id="@+id/test"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<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>
该LinearLayout默认采用垂直方向的线性布局,接下来为ToggleButton按钮,Switch按钮绑定监听器,当它的选中状态发生改变时,程序通过代码来改变LinearLayout的布局方向。
MainActivity.java
package org.crazyit.ui;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.LinearLayout;
import android.widget.Switch;
import android.widget.ToggleButton;
public class MainActivity extends Activity
{
ToggleButton toggle;
Switch switcher;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
toggle = (ToggleButton)findViewById(R.id.toggle);
switcher = (Switch)findViewById(R.id.switcher);
final LinearLayout test = (LinearLayout)findViewById(R.id.test);
OnCheckedChangeListener listener = new OnCheckedChangeListener()
{
@Override
public void onCheckedChanged(CompoundButton button
, boolean isChecked)
{
if(isChecked)
{
// 设置LinearLayout垂直布局
test.setOrientation(1);
toggle.setChecked(true);
switcher.setChecked(true);
}
else
{
// 设置LinearLayout水平布局
test.setOrientation(0);
toggle.setChecked(false);
switcher.setChecked(false);
}
}
};
toggle.setOnCheckedChangeListener(listener);
switcher.setOnCheckedChangeListener(listener);
}
}
6.时钟AnalogClock和TextClock的功能与用法
TextClock支持的XML属性及方法:
AnalogClock则继承了View组件,它重写了View的OnDraw方法,它会在View上绘制模拟时钟。
两者的不同点是TextClock显示数字时钟,可以显示当前的秒数;AnalogClock显示模拟时钟,不会显示当前的秒数。
7.计时器Chronometer
计时器不显示当前时间,它显示的是从某个起始时间开始,一共过去了多长时间。并且只提供了一个android:format属性,用于指定计时器的计时格式。
还支持如下常用方法:
setBase(long base): 设置计时器的起始时间
setFormat(String format) :设置显示时间的格式
start() 开始计时
stop() 停止计时
setOnChronometerTickListener(Chronometer.OnChronometerTickListener listener);
为计时器绑定事件监听器,当计时器改变时触发该监听器。