1.1.1.卷轴视图ScrollView
受到手机屏幕大小的限制,有时候要显示的内容在一个屏幕上显示不完。我们希望可以通过滑动屏幕的方式显示更多的内容。这个时候,我们就需要用到卷轴视图ScrollView了,下面我们来通过一个实例看一下如何使用ScrollView。在5.2.1的工程里新增加一个类,命名为ScrollViewActivity,内容如下:
ScrollViewActivity.java代码清单5-23:
/**
* ScrollView展示类
*
* @author孔明
*/
publicclass ScrollViewActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 设置标题
setTitle("ScrollViewActivity");
// 指定布局文件
setContentView(R.layout.scroll_view);
}
}
这个类的代码非常简单,只是做了一个简单的设置布局文件的操作,让我们看一下布局文件,如下所示:
scroll_view.xml代码清单5-23:
<?xml version=“1.0” encoding=“utf-8”?>
<ScrollViewxmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:ems="6"
android:text="@string/long_text"/>
</LinearLayout>
</ScrollView>
布局文件里,根结点就是一个ScrollView,里面定义了一个线性布局,线性布局里面又包含了一个TextView,这些都很好理解,这里需要注意的是ScrollView里面只能有一个直接的子结点,也就是说上面的布局文件中,如果再增加任何一个与LinearLayout平级的子结点就是错误的。
我们在string.xml定义了一个很长的字符串,命名为long_text,内容是“原始人工作室”的不断重复,因为这是六个字,我们设置ems的值为6(含义是TextView每一行的宽度为6个字符)。因此,运行程序后我们应该能看到每一行的内容都是“原始人工作室”,并且重复很多行。往上拖动屏幕,可以发现会有更多的行出现。实际的运行截图如5-35所示,与我们所期待的一模一样:
图5-35 ScrollView组件示意图
在本例中,我们在ScrollView里面只包含了一个TextView,在实际的应用中,我们在LinearLayout中可以包含许许多多的控件。
孔明:ScrollView实现的效果和PC机上的上下滑动网页的效果是一样的!额……好吧,这是一句没什么用的废话…… |
1.1.2.列表ListView
列表ListView可能是Android里面最常用的一个控件了。ListView实现简单但是能完成许多复杂的界面,下面我们从三个小例子中来学习ListView。在工程里面新建一个类ListViewActivity,在该类里面我们定义了三个按钮分别将我们的程序导向三个小例子,每一个例子使用不同的适配器Adapter来实现的,代码如下:
ListViewActivity.java代码清单5-24:
/**
* ListView示例类
* @author孔明
*/
publicclass ListViewActivity extends Activity {
// 定义三个引导按钮,分别对应我们要讲到的三种情况
// 使用ArrayAdapter适配的ListView
private Button mArrayBtn;
// 使用SimpleCursorAdapter适配的ListView
private Button mSimpleCursorBtn;
// 使用SimpleAdapter适配自定义ListView
private Button mSimpleBtn;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//设置标题
setTitle("ListViewActivity");
//指定布局文件
setContentView(R.layout.list_view);
// 通过id来加载按钮,并设置监听器
mArrayBtn = (Button) findViewById(R.id.array_list_btn);
mArrayBtn.setOnClickListener(mArrayBtnListener);
mSimpleCursorBtn = (Button) findViewById(R.id.simplecursor_list_btn);
mSimpleCursorBtn.setOnClickListener(mSimpleCursorBtnListener);
mSimpleBtn = (Button) findViewById(R.id.simple_list_btn);
mSimpleBtn.setOnClickListener(mSimpleBtnListener);
}
// mArrayBtn的监听器
private Button.OnClickListener mArrayBtnListener = new Button.OnClickListener() {
public void onClick(View v) {
//启动ArrayListViewActivity
Intent intent = newIntent();
intent.setClass(ListViewActivity.this, ArrayListViewActivity.class);
startActivity(intent);
}
};
// mSimpleCursorBtn的监听器
private Button.OnClickListener mSimpleCursorBtnListener = new Button.OnClickListener()
{
public void onClick(View v) {
//启动SimpleCursorListActivity
Intent intent = newIntent();
intent.setClass(ListViewActivity.this, SimpleCursorListActivity.class);
startActivity(intent);
}
};
// mSimpleBtn的监听器
private Button.OnClickListener mSimpleBtnListener = new Button.OnClickListener() {
public void onClick(View v) {
//启动SimpleListActivity
Intent intent = newIntent();
intent.setClass(ListViewActivity.this, SimpleListActivity.class);
startActivity(intent);
}
};
}
运行后,截图如5-36所示:
图5-36 ListView组件示意图
我们先来看第一个按钮导向的ArrayListViewActivity。在下面的例子中,我们使用了ArrayAdapter,并讲解了ListView的几个重要的监听器如何使用。ArrayListViewActivity的具体代码如下:
ArrayListViewActivity.java代码清单5-25:
/**
* 使用ArrayAdapter进行适配的ListView示例
* @author孔明
*/
publicclass ArrayListViewActivity extends Activity {
// 定义一个ListView作为成员变量
private ListView mListView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 新建一個ListView
mListView = newListView(this);
// 设置ListView的适配器为ArrayAdapter
// 其中simple_expandable_list_item_1为Android自带的布局
mListView.setAdapter(new ArrayAdapter<String>(this,
android.R.layout.simple_expandable_list_item_1,getData()));
// 设置点击动作的监听器
mListView.setOnItemClickListener(mItemClickListener);
// 设置长按动作的监听器
mListView.setOnItemLongClickListener(mItemLongClickListener);
// 设置选择动作监听器
mListView.setOnItemSelectedListener(mItemSelectedListener);
// 设置长按菜单动作的监听器
mListView.setOnCreateContextMenuListener(mCreateContextMenuListener);
// 设置布局为ListView
setContentView(mListView);
}
// 私有函数,填充数据
private List<String> getData() {
List<String> data = new ArrayList<String>();
// 通过调用getString方法得到定义在string.xml文件中的字符串
data.add(getString(R.string.words));
data.add(getString(R.string.drawing));
data.add(getString(R.string.legend));
data.add(getString(R.string.fighter));
return data;
}
// 实现点击动作的监听器
private OnItemClickListener mItemClickListener = new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
TextView tv = (TextView)view;
// 设置一下标题,作为点击动作
setTitle("点击了" + tv.getText());
}
};
// 实现长按菜单动作的监听器
private OnCreateContextMenuListener mCreateContextMenuListener = new
OnCreateContextMenuListener() {
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfomenuInfo) {
// 设置菜单的标题
menu.setHeaderTitle("长按菜单");
// 增加两个菜单
menu.add(0, 0, 0, "我喜欢!");
menu.add(0, 1, 0, "我超级喜欢!");
}
};
// 实现长按动作的监听器
private OnItemLongClickListener mItemLongClickListener = new
OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view,
int position, long id) {
TextView tv = (TextView)view;
// 设置一下标题,作为点击动作
setTitle("长按了" + tv.getText());
// 返回false表示该长按事件没有被消耗掉
returnfalse;
}
};
// 实现选择动作的监听器
private OnItemSelectedListener mItemSelectedListener = new OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view,
int position, long id) {
TextView tv = (TextView)view;
// 显示一个Toast作为选择时的动作
Toast.makeText(ArrayListViewActivity.this,
"选择了" + tv.getText(), Toast.LENGTH_SHORT).show();
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
};
@Override
public boolean onContextItemSelected(MenuItem item) {
// 设置一下标题,作为菜单被点击的结果
if(item.getItemId() == 0){
setTitle("你喜欢!");
} else {
setTitle("你超级喜欢!");
}
returnsuper.onContextItemSelected(item);
}
}
在onCreate()方法里面新建了一个ListView并保存到我们定义的成员变量里面,并为这个ListView设置了一个ArrayAdapter,数据来自于getData()方法,而布局使用的是Android自带的布局,并为ListView设置了四个监听器,分别是点击监听器,选择监听器,长按监听器和长按菜单监听器。
孔明:你们注意到了吗?在长按监听器的最后一定要返回false表示长按事件没有被消耗掉,如果返回true的话就会导致后面的长按菜单监听器没有反应。 |
运行我们的程序,首先我们会看到如下5-37的界面:
图5-37 使用ArrayAdapter适配的ListView组件示意图
当我们转动鼠标滚轮选中其中一个的时候,就会触发选择事件,会提示现在选择的是哪一个,如图5-38所示。
图5-38 ListView组件选择事件示意图
同样当我们点击其中一个的时候,也会提示点击的是哪一个,截图5-39所示,标题发生了变为“点击了刀疤鸭传说”。
图5-39 ListView组件点击事件示意图
当我们长按其中的一个的时候,会出现如图5-40中所示界面:
图5-40 ListView组件长按事件示意图
可以看到标题栏上已经显示了当前长按的是哪一个,并且出现了一个菜单,当我们选择其中一个子菜单的时候,出现如图5-41中所示界面:
图5-41 ListView组件子菜单点击事件示意图
标题栏上显示出来了我们选择的子菜单项。当然ListView的监听器还有许多其他的,以上列出的四个是最重要也是最常用的,其他的用法与此类似。在之前的例子当中,我们也提到过ArrayAdapter,这是一类非常简单的数组适配器,而SimpleCursorAdapter是数据库适配器。我们来看下SimpleCursorAdapter到底该如何使用。在下面的例子中,我们读取手机的通讯录的数据库,将名字显示到我们程序的ListView里面,为了能够访问通讯录,我们必须在AndroidMenifest.xml文件里加入相应的权限:
<uses-permissionandroid:name="android.permission.READ_CONTACTS"></uses-permission>
为了便于测试,我们在模拟器的手机通讯录里面新建两个通讯条目,如下图5-42中所示:
图5-42 创建的通讯录
SimpleCursorListActivity类的代码如代码清单5-26所示:
SimpleCursorListActivity.java代码清单5-26:
/**
* SimpleCursorAdapter适配的ListView
*
* @author 关云长
*
*/
public class SimpleCursorListActivity extends Activity {
// 定义一个ListView作为成员变量
private ListView mListView;
@Override
protected void onCreate(BundlesavedInstanceState) {
super.onCreate(savedInstanceState);
// 新建一个ListView
mListView = newListView(this);
// 新建一个与联系人相关联的游标
Cursor cursor = getContentResolver().query(
ContactsContract.Contacts.CONTENT_URI,null, null, null, null);
// 将游标的管理权交给Activity
startManagingCursor(cursor);
// 新建一个SimpleCursorAdapter
ListAdapter listAdapter= new SimpleCursorAdapter(
this,android.R.layout.simple_expandable_list_item_1,
cursor, new String[]{
ContactsContract.Contacts.DISPLAY_NAME},new int[]{android.R.id.text1});
// 设置ListView的Adapter
mListView.setAdapter(listAdapter);
// 设置布局
setContentView(mListView);
}
}
代码中,我们新建了一个ListView和游标,并使得游标与联系人相关联,将游标的管理权交给Activity,新建一个SimpleCursorAdapter,并将这个SimpleCursorAdapter设置为ListView的SimpleCursorAdapter,设置Activity的布局为ListView。
运行程序之后,我们程序显示如图5-43所示:
图5-43 使用SimpleCursorAdapter适配的ListView示意图
还有最后一种类型的适配器,SimpleAdapter,这类的适配器能够发挥最大的灵活性,适合用来做自定义的ListView,下面我们来看下如何实现:
SimpleListActivity.java代码清单5-27:
/**
* 利用SimpleAdapter实现自定义的Listview
* @author孔明
*/
publicclass SimpleListActivity extends Activity {
// 定义一个ListView作为成员变量
private ListView mListView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 新建一个ListView
mListView = newListView(this);
// 新建一个SimpleAdapter
SimpleAdapter adapter = new SimpleAdapter(this,getData(),
R.layout.single_list, new String[] { "title", "info","img" },
newint[] { R.id.title, R.id.info, R.id.img});
// 设置ListView的适配器
mListView.setAdapter(adapter);
// 设置布局
setContentView(mListView);
}
// 返回填充数据
private List<Map<String, Object>> getData() {
List<Map<String, Object>> list = new ArrayList<Map<String,Object>>();
// 第一行的内容
Map<String, Object> map = new HashMap<String, Object>();
// 标题
map.put("title", getString(R.string.words));
// 信息
map.put("info", "背单词很轻松很快乐!");
// 图标
map.put("img", R.drawable.words_logo);
// 加到List里面去
list.add(map);
// 第二行的内容
map = newHashMap<String, Object>();
map.put("title", getString(R.string.legend));
map.put("info", "真的很好玩哦亲!");
map.put("img", R.drawable.legend_logo);
list.add(map);
// 第三行的内容
map = newHashMap<String, Object>();
map.put("title", getString(R.string.drawing));
map.put("info", "发挥你的绘画才艺吧!");
map.put("img", R.drawable.drawing_logo);
list.add(map);
return list;
}
}
我们为每一个ListView当中的一个子项定义了一个ImageView和两个TextView,在程序里面,我们用到了map为ListView的每一个子项来定义View,运行程序,截图如5-44所示:
图5-44 使用SimpleAdapter适配的ListView示意图
我们可以看到正如我们所布局的那样,每一个ListView的子项都有三个View在里面。
1.1.3.标签切换TabView
TabView用于标签之间的切换,下面我们来看一下如何实现这一功能,新增加一个类,命名为TabDemoActivity,代码如下:
TabDemoActivity.java代码清单5-28:
/**
* Tab展示类
* @author孔明
*/
publicclass TabDemoActivity extends TabActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 设置标题
setTitle("TabDemoActivity");
// 返回一个用于放置标签的host
TabHost tabHost = getTabHost();
// 将布局文件定义的界面映射到TabHost里面
LayoutInflater.from(this).inflate(R.layout.tab_demo,
tabHost.getTabContentView(), true);
// 分别设置三个tab的布局
tabHost.addTab(
tabHost.newTabSpec("tab1").setIndicator("tab1").setContent(R.id.view1));
tabHost.addTab(
tabHost.newTabSpec("tab2").setIndicator("tab2").setContent(R.id.view2));
tabHost.addTab(
tabHost.newTabSpec("tab3").setIndicator("tab3").setContent(R.id.view3));
}
}
代码里面,将布局文件映射到TabHost上,TabHost是Tab的容器。然后为TabHost增加了三个Tab,该类对应的布局文件tab_demo.xml为:
tab_demo.xml代码清单5-28:
<?xml version=“1.0” encoding=“utf-8”?>
<FrameLayoutxmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextViewandroid:id="@+id/view1"
android:background="@drawable/blue"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="这里是Tab1里的内容。"/>
<TextViewandroid:id="@+id/view2"
android:background="@drawable/red"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="这里是Tab2的内容"/>
<TextViewandroid:id="@+id/view3"
android:background="@drawable/green"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="这里是Tab3的内容"/>
</FrameLayout>
这里,我们使用了FrameLayout。运行程序,截图如5-45所示:
图5-45 TabView组件示意图
点击不同的Tab可以显示不同的Tab。Tab可以做的更复杂一些,为每一个Tab定义不同的布局,为Tab增加图标等。
孔明:现在有越来越多的应用开始是用TabView组件了,因为TabView组件极大的提高了界面的容量。 |