Android常用控件用法
包含Checkbox 二、RadioButton 三、ImageView 四、深入LinearLayout 五、相对布局 六、TimePicker 七、DatePicker。
一、Checkbox
1.布局文件的定义
<CheckBox
android:id="@+id/eatId"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="吃饭"/>
<CheckBox
android:id="@+id/sleepId"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="睡觉"/>
<CheckBox
android:id="@+id/dotaId"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="dota"/>
2.Activity中的使用
先声明三个成员变量:
private CheckBox eatBox;
private CheckBox sleepBox;
private CheckBox dotaBox;
再在onCreate函数里找到它们
eatBox = (CheckBox) findViewById(R.id.eatId);
sleepBox = (CheckBox) findViewById(R.id.sleepId);
dotaBox = (CheckBox) findViewById(R.id.dotaId);
3.OnClickListener监听器
现在需要定义一个监听器,监听click这个事件
class onClickBoxListener implements OnClickListener{
@Override
public void onClick(View v) {
// TODOAuto-generated method stub
System.out.println("Checkbox is clicked!");
}
}
然后在onCreate函数实例化这个监听器
onClickBoxListener listener = new onClickBoxListener();
将监听器绑定到Checkbox上。这里可以把一个listener绑定到多个控件。
eatBox.setOnClickListener(listener);
sleepBox.setOnClickListener(listener);
dotaBox.setOnClickListener(listener);
现在运行这个程序,如图:
三个选项出现,我们进行勾选,Eclipse的后台会显示Checkbox is clicked!
1) 在监听器中获取checkbox 的ID
虽然实现了基本流程,但是有一个问题没有解决,不管我勾选或取消哪个Checkbox,响应的行为都是一样的,而且不知道是选中还是取消选中。这满足不了编程的需要。
要实现这种功能,我们要通过监听器传参:
public void onClick(View v) {
// TODOAuto-generated method stub
System.out.println("Checkbox is clicked!");
}
函数里的v是View类型,它有一个方法是getId(),它得到的就是控件的ID。
现在事情就很好办了。
if (v.getId() == R.id.eatId){
System.out.println("eatBox");
} else if (v.getId() == R.id.sleepId){
System.out.println("sleepBox");
} else if (v.getId() == R.id.dotaId){
System.out.println("dotaBox");
}
2) 在监听器中获取checkbox 的选中状态
我们需要知道,对某个checkbox操作的是选中还是取消选中。
还是通过v这个参数,由于这个参数是View类型,我们需要向下转型为CheckBox,才能获取选中状态。
CheckBox checkbox = (CheckBox) v;
CheckBox类型有一个方法,是isChecked()。返回值是真,表示选中,返回值是假,表示未选中。
4.OnCheckedChangeListener监听器
依然是定义一个监听器,监听CheckedChange这个事件,即Checkbox的选中状态发生改变时:
class boxListener implements OnCheckedChangeListener{
}
导入包的时候注意,选CompoundButton这个。Checkbox其实是它的子类。
添加未实现的方法时,我们发现函数的传参是个CompoundButton类型,还有第二个参数,是个布尔值。
当选中状态发生改变时,就把控件对象和当前状态传递进来。
@Override
public void onCheckedChanged(CompoundButton buttonView,
booleanisChecked) {
// TODO Auto-generated method stub
}
照旧是实例化这个监听器,绑定到控件上。
boxListener listener2 = new boxListener();
eatBox.setOnCheckedChangeListener(listener2);
sleepBox.setOnCheckedChangeListener(listener2);
dotaBox.setOnCheckedChangeListener(listener2);
现在我们来完善监听代码
if (buttonView.getId() == R.id.eatId){
System.out.println("eatBox Changed");
if (isChecked)
System.out.println("eatBox Changed True");
}
不用多说了,这对程序员来说已经很简单了。
OnClickListener监听和OnCheckedChangeListener监听的区别在于:
前者是监听点击事件,后者是监听状态的改变,因为状态的改变不全是由于直接的点击,也可以是由于代码的控制,代码里设置checkbox状态的函数是setChecked(状态) ,状态的值是true或false。
二、RadioButton
1.布局文件的定义
RadioGroup是指一组单选按键,一组单选按钮只能选中一个。RadioButton是RadioGroup的子标签(RadioButton与RadioGroup分别是不同的控件)。所以在布局文件里,要先定义一个RadioGroup,内部再包含RadioButton。
<RadioGroup
android:id="@+id/radios"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<RadioButton
android:id="@+id/femaleId"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="female"
/>
<RadioButton
android:id="@+id/maleId"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="male"
/>
</RadioGroup>
注意:RadioGroup有个特殊的属性orientation,是指各单选按钮的排列方向,可以设置水平或垂直。
2.Activity中的使用
声明成员变量,注意RadioGroup与RadioButton分开声明:
private RadioGroupradioGroup;
privateRadioButton femaleButton;
privateRadioButton maleButton;
findViewById找到它们:
radioGroup = (RadioGroup) findViewById(R.id.radios);
femaleButton = (RadioButton) findViewById(R.id.femaleId);
maleButton = (RadioButton) findViewById(R.id.maleId);
实现选中之后的行为,需要绑定监听器了。
3.OnClickListener监听器
可以给RadioButton添加OnClickListener,监听各个RadioButton被点击的状态。操作方法与前一讲Checkbox类似,此不赘述。
4.OnCheckedChangeListener监听器
1) RadioGroup的OnCheckedChangeListener
给RadioGroup绑定监听器OnCheckedChangeListener,表示当这个RadioGroup内部的RadioButton被选中时,就会调用OnCheckedChangeListener监听器:
class listener implements OnCheckedChangeListener(){
}
在导入包的时候注意了,这与Checkbox不同,我们须选择第二个
导入包以后,onCreate里绑定到RadioGroup:
listener listener = new listener();
radioGroup.setOnCheckedChangeListener(listener);
然后在监听器里实现未实现的函数:
class listener implements OnCheckedChangeListener{
@Override
public voidonCheckedChanged(RadioGroup group, int checkedId) {
}
}
发现这个函数有两个参数,
第二个参数代表这个RadioGroup里被选中的RadioButton的ID,因为同时被选中的只可能有一个嘛,所以就直接传进来了。
实现监听器的代码:
public voidonCheckedChanged(RadioGroup group, int checkedId) {
if (checkedId == R.id.femaleId){
System.out.println("femaleId is checked");
} else {
System.out.println("maleId is checked");
}
}
2) RadioButton的OnCheckedChangeListener
定义这个监听器的时候,要特别注意,实现的接口不是RadioGroup.OnCheckedChangeListener,而是CompoundButton.OnCheckedChangeListener。
于是我们定义这个监听器的时候,为避免重名,要写全:
class listener2 implements android.widget.CompoundButton.OnCheckedChangeListener{
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
// TODO Auto-generated method stub
}
}
为什么是CompoundButton?
这里解释一下,所谓CompoundButton,是指两种状态的button的抽象父类,Checkbox和RadioButton都是它的子类。
绑定它到femaleButton上:
listener2 listener2 = new listener2();
femaleButton.setOnCheckedChangeListener(listener2);
如此表示,当femaleButton的选中状态发生改变时,触发listener2监听器里的代码。
注意:如果我们选中了maleButton,也会调用这个监听器,因为选中maleButton的同时,femaleButton的选中状态也发生了改变。
我们实现这个监听器里的代码:
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
System.out.println("female is "+ isChecked);
}
第二个参数就是当前选中的状态。
三、ImageView
1.布局文件的定义
<ImageView
android:id="@+id/imageId"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/qq" />
这里有个src属性,很好理解,不过里面的东东是怎么来的呢?
之前我们提到过的res这个资源目录,里面的drawable表示存放图片。
我们将图片拷进目录:
R.java文件会自动生成它的ID:
public static final class drawable {
public static final int ic_launcher=0x7f020000;
public static final int qq=0x7f020001;
}
因此,我们使用android:src="@drawable/qq"就可以引用到它了。
2.Activity中的使用
声明变量
private ImageView image;
找到控件
image = (ImageView) findViewById(R.id.imageId);
之前是在布局文件中设置它的源文件,也可以在代码中设置:
image.setImageResource(R.drawable.qq);
3.ScaleType属性
现在的问题是,图片铺不满全屏。ScaleType就是用来解决这个问题的,它用于定义图片拉伸的类型是什么。
先让我们把准备工作做好,写两个ImageView写好高宽和背景色,以方便做对比。
上一张是刚才那只卖萌狗,下一张是安卓机器人图标:
<ImageView
android:id="@+id/imageId"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#FF0000"
android:scaleType="center"
android:src="@drawable/qq" />
<ImageView
android:id="@+id/image2Id"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#00FF00"
android:scaleType="center"
android:src="@drawable/ic_launcher"/>
ScaleType有以下几种,让我们来分别试验一下:
1) center
不缩放。
如果图比ImageView小,就居中。如果图比ImageView大,就截取中间部分。
2) centerCrop
等比例缩放。
并以短边为准铺满。长出的部分截掉。
3) centerInside
等比例缩小并居中对齐。
如果图比ImageView小,就不变。如果图比ImageView大,就缩小。
4) fitCenter
等比例缩放并居中对齐。
如果图比ImageView小,就放大。如果图比ImageView大,就缩小。
5) fitStart
等比例缩放并靠左上角对齐。
6) fitEnd
等比例缩放并靠右下角对齐。
7) fitXY
不等比例缩放,拉伸为与ImageView同样大小。
在代码里怎么控制scaleType呢?
image.setScaleType(ScaleType.CENTER);
四、深入LinearLayout
1.LinearLayout的嵌套
这样一个布局用一个LinearLayout是无法实现的。需要用到LinearLayout的嵌套。
布局代码如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FF0000"
android:orientation="horizontal"
tools:context=".MainActivity" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#880000"
android:layout_marginRight="10dp"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:text="first"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:text="second"/>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#880000"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:text="first"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:text="second"/>
</LinearLayout>
</LinearLayout>
这个嵌套对程序员来说太容易理解了,就不多说了。
2.layout_weight属性
Layout_weight这个属性的值用于指定空闲空间的分配比例,如下图:
使用layout_weight,要求子控件并未占满你控件的所有空间。否则这个属性将不具意义。
Layout_weight的值是整型。
例如,上面这张图,如果我们给两个控件的layout_weight分别给定值1:
那么,这两个控件将平分空闲空间。达到的效果见下图:
有一点需要特别注意:
layout_weight=1不代表两个控件平分父控件的空间,而是在本身占据的空间基础上,将剩下的空间一分为二,分别加给两控件。所以,两控件并不一定是各占父控件的二分之一的。
见下图:
红线所划的距离是相等的。而绿色和蓝色的长度却不等。
这是layout_weight为1的情况,如果将控件一的layout_weight设为2呢?
那么,就将剩余空间平均分为三份,其中两份给控件一,一份给控件二。
以此类推。
我们在实际开发中常常需要让控件占父控件的1/2,或1/3等等。这样layout_weight就满足不了我们的要求。但有个办法可以做到:
将控件的宽不再wrap_content,而是设为0dp。
五、相对布局
1.什么是相对布局
相对布局是通过指定当前控件与兄弟控件或父控件之间的相对位置,从而达到控制控件位置的目的。
和线性布局相比有什么优势呢?看下面这张图:
这个布局如果用线性布局,需要嵌套好几层,而如果用相对布局,一个布局就搞定了。
对Android UI来说,几层布局嵌套,性能比一个布局要差。
2.相对布局基本思路
先确定一个控件的位置,第二个控件,确定它相对于第一个控件的位置。
这种情况下,如果第一个控件因为某种原因发生位置改变,那么,第二个控件与它的相对位置不变,也跟着位移。
在相对布局中,如果不指定相对位置,默认会放在父控件的左上角:
如果第二个控件也不指定相对位置,那么,第二个控件会覆盖第一个控件,仍然放在左上角:
要实现相对布局,就要指定相对位置,以下我们分别介绍:
1) 与兄弟控件边缘对齐
layout_toRightOf
把当前控件的左边缘对齐到指定控件的右边缘。
第一个控件给定ID为first:
<TextView
android:id="@+id/first"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#FF0000"
android:text="第一个控件" />
第二个控件设置layout_toRightOf属性为@id/first:
注意:这里没有+,+表示增加一个id
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#00FF00"
android:layout_toRightOf="@id/first"
android:text="第二个控件" />
这样就能把第二个控件放置在第一个控件的右边
layout_toLeftOf
把当前控件的右边缘对齐到指定控件的左边缘。
理同layout_toRightOf
如果第一个控件没有指定相对位置,而第二个控件指定到它的左边缘,那么第二个控件会被挤到屏幕外面,不可见。见下图:
layout_below
把当前控件的上边缘对齐到指定控件的下边缘。
layout_above
把当前控件的上边缘对齐到指定控件的下边缘。
同layout_toLeftOf理,在屏幕外,不可见了。
layout_alignLeft
把当前控件的左边缘对齐到指定控件的左边缘。
我们先把第一个控件的文本改得“第一个控件比较长”,这样看得出来。
把第二个控件的layout_alignLeft值设为@id/first:
第一个控件被覆盖掉了一部分。
layout_alignRight
把当前控件的右边缘对齐到指定控件的右边缘。
理同layout_alignLeft
layout_alignTop
把当前控件的上边缘对齐到指定控件的上边缘。
layout_alignBottom
把当前控件的下边缘对齐到指定控件的下边缘。
2) 与兄弟控件基准线对齐
什么是基准线
基准线(baseline):为了保证印刷字母的整齐而划定的线。这主要针对英文,对于中文其实没有这个问题。
第三条线就是基准线。
对齐到基准线的属性是layout_alignBaseLine。
layout_alignBaseLine
把当前控件的基准线对齐到指定控件的基准线。
沿用之前的代码,第二个控件的定义如下:
<TextView
android:id="@+id/second"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#00FF00"
android:layout_alignBaseline="@id/first"
android:layout_toRightOf="@id/first"
android:text="第二个控件" />
定义了两个对齐属性,layout_alignBaseline和layout_toRightOf都指定为@id/first
为了比较明显,把第一个控件的字体设大,为30sp。
效果如下:
对齐的不再是边缘,而是字体的基准线。
3) 与父控件边缘对齐
我们去掉第二个控件,将第一个控件设置以下属性:
注意:这些属性的值不再是某控件的id,而是true或false
layout_alignParentRight
把当前控件的右边缘对齐到父控件的右边缘。
<TextView
android:id="@+id/first"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#FF0000"
android:textSize="30sp"
android:layout_alignParentRight="true"
android:text="第一个控件" />
layout_alignParentLeft
把当前控件的左边缘对齐到父控件的左边缘。
如果我同时设定layout_alignParentRight和layout_alignParentLeft都为true,会出现什么情况呢?
它的效果会叠加,即左边缘对齐父控件的左边缘,右边缘对齐父控件的右边缘。
layout_alignParentTop
把当前控件的上边缘对齐到父控件的上边缘。
理同layout_alignParentRight,可与其他三个属性叠加。
比如可设置左上对齐,或右上对齐。
layout_alignParentBottom
把当前控件的右边缘对齐到父控件的右边缘。
理同layout_alignParentRight,可与其他三个属性叠加。
比如可设置左下对齐,或右下对齐。
4) 与父控件中央对齐
layout_centerInParent
把当前控件对齐到父控件垂直和水平的中间位置。
layout_centerHorizontal
把当前控件对齐到父控件水平的中间位置。
layout_centerVertical
把当前控件对齐到父控件垂直的中间位置。
3.相对布局的新属性(Android4.2)
为了使用这些新属性,项目新建时,必须把最低的兼容属性也调整到4.2,否则使用不了这些属性。
layout_alignStart
把当前控件对齐到指定控件的起始位置。
<TextView
android:id="@+id/first"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#FF0000"
android:text="@string/hello_world" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#00FF00"
android:layout_alignEnd="@id/first"
android:text="abc" />
可以和layout_below一起用:
layout_alignEnd
把当前控件对齐到指定控件的结束位置。
和layout_below一起用时的效果:
layout_alignParentStart
把当前控件的头部对齐到父控件的开始位置。
值为true或false。
layout_alignParentEnd
把当前控件的尾部对齐到父控件的尾部。
值为true或false。
4.综合运用
来个实用的例子:
实现这个界面之前,先记住两个之前没有提过的东西:
1.内容居中
android:gravity="center"
2.文本框
EditText。
EditText有个属性叫hint,表示文本框在未输入前的提示信息:
android:hint="请输入内容"
还有个属性叫inputType,表示输入的类型,如文本(text)、日期(date)、日期时间(datetime)、数字(number)、电话(phone)、密码(textPassword)等等。
android:inputType="textPassword"
动手做一做吧。
六、TimePicker
1.布局文件的定义
<TimePicker
android:id="@+id/timeId"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
效果如下图:
2.Acitivity中的使用
声明这个变量
private TimePicker timePicker;
找到这个控件
timePicker = (TimePicker) findViewById(R.id.timeId);
3.OnTimeChangedListener监听器
定义这个监听器:
class Listener implementsOnTimeChangedListener{
@Override
public voidonTimeChanged(TimePicker view, int hourOfDay, int minute) {
System.out.println("hour:"+hourOfDay+",minute:"+minute);
}
}
绑定到之前的控件:
Listener Listener=new Listener();
timePicker.setOnTimeChangedListener(Listener);
观察未实现的方法,有三个参数:
第二个参数hourOfDay表示用户选择的小时
第三个参数minute表示用户选择的分钟
4.24小时制
用一行代码可以做到:
timePicker.setIs24HourView(true);
5.选定以后提交
如果不要一直变化,而要用户选定以后再点确定提交,怎么做呢?
先加个Button:
<Button
android:id="@+id/submit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="确定"
android:layout_below="@id/timeId"
/>
在Activity里声明它
private Button submit;
找出它
submit = (Button) findViewById(R.id.submit);
定义一个OnClickListener的监听器
class listener2 implementsOnClickListener{
@Override
public void onClick(View v) {
int Hour = timePicker.getCurrentHour();
int Minute = timePicker.getCurrentMinute();
System.out.println("hour:"+Hour+",minute:"+Minute);
}
}
int Hour = timePicker.getCurrentHour();表示获取当前选择的小时数。
int Minute = timePicker.getCurrentMinute();表示获取当前选择的分钟数。
绑定这个监听器到Button上。
listener2 listener2=new listener2();
submit.setOnClickListener(listener2);
6.设定初始时间
TimePicker默认显示当前时间。可以设置:
timePicker.setCurrentHour(10);
timePicker.setCurrentMinute(00);
七、DatePicker
1.布局文件的定义
定义一个DatePicker和一个Button
<DatePicker
android:id="@+id/datePicker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<Button
android:id="@+id/submit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/datePicker"
android:text="提交"
/>