资源描述
2013年1月11日14:29:53
第二章 android应用的界面编程
2.1界面编程与视图组件
2.1.1视图组件与容器组件
Android应用的所有UI组件都继承了View类
View类还有一个重要的子类:ViewGroup,但ViewGroup通常作为其他组件的容器使用
Android的所有UI组件都是建立在View、ViewGroup基础之上的,android采用了“组合器”设计模式来设计View和ViewGroup:ViewGroup是View的子类,因此ViewGroup也是可被当成View使用。对于一个android应用的图形用户界面来说,ViewGroup作为容器来盛装其他组件,而ViewGroup里除了可以包含普通View组件外,还可以再次包含ViewGroup组件
View类的XML属性、相关方法和说明
ViewGroup继承了View类,当然也可以当成普通View来使用,但是ViewGroup主要还是当成容器类使用。但由于ViewGroup是一个抽象类,因此实际使用通常总是使用ViewGroup的子类来作为容器。
2.1.2使用XML布局文件控制UI界面
2.1.3在代码中控制UI界面
如果再代码中控制UI界面,那么所有的UI组件都将通过new关键字创建出来,然后以合适的方式“搭建”在一起即可。
public class Test2_1 extends Activity {
//创建时回调函数
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//创建一个线性布局管理器
LinearLayout layout=new LinearLayout(this);
//设置该Activity显示layout
super.setContentView(layout);
layout.setOrientation(LinearLayout.VERTICAL);
//创建一个TextView Button
final TextView textView=new TextView(this);
textView.setText("12345678");
Button button=new Button(this);
button.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT));
button.setText("按钮");
layout.addView(textView);
layout.addView(button);
//为按钮绑定监听事件
button.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
textView.setText("被点击了232345");
}
});
}
}2.1.4使用XML布局文件和Java代码混合控制UI界面
把变化小、行为比较固定的组件放在XML布局文件中管理
那些变化较多、行为控制比较复杂的组件则交给Java代码来管理
public class Test2_2_1 extends Activity {
int []image=new int[]{
R.drawable.fengjing01,
R.drawable.fengjing02,
R.drawable.fengjing03,
R.drawable.fengjing04,
R.drawable.fengjing05,
R.drawable.fengjing06,
R.drawable.fengjing07,
R.drawable.fengjing08,
R.drawable.fengjing09,
R.drawable.fengjing10,
};
int current=0;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test2_2_1);
//获取布局容器
LinearLayout linearLayout=(LinearLayout)findViewById(R.id.root);
//创建ImageView
final ImageView imageView=new ImageView(this);
imageView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,ViewGroup.LayoutParams.FILL_PARENT));
linearLayout.addView(imageView);
//初始化显示第一张
imageView.setImageResource(image[0]);
imageView.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
if(current>=9)
{
current=-1;
}
imageView.setImageResource(image[++current]);
}
});
}
}
2.1.5开发自定义View
View组件他只是一个矩形的空白区域,里面没有内容。
当开发者打算派生出自己的UI组件时,首先定义一个继承View基类的子类,然后重写View类的一个或多个方法,通常可以被用户重写的方法如下:
-》构造器:重写构造器是定制View的最基本方式,当Java代码创建一个View实例,或根据XML布局文件加载并构建界面时需要调用该构造器。
-》onFinishInflate():这是一个回调方法,当应用从XML布局文件加载该组件并利用它来构建界面之后,该方法就会被回调
-》onMeasure(int,int):调用该方法来检测View组件及它所包含的所有子组件的大小
-》onLayout(boolean,int,int,int,int):当该组件需要分配其子组件的位置、大小时,该方法就会被回调
-》onSizeChanged(int,int,int,int):当该组件的大小被改变时回调该方法
-》onDraw(Canvas):当该组件将要绘制它的内容时回调该方法进行绘制
-》onKeyDown(int,KeyEvent):当某个键被按下时触发该方法
-》onKeyUp(int,KeyEvent):当松开某个键时触发该方法
-》onTrackballEvent(MotionEvent):当发生轨迹球事件时触发该方法
-》onTouchEvent(MotionEvent):当发生触摸屏事件时触发该方法
-》onWindowFocusChanged(boolean):当该组件得到、失去焦点时触发该方法
-》onAttachedToWindow():当把该组件放入某个窗口时触发该方法
-》onDetachedFromWindow():当把该组件从某个窗口上分离时触发该方法
-》onWindowVisibilityChanged(int):当包含该组件的窗口的可见性发生改变时触发该方法
以上方法,根据业务要求重写部分方法
实例:跟随手指的小球:
为了实现一个跟随手指的小球,开发自定义的UI组件,这个组件将会在指定位置绘制一个小球,这个位置可以动态改变。当手指移动,程序监听这个手机动作,并把手指动作的位置传入自定义的UI组件,并通知该组件重绘即可。
public class DrawView extends View {
public float currentx=40;
public float currtney=50;
public DrawView(Context context) {
super(context);
}
@SuppressLint("DrawAllocation")
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
//创建画笔
Paint p=new Paint();
//设置画笔的颜色
p.setColor(Color.RED);
//绘制一个小圆
canvas.drawCircle(currentx, currtney, 15,p);
}
}
public class Test2_3 extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test2_1);
LinearLayout linearLayout=(LinearLayout)findViewById(R.id.root);
final DrawView drawView=new DrawView(this);
//设置自定义组件的最大宽度、高度
drawView.setMinimumWidth(300);
drawView.setMinimumHeight(500);
//绑定监听事件
drawView.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
drawView.currentx=event.getX();
drawView.currtney=event.getY();
drawView.invalidate();
return true;
}
});
linearLayout.addView(drawView);
}
}
2.2布局管理器
为了更好地管理android应用的用户界面的各组件,android提供了布局管理器。通过使用布局管理器,android应用的图形用户界面具有良好的平台无管性
Android的布局管理器本身就是一个UI组件,所有的布局管理器都是ViewGroup的子类
2.2.1线性布局
线性布局由LinearLayout类来代表,它们都会将容器里的组件一个挨着一个地排列起来。LinearLayout不仅可以控制各组件横向排列,也可以控制各组件纵向排列(通过设置android:orientation属性控制)
LinearLayout的常用XML属性及相关方法
android:gravity属性中多个属性之间用竖线隔开,但竖线前后千万不能出现空格
设置布局管理器内组件的对齐方式(在布局的位置呈现方式)
android:gravity=”bottom|center_horizontal”底部、居中对齐
android:gravity=”right|center_vertical”居右、水平
Android:orientation设置布局管理器内组件的排列方式(组件排列方式)
horizontal水平排列
vertical垂直排列、默认值
2.2.2表格布局
表格布局有TableLayout多代表,表格布局采用行、列的形式来管理UI组件,TableLayout并不需要明确包含多少行、多少列,而是通过TableRow、其它组件来控制表格的行数和列数。
每次向TableLayout中添加一个TableRow,该TableRow就是一个表格行,TableRow也是容器,因此她也可以不断地添加其它组件,没添加一个子组件该组件表格就增加一列。
在表格布局中,列的宽度有该列中最宽的那个单元格决定,整个表格布局的宽度则取决于父容器的宽度(默认总是沾满父容器本身)
在表格布局管理器中,可以为单位格设置如下三种行为方式:
-》Shrinkable:如果某列被设为Shrinkable,那么该列的所有单元格的宽度可以被收缩,以保证该表格能适应父容器的宽度
-》Stretchable:如果某个列被设为Stretchable,那么该列的所有单元格的宽度可以被拉伸,以保证组件能完全填满表格空余空间
-》Collapsed:如果某列被设为Collapsed,那么该列的所有单元格会被隐藏
TableLayout继承了LInearLayout,因此它完全可以支持LinearLayout所支持的全部XML属性,以及以下属性:
2.2.3帧布局
帧布局由FrameLayout所代表,FrameLayout直接继承了ViewGroup
帧布局容器为每个加入其中的组件创建一个空白的区域(称为一帧),所有每个子组件占据一帧,这些帧都会根据gravity属性执行自动对齐
FrameLayout常用的XML属性及相关方法说明
2013年1月14日10:09:13
2.2.4布局相对
相对布局由RelativeLayout代表,相对布局容器子组件的位置总是相对兄弟组件、父容器来决定的,因此这种布局方式称为相对布局。
如果A组件的位置是由B组件的位置来决定的,Android要求定义B组件,再定义A组件。
RelativeLayout可支持的两个XML属性
为了控制布局容器中各个子组件的布局分布,RelativeLayout提供了一个内部类:RelativeLayout.LayoutParam,该类提供了大量的XML属性来控制RelativeLayout布局容器中子组件的布局分布。
RelativeLayout.LayoutParams里只能设为true、false的XML属性如下:
RelativeLayout.LayoutParams里只能设为boolean值的属性
RelativeLayout.LayoutParams里属性值为其它UI组件的XML属性如下:
2.2.5绝对布局
绝对布局由AbsoluteLayout代表。就是android不提供任何布局控制,而是由开发人员自己通过X坐标、Y坐标来控制组件的位置。当使用AbsoluteLayout作为布局容器时,布局容器不再管理子组件的位置、大小-这些都需要开发人员自己控制。
2.3基本界面组件
2.3.1文本框(TextView)与编辑框(EditText)的功能和用法
从功能上来看,TextView其实就是一个文本编辑器,只是android关闭了它的文字编辑功能。如果开发者想要定义一个可以编辑内容的文本框,则可以使用它的子类:EditText。EditText允许用户编辑文本框中的内容。
TextView派生出的子类
TextView:CheckedTextView、EditText、Chronometer、Button、DigitalChock
EditText子类:AutoCompleteTextView、ExtractEditText
AutoCompleteTextView子类:MultiAutoCompleteTextView
Button子类:CompoundButton
CompoundButton子类:CheckBox、Raidobutton、ToggleButton
TextView和EditText具有很多相似之处,它们之间最大区别在于TextView不允许用户编辑文本内容,而EditText则允许用户编辑文本内容。
TextView的XML属性及相关方法的说明
表中android:autoLink属性值是如下几个属性值的一个或几个,多个属性值之间用竖线隔开
-》nane:不设置任何超链接
-》web:(对应于Linkify.WEB_URLS):将文本中的URL地址转换为超链接
-》email(对应于LInkify.EMAIL_ADDRESSES):将文本中的E-mail地址转换为超链接
-》phone(对应于LInkify.PHONE_NUBERS):将文本中的电话号码转换为超链接
-》map(对应于LInkify.MAP_ADDRESSES):将文本中的街道地址转换为超链接
-》all:相当于指定weblemailphonelmap.
表中android:ellipsize属性可支持如下几个属性值
-》none:不进行任何处理
-》start:在文本开头部分进行省略
-》middle:在文本中间部分进行省略
-》end:在文本结尾进行省略
-》marquee:在文本结尾处以淡出的方式省略
实例:不同字体、不同颜色的文本、URL(2.3.6)
实例:带边框、图片的TextView(2.3.7)
实例:用户友好的输入界面(2.3.8)
2.3.2按钮(Button)与图片按钮(ImageButton)组件的功能和用法
Button继承了TextView,ImageButton继承了Button。不管是Button还是ImageButton,它们的功能都是很单一的,主要是在UI界面上生成一个按钮,该按钮可以供用户单击,当用户单击按钮时,按钮会触发一个Onclick事件。
Button与ImageButton的区别在于:Button生成的按钮上显示文字,而ImageButton上则显示图片。需要指出的是:为Imagebutton按钮指定android:text属性没用,即使指定了该属性,图片按钮也不会显示文字。
实例:按钮、圆形按钮、带文字的图片按钮(2.3.9)
2.3.3使用9Patch图片作为按钮背景
为了实现只缩放图片中某个部分的效果,我们要借助于9Patch图片来实现。
2013年1月15日12:26:44
2.3.4单选按钮(RadioButton)和复选框(CheckBox)介绍与应用
单选按钮和复选框是所有用户界面中最普通的UI组件android中的RadioButton和CheckBox都继承了Button按钮,因此它们都可直接使用Button支持的各种属性和方法。
RadioButton、Check与普通按钮不同的是,它们多了一个可选中的功能,因此RadioButton、Check都可额外指定一个android:check属性,该属性用于指定RadioButton、CheckBox初始时是否被选中。
RadioButton与Check的不同之处在于,一组RadioButton只能选中其中一个,因此RadioButton通常要与RadioGroup一起使用,用于定义一组单选按钮
2.3.5状态开关按钮(ToggleButton)的功能与用法
ToggleButton也是由Button派生出来的。从界面上来看,他与CheckBox复选框非常相似,它们都可以提供两个状态。不过ToggleButton与CheckBox的区别主要体现功能上,ToggleButton通常用于切换程序中的某种状态。
ToggleButton支持的XML属性及相关方法说明
实例:动态控制布局(2.3.11)
2.3.6时钟(AnalogChock和DigitalChock)的功能与用法
时钟UI组件是两个非常简单的组件,DigitalChock本身就是继承了TextView-也就是说它本身就是文本框,只是它里面显示的内容是当前时间,AnalogChock则继承了View组件,它重写了View的OnDraw方法,他会在View上显示模拟时钟
AnalogChock和DigitalChock都会显示当前时间。不同的是,DigitalChock显示数字时钟,可以显示当前的秒数;AnalogChock显示模拟时钟,不会显示当前秒数。
下面的例子简单示范了AnalogChock和DigitalChock的用法(2.3.12)
Android还提供了一个计时器组件:Chronometer,该组件与DigitalClock都继承了TextView,因此它们都会显示一段文本。但Chronometer并不显示当前时间,它显示的是从某个起始时间开始,一共过去了多长时间。
Chronometer的用法也非常简单,他只提供了一个android:format属性,用于指定计时器的计时格式。除此之外,Chronometer支持如下常用方法
-》setBase(long base):设置计时器的起始时间
-》setFormat(String format):设置显示时间的格式
-》start():开始时间
-》stop():结束时间
-》setOnChronometerTickListener(Chronometer.OnChronometerTickListener listener):为计时器绑定事件监听器,当计时器改变时触发该监听器。
下面的程序简单示范了Chronometer用法:该程序界面中定义了一个Chronometer组件个一个Button组件,当用户单击Button时系统开始计时,当计时超过20秒时停止。(2.3.13)
2.3.7图像视图(ImageView)的功能和用法
ImageView继承了View组件,它的主要功能是用于显示图片,任何Drawable对象都可以用ImageView来显示。
以下显示ImageView支持的XML属性及相关方法的说明
上面的android:scaleType属性可指定如下属性值
-》matrix(ImageView.ScaleType.MATRIX):使用matrix方式进行缩放。
-》fitXY(ImageView.ScaleType.FIT_XY):对图片横向、纵向独立缩放,使得该图片完全适应ImageView,图片的纵横比可能会改变。
-》fitStart(ImageView.ScaleType.FIT_START):保持纵横比缩放图片,直到该图片能完全显示在ImageView中(图片较长的边长与ImageView相应的边长相等),缩放完成后将该图片放在ImageView的左上角。
-》fitCenter(ImageView.ScaleType. FIT_CENTER):保持纵横比缩放图片,直到该图片能完成后将该图片放在ImageView中(图片较长的边长与ImageView相应的边长相等),缩放完成后将该图片放在ImagView的中央。
-》fitEnd(ImageView.ScaleType. FIT_END):保持纵横比缩放图片,直到该图片能完成后将该图片放在ImageView中(图片较长的边长与ImageView相应的边长相等),缩放完成后将该图片放在ImagView的右下角。
-》center(ImageView.ScaleType.FIT_CENTER):保持纵横比缩放图片。以使得任何缩放。
-》centerCrop(ImageView.ScaleType.CENTER_CROP):保持纵横比缩放图片,以使得图片能任何缩放。
-》centerInside(ImageView.ScaleType.CENTER_INSIDE):保持纵横比缩放图片,以使得ImageView能完全显示该图片。
实例:图片浏览器(2.3.14)
2.4高级界面组件
2.4.1自动完成文本框(AutoCompleteTextView)的功能和用法
自动完成文本框从EditTex派生而出,实际上他也是一个文本编辑框,但它比普通编辑框多了一个功能:当用户输入一定字符之后,自动完成文本框会显示一个下拉菜单,供用户从中选择,当用户选择某个菜单项之后,AutoCompleteTextView按用户选择自动填写文本框。
使用AutoCompleteTextView很简单,只要为他设置一个Adapter,该Adapter封装了AutoCompleteTextView预设的提示文本。
实例(2.4.1)
2.4.2Spinner的功能和用法
Spinner组件其实就是一个列表选项框。Android的列表选择框并不是需要显示下拉列表的,而是相当于弹出一个菜单供用户选择。
如果开发者使用Spinner时已经可以确定下拉列表框里的列表项,则完全不需要编写代码,只要为Spinner指定android:entries属性即可实现一个下拉列表项:
实例:一般列表项的Spinner(2.4.2)列表项由XML文件给出
实例:不存储以及自定义的列表项的Spinner(2.4.3)
2.4.3日期、时间选项器(DataPicker和TimePicker)的功能和用法
DataPicker和TimePicker是两个比较易用的控件3,它们从FrameLayout派生而来,其中DataPicker供用户选择日期;而TimePIcker则供用户选择时间。
DataPicker和TimePIcker在FrameLayout的基础上提供了一些方法来获取当前用户所选择的日期、时间;如果程序需要获取用户选择的日期、时间,则可以通过DataPicker添加OnDataChangedListener进行监听、为TimePicker添加OnTimerChangedListener进行监听来实现。
实例:用户选择日期、时间(2.4.4)
2.4.4进度条(ProgressBar)的功能和用法
进度条也是UI界面中的一种非常实用的组件,通常用于向用户显示某个耗时操作完成的百分比。因此进度条可以动态地显示进度,因此避免长时间地执行某个耗时操作时,让用户感觉程序失去了响应,从而更好地提高用户的友好性。
Android支持几种风格的进度条,通过style属性可以为ProgressBar指定风格。该属性可支持如下几个属性值。
-》@android:style/Widget.ProgressBar.Horizontal:水平进度条。
-》@android:style/Widget.ProgressBar.inverse:不断跳跃、旋转画面的进度条
-》@android:style/Widget.ProgressBar.Large:大进度条
-》@android:style/Widget.ProgressBar.Large.Inverse:不断跳跃、旋转画面的大进度条。
-》@android:style/Widget.ProgressBar..Small:小进度条
-》@android:style/Widget.ProgressBar.Small.Inverse:不断跳跃、旋转画面的小进度条
ProgressBar常用的XML属性
上面中android:progressDrawable用于指定进度条的轨道的绘制形式,该属性可指定为一个LayoutDrawable对象(该对象可通过在XML文件中用<layer-list>元素进行配置)的引用。
ProgressBar提供了如下方法操作进度:
-》setProgress(int):设置进度的完成百分比
-》incrementProgressBy(int):设置进度条的进度增加或减少。当参数为整数时进度条增加,当参数为负数时进度条减少。
实例:2.4.5
2013年1月16日13:36:01
实例:显示在标题上的进度条(2.4.6)
还有一种进度条,它可以直接在窗口标题上显示,这种进度条甚至不需要使用ProgressBar组件,它是直接由Activity的方法启动用的,为了在窗口上显示进度条,需要经过如下两步。
-》调用Activity的requestWindowFeature()方法,该方法根据传入的参数可启用特定的窗口特性,例如传入Window.FEATURE_INDETERMINATE_PROGRESS在窗口上显示不带进度的进度条;传入Window.FEATURE_PROGRESS则显示带进度的进度条。
-》调用Activity的setProgressBarVisibility(boolean)或setProgressBarIndeterminateVisibility(boolean)方法即可控制进度条的显示和隐藏。
2.4.5拖动条(SeekBar)的功能和用法
2013年1月16日21:16:23
拖动条和进度条非常相似,只是进度条采用颜色填充来表明进度完成的程序,而拖动条则通过滑块来改变值,因此拖动条通常用于对系统的某种值进行调节,比如调节声音等。
SeekBar允许用户改变拖动条的滑块外观,改变滑块外观通过如下属性来指定。
Android:thumb:指定一个Drawable对象,该对象将作为自定义滑块。
为了让程序能响应拖动条滑块位置的改变,程序可以考虑为他绑定一个OnSeekBarChangeListener监听器。
实例:通过拖动条滑块来改变图片的透明度(2.4.7)
2.4.6星级评分条(RatingBar)的功能和用法
星级评分条与拖动条十分相似,他们甚至有相同的父类:AbsSeekBar。实际上星级评分条与拖动条的用法、功能都十分接近:他们都允许用户通过拖动条来改变进度。RatingBar与SeekBar最大区别在于:RatingBar通过星星来表示进度。
为了让程序能响应星级评分条评分的改变,程序可以考虑为他绑定一个OnRatingBarChangeListener监听器。
以下是星级评分条所支持的常见XML属性
实例:通过星级改变图片的透明度(2.4.8)
2.4.7选项卡(TabHost)的功能和用法
TabHost是一种非常实用的组件,TabHost可以很方便地在窗口上放置多个标签页,每个标签页相当于获得了一个与外部容器相同大小的组件摆放区域。通过这种方式,就可以在一个容器里放置更多组件,例如许多手机系统都会在同一个窗口定义多个标签页来显示通话记录,包括“未接电话”“已接电话”等。
TabHost仅仅是一个简单的容器,他提供了如下两个方法来创建选项卡、添加选项卡。
-》newTabSpec(String tag):创建选项卡
-》addTab(TabHost.TabSpec tabSpec):添加选项卡
使用TabHost的一般步骤为:
-》在界面布局中定义TabHost组件,并为该组件定义选项卡的内容
-》Activity应该继承TabActivity
-》调用TabActivity的getTabHost()方法获取TabHost对象
-》通过TabHost对象的方法来创建选项卡、添加选项卡
如果程序需要监控TabHost里当前标签页的改变,可以为他设置TabHost.OnTabChangeListener监听器。
实例:通话记录界面(2.4.9)
2013年1月17日9:05:30
2.4.8滚动视图(ScrollView)的功能和用法
滚动视图由FrameLayout拍色而出,他就是一个用于为普通组件添加滚动条的组件。ScrollView里最多只能包含一个组件,而ScrollView的作用就是为该组件添加垂直滚动条。
默认情况下,ScrollView只是为其它组件添加垂直滚动条,如果应用需要添加水平滚动条,则可借助于另一个滚动条视图:HorizontalScrollView来实现。ScrollView与HorizontalScrollView的功能基本相似,只是前者添加垂直滚动条,后者添加水平滚动条。
实例:可垂直和水平滚动条的视图(2.4.10)
2.4.9列表视图(ListView和ListActivity)
listView是手机系统中使用非常广泛的一种组件,它以垂直列表的形式显示所有列表项。
创建ListView有两种方式:
-》直接使用ListView进行创建
-》让Activity继承LIstView
一旦在程序中获得了LisView之后,接下来就需要为Listiew 设置他要显示的列表项了,在这一点上,ListView与前面介绍的AutoComplete、Spinner类似,他们都需要一个供显示的列表项,这就需要借助于内容Adapter了,内容Adapter负责提供需要显示的列表项。
提示:AutoCompleteTextView、Spinner、ListView采用Adapter提供数据的设计,其实就是MVC的典型应用,此时的AutoCompleteTextView、Spinner、ListView只是View部分(实际上还包括Controller),他们只负责更新和显示,而显示的数据则由Model部分(Adapter)提供。
ListView额外提供了下表常用的XML属性:
实例:改变分割线、基于数组的ListView(2.4.11)
程序中创建了一个ArrayAdapter,创建ArrayAdapter时必须指定一个textViewResourceId,该参数决定每个列表项的外观形式。Android为该属性提供了如下属性值。
-》simple_list_item_1:每个列表项都是一个普通的TextView。
-》simple_list_item_1:每个列表项都是一个普通的TextView(字体稍大)。
-》simple_list_item_checked:每个列表项都是一个已勾选的列表项。
-》simple_list_item_multiple:每个列表项都是带多选框的文本。
-》simple_list
展开阅读全文