一、Android应用的界面编程
1、布局管理器
线性布局:LinerLayout
表格布局:TableLayout
相对布局:RelativeLayout
绝对布局:AbsoluteLayout
帧布局:FrameLayout
网格布局:GridLayout(android 4.0新增)
1.线性布局
线性布局不会自动换行,当组件会一个一个的排列到头后,剩下的组件将不会被显示出来。
注:纵向vertical或横向horizontal
2.表格布局(注册界面)
TableLayout属于行和列形式的管理控件,每行为一个TableRow对象,也可以是一个View对象。在TableRow中还可以继续添加其他的控件,每添加一个子控件就成为一列。TableLayout不会生成边框。
Android:collapseColumns 设置指定的列为collapse,如果一列被标示为collapse,该列会被隐藏
Android:shrinkColumns 设置指定的列为shrinkable,如果一列被标示为shrinkable,列的宽度进行收缩,自适应父容器的大小
Android:stretchColumns 设置指定的列为stretchable,如果一列被标示为stretchable ,该列会被拉伸,填充满表格的空白区域
e.g.
android:shrinkColumns="1" //第2列允许收缩
android:stretchColumns="2" //第3列允许拉伸
android:collapseColumns="1" //第2列被隐藏
3.相对布局
相对布局中的视图组件是按相互之间的相对位置来确定的,并不是线性布局中的必须按行或按列单个显示。
4.帧布局(视频播放暂停画面)
帧布局中的每一个组件都代表一个画面,默认以屏幕左上角作为(0,0)坐标,按组件定义的先后顺序依次逐屏显示,后面出现的会覆盖前面的画面。用该布局可以实现动画效果。
5.绝对布局(登陆界面)
注:绝对定位AbsoluteLayout,又可以叫做坐标布局,可以直接指定子元素的绝对位置,这种布局简单直接,直观性强,但是由于手机屏幕尺寸差别比较大,使用绝对定位的适应性会比较差。
在绝对定位中,如果子元素不设置layout_x和layout_y,那么它们的默认值是0,也就是说它会像在FrameLayout一样这个元素会出现在左上角。
6.网格布局(计算器)
网格布局的作用类似于HTML中的table标签,它把整个容器分成raws x columns个网格,每个网格放一个组件,除此之外也可以设置一个组件横跨多少列,一个组件横跨多少行。
e.g.
android:rowCount="6" //6行
android:columnCount="4" //4列
android:layout_columnSpan="4" //横跨4列
Android长度单位详解(dp、sp、px、in、pt、mm、dip)
android中定义的dimension单位有以下这些:
1、px(Pixels ,像素):对应屏幕上的实际像素点。例如,320*480的屏幕在横向有320个象素,在纵向有480个象素。
2、in(Inches ,英寸):屏幕物理长度单位。每英寸等于2.54厘米。例如,形容手机屏幕大小,经常说,3.2(英)寸、3.5(英)寸、4(英)寸就是指这个单位。这些尺寸是屏幕的对角线长度。如果手机的屏幕是3.2英寸,表示手机的屏幕(可视区域)对角线长度是3.2*2.54 = 8.128厘米。读者可以去量一量自己的手机屏幕,看和实际的尺寸是否一致。
3、mm(Millimeters ,毫米):屏幕物理长度单位。
4、pt(Points ,磅):屏幕物理长度单位, 表示一个点,是屏幕的物理尺寸。大小为1英寸的1/72。
5、dp(与密度无关的像素):逻辑长度单位,在 160 dpi 屏幕上,1dp=1px=1/160英寸。随着密度变化,对应的像素数量也变化,但并没有直接的变化比例。
dip:与dp相同,多用于Google示例中。
sp(与密度和字体缩放度无关的像素):与dp类似,但是可以根据用户的字体大小首选项进行缩放。尽量使用dp作为空间大小单位,sp作为和文字相关大小单位。
二、UI组件
1.TextView及其子类
<!--滚动显示文本内容-->
android:ellipsize="marquee"
android:singleLine="true"
android:focusable="true"
android:focusableInTouchMode="true"
android:scrollHorizontally="true"
android:marqueeRepeatLimit="marquee_forever"
<!-- 设置文字阴影 -->
android:shadowDx="10.0" //阴影水平偏移量
android:shadowDy="8.0" //阴影垂直偏移量
android:shadowRadius="3.0" //阴影半径
<!--对邮件、电话增加链接-->
android:autoLink="email|phone"
<!--密码输入-->
android:password="true"
<!--通过checkMark设置该文本框的勾选图标-->
android:checkMark="@drawable/ok"
<!-- 通过android:background指定背景 -->
android:background="@drawable/bg_border" //红色边框,bg_border.xml如下
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 设置背景色为透明色 -->
<solid android:color="#0000"/>
<!-- 设置红色边框 -->
<stroke android:width="4px" android:color="#f00" />
</shape>
<!-- 通过android:drawableLeft绘制一张图片 -->
android:background="@drawable/bg_border2" //圆角边框,渐变背景
<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>
<!--文本框默认提示 -->
android:hint="请填写登录帐号"
<!--只能接收数字密码 -->
android:inputType="numberPassword"
<!-- 数值输入框 -->
android:inputType="number"
<!-- 日期输入框 -->
android:inputType="date"
<!-- 电话号码的输入框 -->
android:inputType="phone"
<!-- 文字带阴影的按钮 -->
android:shadowColor="#aa5"
android:shadowRadius="1"
android:shadowDx="5"
android:shadowDy="5"
<!-- 带文字的图片按钮-->
android:background="@drawable/button_selector"//button_selector.xml如下所示
<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>
<!--单选框 -->
<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>
<!--复选框 -->
<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="绿色" />
<!-- ToggleButton状态开关按钮 -->
<ToggleButton
android:id="@+id/toggle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textOff="横向排列"
android:textOn="纵向排列"
android:checked="true" />
<!-- Switch开关按钮 -->
<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"/>
<!-- 模拟时钟 -->
<AnalogClock
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<!-- 数字时钟 -->
<DigitalClock
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14pt"
android:textColor="#f0f"
android:drawableRight="@drawable/ic_launcher" />
<!-- 模拟时钟,并使用自定义表盘、时针图片 -->
<AnalogClock
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:dial="@drawable/watch"
android:hand_minute="@drawable/hand"/>
<!-- Chronometer计时器 -->
<Chronometer
android:id="@+id/test"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="12pt"
android:textColor="#ffff0000" />
2.ImageView及其子类
<!-- ZoomButton计缩放按钮 -->
<ZoomButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/btn_zoom_down"
android:src="@android:drawable/btn_minus" />
<!-- ZoomControls缩放组件 -->
<ZoomControls
android:id="@+id/zoomControls1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"/>
<!-- QuickContactBadge关联联系人 -->
<QuickContactBadge
android:id="@+id/badge"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:src="@drawable/ic_launcher"/>
QuickContactBadge badge = (QuickContactBadge) findViewById(R.id.badge);
// 将QuickContactBadge组件与特定电话号码对应的联系人建立关联
badge.assignContactFromPhone("15828560682", false);
3. AdapterView及其子类
AdapterView派生了三个子类:AbsListView , AbsSpinner ,和AdapterViewAnimator
3.1、列表视图(ListView)和ListActivity
创建ListView有如下两种方式:
(1)、直接使用ListView创建
(2)、让Activity继承ListActivity(相当于该Activity显示的组件为ListView)
ListView、GridView、Spinner、Gallery等AdapterView都只是容器,而Adapter负责提供每个列表项组件,AdapterView则采用合适的方式显示这些表项。
ListView的功能与用法:
(1)、直接指定ListView的数组资源
<ListView
android:entries="@array/books" // 数组资源
android:divider="#f00" //红色分割线
android:dividerHeight="2px" //分割线宽度
android:headerDividersEnabled="false" //不会在页眉视图前画分隔符
/>
Adapter常见的实现类如下:
<1>.ArrayAdapter:简单、易用,通常用于数组或List集合的多个值包装成的列表项
<2>.SimpleAdapter:不简单、功能强大,可用于将List集合的多个对象包装成列表项
<3>.SimpleCursorAdapter:与SimpleAdapter基本相似,用于包装Cursor提供的数据
<4>.BaseAdapter:通常用于扩展,可以对列表项进行最大限制的定制
(2)、使用ArrayAdapter创建ListView
// 定义一个数组
String[] arr2 = { "Java", "Hibernate", "Spring" , "Android" };
// 将数组包装ArrayAdapter
ArrayAdapter<String> adapter2 = new
ArrayAdapter<String>(this, R.layout.checked_item, arr2);
// 为ListView设置Adapter
list2.setAdapter(adapter2);
(3)、基于ListActivity实现列表
String[] arr = { "孙悟空", "猪八戒", "唐僧" };
// 创建ArrayAdapter对象
ArrayAdapter<String> adapter = new ArrayAdapter<String>
(this,android.R.layout.simple_list_item_multiple_choice, arr);
// 设置该窗口显示列表
setListAdapter(adapter);
//界面布局文件中应该包含id为"@+id/android:list"的ListView
<ListView
android:id="@+id/android:list"
...
/>
(4)、使用SimpleAdapter创建ListView
public class SimpleAdapterTest extends Activity
{
private String[] names = new String[]
{ "虎头", "弄玉", "李清照", "李白"};
private String[] descs = new String[]
{ "可爱的小孩", "擅长音乐的女孩", "擅长文学的女性", "浪漫主义诗人"};
private int[] imageIds = new int[]
{ R.drawable.tiger , R.drawable.nongyu
, R.drawable.qingzhao , R.drawable.libai};
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 创建一个List集合,List集合的元素是Map
List<Map<String, Object>> listItems =
new ArrayList<Map<String, Object>>();
for (int i = 0; i < names.length; i++)
{
Map<String, Object> listItem = new HashMap<String, Object>();
listItem.put("header", imageIds[i]);
listItem.put("personName", names[i]);
listItem.put("desc", descs[i]);
listItems.add(listItem);
}
// 创建一个SimpleAdapter
SimpleAdapter simpleAdapter = new SimpleAdapter(this, listItems,
R.layout.simple_item,
new String[] { "personName", "header" , "desc"},
new int[] { R.id.name, R.id.header , R.id.desc });
ListView list = (ListView) findViewById(R.id.mylist);
// 为ListView设置Adapter
list.setAdapter(simpleAdapter);
// 为ListView的列表项单击事件绑定事件监听器
list.setOnItemClickListener(new OnItemClickListener()
{
// 第position项被单击时激发该方法。
public void onItemClick(AdapterView<?> parent, View view,int position, long id)
{
System.out.println(names[position]+ "被单击了");
}
});
}
}
(5)、扩展BaseAdapter实现不存储列表项的ListView
public class BaseAdapterTest extends Activity
{
ListView myList;
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
myList = (ListView) findViewById(R.id.myList);
BaseAdapter adapter = new BaseAdapter()
{
public int getCount()
{
// 指定一共包含40个选项
return 40;
}
public Object getItem(int position)
{
return null;
}
// 重写该方法,该方法的返回值将作为列表项的ID
public long getItemId(int position)
{
return position;
}
// 重写该方法,该方法返回的View将作为列表框
public View getView(int position, View convertView , ViewGroup parent)
{
// 创建一个LinearLayout,并向其中添加2个组件
LinearLayout line = new LinearLayout(BaseAdapterTest.this);
line.setOrientation(0);
ImageView image = new ImageView(BaseAdapterTest.this);
image.setImageResource(R.drawable.ic_launcher);
TextView text = new TextView(BaseAdapterTest.this);
text.setText("第" + (position +1 ) + "个列表项");
text.setTextSize(20);
text.setTextColor(Color.RED);
line.addView(image);
line.addView(text);
// 返回LinearLayout实例
return line;
}
};
myList.setAdapter(adapter);
}
}
以上方法完全适用于AdapterView的其他类:GridView、Spinner、Gallery、AdapterViewFlipper等。
自动完成文本框(AutoCompleteTextView)的功能和用法
<!-- 定义一个自动完成文本框,指定输入一个字符后进行提示 -->
<AutoCompleteTextView
android:id="@+id/auto"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:completionHint="请选择您喜欢的图书:"
android:dropDownHorizontalOffset="10dp"
android:completionThreshold="1"/>
<!-- 定义一个MultiAutoCompleteTextView组件 -->
<MultiAutoCompleteTextView
android:id="@+id/mauto"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:completionThreshold="1"/>
网格视图(GridView)功能与用法
<GridView
android:horizontalSpacing="1pt"
android:verticalSpacing="1pt"
android:numColumns="4"
android:gravity="center"
……
/>
// 创建一个List对象,List对象的元素是Map
List<Map<String, Object>> listItems = new ArrayList<Map<String, Object>>();
for (int i = 0; i < imageIds.length; i++)
{
Map<String, Object> listItem = new HashMap<String, Object>();
listItem.put("image", imageIds[i]);
listItems.add(listItem);
}
// 创建一个SimpleAdapter
SimpleAdapter simpleAdapter = new SimpleAdapter(this,listItems, R.layout.cell, new String[] { "image" },new int[] { R.id.image1 });
// 使用/layout/cell.xml文件作为界面布局
// 为GridView设置Adapter
grid.setAdapter(simpleAdapter);
可展开的列表组件(ExpandableListView)
<ExpandableListView
android:id="@+id/list"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:childIndicator="@drawable/ic_launcher"
/>
public class ExpandableListViewTest extends Activity
{
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//创建一个BaseExpandableListAdapter对象
ExpandableListAdapter adapter = new BaseExpandableListAdapter()
{
int[] logos = new int[]
{
R.drawable.p,
R.drawable.z,
R.drawable.t
};
private String[] armTypes = new String[]
{ "神族兵种", "虫族兵种", "人族兵种"};
private String[][] arms = new String[][]
{
{ "狂战士", "龙骑士", "黑暗圣堂", "电兵" },
{ "小狗", "刺蛇", "飞龙", "自爆飞机" },
{ "机枪兵", "护士MM" , "幽灵" }
};
// 获取指定组位置、指定子列表项处的子列表项数据
public Object getChild(int groupPosition, int childPosition)
{
return arms[groupPosition][childPosition];
}
public long getChildId(int groupPosition, int childPosition)
{
return childPosition;
}
public int getChildrenCount(int groupPosition)
{
return arms[groupPosition].length;
}
private TextView getTextView()
{
AbsListView.LayoutParams lp = new AbsListView.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, 64);
TextView textView = new TextView(ExpandableListViewTest.this);
textView.setLayoutParams(lp);
textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
textView.setPadding(36, 0, 0, 0);
textView.setTextSize(20);
return textView;
}
// 该方法决定每个子选项的外观
public View getChildView(int groupPosition, int childPosition,
boolean isLastChild, View convertView, ViewGroup parent)
{
TextView textView = getTextView();
textView.setText(getChild(groupPosition, childPosition).toString());
return textView;
}
// 获取指定组位置处的组数据
public Object getGroup(int groupPosition)
{
return armTypes[groupPosition];
}
public int getGroupCount()
{
return armTypes.length;
}
public long getGroupId(int groupPosition)
{
return groupPosition;
}
// 该方法决定每个组选项的外观
public View getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent)
{
LinearLayout ll = new LinearLayout(ExpandableListViewTest.this);
ll.setOrientation(0);
ImageView logo = new ImageView(ExpandableListViewTest.this);
logo.setImageResource(logos[groupPosition]);
ll.addView(logo);
TextView textView = getTextView();
textView.setText(getGroup(groupPosition).toString());
ll.addView(textView);
return ll;
}
public boolean isChildSelectable(int groupPosition,
int childPosition)
{
return true;
}
public boolean hasStableIds()
{
return true;
}
};
ExpandableListView expandListView = (ExpandableListView) findViewById(R.id.list);
expandListView.setAdapter(adapter);
}
}
列表选择框(Spinner)的功能和用法
<!-- 定义了一个Spinner组件,指定该显示该Spinner组件的数组 -->
<Spinner
……
android:entries="@array/books"
android:prompt="@string/tip"
/>
<Spinner
android:id="@+id/spinner"
android:prompt="@string/tip"
......
/>
String[] arr = { "孙悟空", "猪八戒", "唐僧" };
// 创建ArrayAdapter对象
ArrayAdapter<String> adapter = new ArrayAdapter<String>
(this,android.R.layout.simple_list_item_multiple_choice, arr);
// 为Spinner设置Adapter
spinner.setAdapter(adapter);
画廊视图(Gallery)的功能和用法(已经过时,用ViewPager和HorizontalScrollView代替,新平台上尽量少用Gallery组件)
<!-- 定义一个Gallery组件 -->
<Gallery
android:id="@+id/gallery"
android:layout_marginTop="2dp"
android:unselectedAlpha="0.6" //未被选中时的透明度
android:spacing="2pt"
......
/>
BaseAdapter adapter = new BaseAdapter()
{
public int getCount()
{
return imageIds.length;
}
public Object getItem(int position)
{
return position;
}
public long getItemId(int position)
{
return position;
}
// 该方法的返回的View就是代表了每个列表项
public View getView(int position, View convertView, ViewGroup parent)
{
// 创建一个ImageView
ImageView imageView = new ImageView(GallaryTest.this);
imageView.setImageResource(imageIds[position]);
// 设置ImageView的缩放类型
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
// 为imageView设置布局参数
imageView.setLayoutParams(new Gallery.LayoutParams(75, 100));
TypedArray typedArray = obtainStyledAttributes(R.styleable.Gallery);
imageView.setBackgroundResource(typedArray.getResourceId(R.styleable.Gallery_android_galleryItemBackground, 0));
return imageView;
}
};
gallery.setAdapter(adapter);
AdapterViewFlipper的功能与用法
AdapterViewFlipper继承了AdapterViewAnimator,它也会显示Adapter提供的多个View组件,但它每次只能显示一个View组件,程序可通过showPrevious()和showNext()方法控制该组件显示上一个、下一个组件,还可以调用startFlipping()控制它“自动播放”下一个View组件。
----自动播放的图片库----
<AdapterViewFlipper
android:id="@+id/flipper"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:flipInterval="5000" //每个五秒自动切换
android:layout_alignParentTop="true"
/>
BaseAdapter adapter = new BaseAdapter()
{
public int getCount()
{
return imageIds.length;
}
public Object getItem(int position)
{
return position;
}
public long getItemId(int position)
{
return position;
}
// 该方法的返回的View就是代表了每个列表项
public View getView(int position, View convertView, ViewGroup parent)
{
// 创建一个ImageView
ImageView imageView = new ImageView(AdapterViewFlipperTest.this);
imageView.setImageResource(imageIds[position]);
// 设置ImageView的缩放类型
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
// 为imageView设置布局参数
imageView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
return imageView;
}
};
flipper.setAdapter(adapter);
// 显示上一个组件
flipper.showPrevious();
// 显示下一个组件
flipper.showNext();
// 开始自动播放
flipper.startFlipping();
// 停止自动播放
flipper.stopFlipping();
StackView的功能与用法
StackView也是AdapterViewAnimator的子类,它也用于显示Adapter提供的系列View。StackView将会以”堆叠”的方式来显示多个列表项。程序可通过showPrevious()和showNext()方法控制该组件显示上一个、下一个组件。
为了控制StackView显示的View,StackView提供了两种控制方式:
1>.拖走StackView中处于顶端的View,下一个View将会显示出来
2>.将上一个View拖进StackView,将使之显示出来
<StackView
android:id="@+id/mStackView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:loopViews="true" //循环
/>
stackView = (StackView) findViewById(R.id.mStackView);
// 创建一个List对象,List对象的元素是Map
List<Map<String, Object>> listItems = new ArrayList<Map<String, Object>>();
for (int i = 0; i < imageIds.length; i++)
{
Map<String, Object> listItem = new HashMap<String, Object>();
listItem.put("image", imageIds[i]);
listItems.add(listItem);
}
// 创建一个SimpleAdapter
SimpleAdapter simpleAdapter = new SimpleAdapter(this,listItems, R.layout.cell, new String[] { "image" },new int[] { R.id.image1 });
// 使用/layout/cell.xml文件作为界面布局
stackView.setAdapter(simpleAdapter);
// 显示上一个组件
stackView.showPrevious();
// 显示下一个组件
stackView.showNext();
4. ProgressBar及其子类
ProgressBar的用法
<!-- 定义一个大环形进度条 -->
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@android:style/Widget.ProgressBar.Large"
/>
<!-- 定义一个中等大小的环形进度条 -->
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<!-- 定义一个小环形进度条 -->
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@android:style/Widget.ProgressBar.Small"
/>
<!-- 定义一个水平进度条 -->
<ProgressBar
android:id="@+id/bar"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:max="100"
style="@android:style/Widget.ProgressBar.Horizontal"
/>
<!-- 定义一个水平进度条,并改变轨道外观 -->
<ProgressBar
android:id="@+id/bar2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:max="100"
android:progressDrawable="@drawable/my_bar"
style="@android:style/Widget.ProgressBar.Horizontal"
/>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 定义轨道的背景 -->
<item
android:id="@android:id/background"
android:drawable="@drawable/no"
/>
<!-- 定义轨道上已完成部分的样式 -->
<item
android:id="@android:id/progress"
android:drawable="@drawable/ok"
/>
</layer-list>
显示在标题上的进度条
//设置窗口特征:启用显示进度的进度条
requestWindowFeature(Window.FEATURE_PROGRESS); //①
//显示带进度的进度条。
setProgressBarVisibility(true);
//设置进度条的进度
setProgress(4500);
//隐藏带进度的进度条。
setProgressBarVisibility(false);
//设置窗口特征:启用不显示进度的进度条
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); //②
//显示不带进度的进度条。
setProgressBarIndeterminateVisibility(true);
//隐藏不带进度的进度条。
setProgressBarIndeterminateVisibility(false);
拖动条(SeekBar)的功能和用法
<!-- 定义一个拖动条,并改变它的滑块外观 -->
<SeekBar
android:id="@+id/seekbar"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:max="255"
android:progress="255"
android:thumb="@drawable/ic_launcher" //拖动条上的滑块
/>
星级评分条(RatingBar)
<!-- 定义一个星级评分条 -->
<RatingBar
android:id="@+id/rating"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:numStars="5" //5颗星
android:max="255"
android:progress="255"
android:stepSize="0.5" //最小值0.5
/>
5.ViewAnimator及其子类
ViewAnimator是一个基类,它继承了FrameLayout,因此它表现出了FrameLayout的特征,可以将多个View组件”叠”在一起。
ViewSwitcher的功能与用法
ViewSwitcher代表了视图切换组件,它本身继承了FrameLayout,因此可以将多个View层叠在一起,每次只显示一个组件,当程序控制从一个View切换到另一个View时,ViewSwitcher支持指定动画效果。
为了给ViewSwitcher添加多个组件,一般通过调用ViewSwitcher的setFactory(ViewSwitcher.ViewFactory)方法为之设置ViewFactory,并由该ViewFactory为之创建View即可。
<!-- 定义一个ViewSwitcher组件 -->
<ViewSwitcher
android:id="@+id/viewSwitcher"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
switcher = (ViewSwitcher) findViewById(R.id.viewSwitcher);
switcher.setFactory(new ViewFactory()
{
// 实际上就是返回一个GridView组件
public View makeView()
{
// 加载R.layout.slidelistview组件,实际上就是一个GridView组件。
return inflater.inflate(R.layout.slidelistview, null);
}
});
ImageSwitcher的用法
1>.为ImageSwitcher提供一个ViewFactory,该Factory生成的View组件必须是ImageView
2>.需要切换图片时,只需要调用ImageSwitcher的setImageDrawable(Drawable drawable)、setImageResource(int resid)和setImageURI(Uri uri)
<!-- 定义一个ImageSwitcher组件 -->
<ImageSwitcher android:id="@+id/switcher"
android:layout_width="300dp"
android:layout_height="300dp"
android:layout_gravity="center_horizontal"
android:inAnimation="@android:anim/fade_in"
android:outAnimation="@android:anim/fade_out"
/>
// 获取显示图片的ImageSwitcher
switcher = (ImageSwitcher)findViewById(R.id.switcher);
// 为ImageSwitcher设置图片切换的动画效果
switcher.setFactory(new ViewFactory()
{
public View makeView()
{
// 创建ImageView对象
ImageView imageView = new ImageView(Main.this);
imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
imageView.setLayoutParams(new ImageSwitcher.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
// 返回ImageView对象
return imageView;
}
});
TextSwitcher的用法
1>.TextSwitcher需要设置一个ViewFactory,该Factory生成的View组件必须是TextView
2>.需要切换文本时,只需要调用TextSwitcher的setText();方法修改即可
<!-- 定义一个TextSwitcher,并指定了文本切换时的动画效果 -->
<TextSwitcher
android:id="@+id/textSwitcher"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inAnimation="@android:anim/slide_in_left"
android:outAnimation="@android:anim/slide_out_right"
android:onClick="next"
/>
textSwitcher = (TextSwitcher) findViewById(R.id.textSwitcher);
textSwitcher.setFactory(new ViewSwitcher.ViewFactory()
{
public View makeView()
{
TextView tv = new TextView(TextSwitcherTest.this);
tv.setTextSize(40);
tv.setTextColor(Color.MAGENTA);
return tv;
}
});
// 调用next方法显示下一个字符串
next(null);
// 事件处理函数,控制显示下一个字符串
public void next(View source)
{
textSwitcher.setText(strs[curStr++ % strs.length]);
}
ViewFlipper的功能与用法
ViewFlipper是继承了ViewAnimator,它调用了addView(View v)添加多个组件,一旦向ViewFlipper中添加了多个组件后,ViewFlipper可以使用动画控制多个组件切换的效果。
ViewFlipper与AdapterViewFlipper有较大的相似性,他们的区别是:ViewFlipper需要开发者通过addView(View v)添加多个组件,而AdapterViewFlipper则只要传入一个Adapter,Adapter将会负责提供多个View。
<ViewFlipper
android:id="@+id/details"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:persistentDrawingCache="animation"
android:flipInterval="1000" >
<ImageView
android:src="@drawable/ee"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
</ImageView>
......添加组件......
<ImageView
android:src="@drawable/ee"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
</ImageView>
</ViewFlipper>
6.其他杂项组件
<1>.Toast
Toast具有如下两个特点:
☆.Toast提示信息不会获得焦点
☆.Toast提示信息过一段时间会自动消失
<-----创建一个简单的Toast提示信息----->
Toast toast = Toast.makeText(Main.this, "简单的提示信息", Toast.LENGTH_SHORT);
toast.show();
<-----创建一个带图片的Toast提示信息----->
Toast toast = new Toast(Main.this);
// 设置Toast的显示位置
toast.setGravity(Gravity.CENTER, 0, 0);
// 创建一个ImageView
ImageView image = new ImageView(Main.this);
image.setImageResource(R.drawable.tools);
// 创建一个LinearLayout容器
LinearLayout ll = new LinearLayout(Main.this);
ll.setBackgroundColor(Color.BLACK);
// 向LinearLayout中添加图片、原有的View
ll.addView(image);
// 创建一个ImageView
TextView textView = new TextView(Main.this);
textView.setText("带图片的提示信息");
// 设置文本框内字体的大小和颜色
textView.setTextSize(30);
textView.setTextColor(Color.MAGENTA);
ll.addView(textView);
// 设置Toast显示自定义View
toast.setView(ll);
// 设置Toast的显示时间
toast.setDuration(Toast.LENGTH_LONG);
toast.show();
<2>.CalendarView
<!--CalendarView-->
<CalendarView
android:layout_width="400dp"
android:layout_height="500dp"
android:firstDayOfWeek="2" //以星期一作为每周第一天
android:shownWeekCount="6" //该组件总共显示6个星期
android:selectedWeekBackgroundColor="#ffffcc" //被选中周的背景色
android:focusedMonthDateColor="#cc0066" //获得焦点月份的日期颜色
android:weekSeparatorLineColor="#000033"
android:unfocusedMonthDateColor="#c0c0c0" //没有焦点的日期文字的颜色
android:id="@+id/calendarView"
/>
cv = (CalendarView)findViewById(R.id.calendarView);
// 为CalendarView组件的日期改变事件添加事件监听器
cv.setOnDateChangeListener(new OnDateChangeListener()
{
public void onSelectedDayChange(CalendarView view, int year,int month, int dayOfMonth)
{
// 使用Toast显示用户选择的日期
Toast.makeText(CalendarViewTest.this,"你生日是" + year + "年" + month + "月" + dayOfMonth + "日" ,Toast.LENGTH_SHORT).show();
}
});
<3>.DatePicker/TimePicker、NumberPicker
<!-- 定义一个DatePicker组件 -->
<DatePicker
android:id="@+id/datePicker"
android:layout_width="wrap_content"
android:layout_height="200dp"
android:layout_gravity="center_horizontal"
android:startYear="2000"
android:endYear="2012"
android:calendarViewShown="true"
android:spinnersShown="true"
/>
<!-- 定义一个TimePicker组件 -->
<TimePicker
android:id="@+id/timePicker"
android:layout_width="wrap_content"
android:layout_height="100dp"
android:layout_gravity="center_horizontal"
/>
// 获取当前的年、月、日、小时、分钟
Calendar c = Calendar.getInstance();
year = c.get(Calendar.YEAR);
month = c.get(Calendar.MONTH);
day = c.get(Calendar.DAY_OF_MONTH);
hour = c.get(Calendar.HOUR);
minute = c.get(Calendar.MINUTE);
// 初始化DatePicker组件,初始化时指定监听器
datePicker.init(year, month, day, new OnDateChangedListener()
{
public void onDateChanged(DatePicker arg0, int year, int month, int day)
{
ChooseDate.this.year = year;
ChooseDate.this.month = month;
ChooseDate.this.day = day;
// 显示当前日期、时间
showDate(year, month, day, hour, minute);// 在EditText中显示当前日期、时间的方法
}
});
// 为TimePicker指定监听器
timePicker.setOnTimeChangedListener(new OnTimeChangedListener()
{
public void onTimeChanged(TimePicker view, int hourOfDay, int minute)
{
ChooseDate.this.hour = hourOfDay;
ChooseDate.this.minute = minute;
// 显示当前日期、时间
showDate(year, month, day, hour, minute); // 在EditText中显示当前日期、时间的方法
}
});
<!-- 定义一个NumberPicker组件 -->
<NumberPicker
android:id="@+id/np1"
android:layout_width="match_parent"
android:layout_height="80dp"
android:focusable="true"
android:focusableInTouchMode="true"
/>
// 设置np1的最小值和最大值
np1.setMinValue(10);
np1.setMaxValue(50);
// 设置np1的当前值
np1.setValue(25);
<4>.SearchView
<!-- 定义一个SearchView -->
<SearchView
android:id="@+id/sv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
public class Main implements SearchView.OnQueryTextListener extends Activity
{
// 设置该SearchView默认是否自动缩小为图标
sv.setIconifiedByDefault(true);
// 为该SearchView组件设置事件监听器
sv.setOnQueryTextListener(this);
// 设置该SearchView显示搜索按钮
sv.setSubmitButtonEnabled(true);
// 设置该SearchView内默认显示的提示文本
sv.setQueryHint("查找");
// 用户输入字符时激发该方法
@Override
public boolean onQueryTextChange(String newText)
{
if (TextUtils.isEmpty(newText))
{
// 清除ListView的过滤
lv.clearTextFilter();
}
else
{
// 使用用户输入的内容对ListView的列表项进行过滤
lv.setFilterText(newText);
}
return true;
}
// 单击搜索按钮时激发该方法
@Override
public boolean onQueryTextSubmit(String query)
{
// 实际应用中应该在该方法内执行实际查询
// 此处仅使用Toast显示用户输入的查询内容
Toast.makeText(this, "您的选择是:" + query
, Toast.LENGTH_SHORT).show();
return false;
}
}
<5>.TabHost(标签页)
<?xml version="1.0" encoding="utf-8"?>
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/tabhost"
>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
>
<TabWidget
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@android:id/tabs"
/>
<FrameLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@android:id/tabcontent"
>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/page1"
>
<TextView
…
/>
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/page2"
>
<TextView
…
/>
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/page3"
>
<TextView
…
/>
</LinearLayout>
</FrameLayout>
</LinearLayout>
</TabHost>
tabHost.setup();
TabSpec tabSpec = tabHost.newTabSpec("page1");
//tabSpec.setIndicator("首页", getResources().getDrawable(R.drawable.i1));
tabSpec.setIndicator(createTabView("首页"));// createTabView()创建标题View
tabSpec.setContent(R.id.page1);
tabHost.addTab(tabSpec);
<6>.ScrollView
<!-- 定义ScrollView,为里面的组件添加垂直滚动条 -->
<!-- ScrollView里最多只能包含一个组件 -->
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<!-- 定义HorizontalScrollView,为里面的组件添加水平滚动条 -->
<HorizontalScrollView
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="fill_parent"
>
<TextView
......
/>
</LinearLayout>
</HorizontalScrollView>
</ScrollView>
<7>.Notification
// 获取系统的NotificationManager服务
NotificationManager nm =
(NotificationManager)getSystemService(NOTIFICATION_SERVICE);
Notification notify = new Notification.Builder(this)
// 设置打开该通知,该通知自动消失
.setAutoCancel(true)
// 设置显示在状态栏的通知提示信息
.setTicker("有新消息")
// 设置通知的图标
.setSmallIcon(R.drawable.notify)
// 设置通知内容的标题
.setContentTitle("一条新通知")
// 设置通知内容
.setContentText("恭喜你,您加薪了,工资增加20%!")
// 设置使用系统默认的声音、默认LED灯
//.setDefaults(Notification.DEFAULT_SOUND|Notification.DEFAULT_LIGHTS)
// 设置通知的自定义声音
.setSound(Uri.parse("android.resource://org.crazyit.ui/"+ R.raw.msg))
.setWhen(System.currentTimeMillis())
// 设改通知将要启动程序的Intent
.setContentIntent(pi).build();
// 发送通知
nm.notify(NOTIFICATION_ID, notify);
三、对话框
Android提供了4种常用的对话框:
1.AlertDialog:功能最丰富、实际应用最广的对话框
2.ProgressDialog:进度对话框,这个对话框只是对简单进度条的封装
3.DatePickerDialog:日期选择对话框,这个对话框只是对DatePicker的包装
4.TimePickerDialog:时间选择对话框,这个对话框只是对TimePicker的包装
< ---AlertDialog--- >
AlertDialog生成的对话框可分为4个区域:
1>.图标区
2>.标题区
3>.内容区
4>.按钮区
创建对话框步骤:
1>.使用创建AlertDialog.Builder对象
2>.调用AlertDialog.Builder的setTitle()或setCustomTitle方法设置标题
3>.调用AlertDialog.Builder的setIcon方法设置标题
4>.调用AlertDialog.Builder的相关方法设置对话框内容
5>.调用AlertDialog.Builder的setPositiviteButton、setNegativiteButton或setNeutralButton方法添加多个按钮
6>.调用AlertDialog.Builder的create()方法创建AlertDialog对象,再调用AlertDialog对象的show()方法将对话框显示出来
AlertDialog提供了6种方法来指定对话框的内容
1>.setMessage():设置对话框内容为简单文本
2>.setItems():设置对话框内容为简单列表项
3>.setSingleChoiceItems():设置对话框内容为单选列表项
4>.setMultiChoiceItems():设置对话框内容为多选列表项
5>.setAdapter():设置对话框内容为自定义列表项
6>.setView():设置对话框内容为自定义View
AlertDialog.Builder builder = new AlertDialog.Builder(this);//创建对象
builder.setTitle("对话框");// 设置对话框标题
builder.setIcon(R.drawable.tools);// 设置对话框的图标
builder.setMessage("对话框的测试内容\n第二行内容"); //设置简单内容
builder.setItems(items, new OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
show.setText("你选中了《" + items[which] + "》");
}
});// 设置简单的列表项内容
builder.setSingleChoiceItems(items, 1, new OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
show.setText("你选中了《" + items[which] + "》");
}
});// 设置单选列表项,默认选中第二项(索引为1)
builder.builder.setMultiChoiceItems(items,
new boolean[]{false , true ,false ,true}, null);
// 设置多选列表项,设置勾选第2项、第4项
builder.setAdapter(new ArrayAdapter<String>(this , R.layout.array_item , items), null);// 设置自定义列表项
builder.setView(loginForm);// 设置对话框显示的View对象
setPositiveButton(builder);// 添加【确定】按钮
setNegativeButton(builder);//添加【取消】按钮
builder.create().show();//创建,显示对话框
builder.setPositiveButton("登录" , new OnClickListener()
{
@Override
public void onClick(DialogInterface dialog,int which)
{
// 此处可执行登录处理
}
});
private AlertDialog.Builder setPositiveButton(AlertDialog.Builder builder)
{
// 调用setPositiveButton方法添加确定按钮
return builder.setPositiveButton("确定", new OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
show.setText("单击了【确定】按钮!");
}
});
}
< ---对话框风格窗口--- >
android:theme="@android:style/Theme.Dialog"//以对话框形式显示activity
< ---使用PopupWindow--- >
// 装载R.layout.popup对应的界面布局
View root = this.getLayoutInflater().inflate(R.layout.popup, null);
// 创建PopupWindow对象
final PopupWindow popup = new PopupWindow(root, 280, 360);
//popup.showAsDropDown(v);// 以下拉方式显示。
//将PopupWindow显示在指定位置
popup.showAtLocation(findViewById(R.id.bn), Gravity.CENTER, 20,20);
< ---使用DatePickerDialog/TimePickerDialog--- >
Calendar c = Calendar.getInstance();
// 直接创建一个DatePickerDialog对话框实例,并将它显示出来
new DatePickerDialog(DateDialogTest.this,
// 绑定监听器
new DatePickerDialog.OnDateSetListener()
{
@Override
public void onDateSet(DatePicker dp, int year,int month, int dayOfMonth)
{
EditText show = (EditText) findViewById(R.id.show);
show.setText("您选择了:" + year + "年" + (month + 1)+ "月" + dayOfMonth + "日");
}
}
//设置初始日期
, c.get(Calendar.YEAR)
, c.get(Calendar.MONTH)
, c.get(Calendar.DAY_OF_MONTH)).show();
Calendar c = Calendar.getInstance();
// 创建一个TimePickerDialog实例,并把它显示出来。
new TimePickerDialog(DateDialogTest.this,
// 绑定监听器
new TimePickerDialog.OnTimeSetListener()
{
@Override
public void onTimeSet(TimePicker tp, int hourOfDay,int minute)
{
EditText show = (EditText) findViewById(R.id.show);
show.setText("您选择了:" + hourOfDay + "时" + minute+ "分");
}
}
//设置初始时间
, c.get(Calendar.HOUR_OF_DAY)
, c.get(Calendar.MINUTE)
//true表示采用24小时制
, true).show();
< ---使用ProgressDialog创建进度对话框 --- >
// 调用静态方法显示环形进度条
ProgressDialog.show(this, "任务执行中", "任务执行中,请等待", false, true); //①环形进度对话框
ProgressDialog pd1 = new ProgressDialog(ProgressDialogTest.this);
// 设置对话框的标题
pd1.setTitle("任务正在执行中");
// 设置对话框显示的内容
pd1.setMessage("任务正在执行中,敬请等待...");
// 设置对话框能用“取消”按钮关闭
pd1.setCancelable(true);
// 设置对话框的进度条风格
pd1.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
// 设置对话框的进度条是否显示进度
pd1.setIndeterminate(true);
pd1.show(); //②不显示进度的进度条对话框
// 将进度条的完成进度重设为0
progressStatus = 0;
// 重新开始填充数组。
hasData = 0;
ProgressDialog pd2 = new ProgressDialog(ProgressDialogTest.this);
pd2.setMax(MAX_PROGRESS);
// 设置对话框的标题
pd2.setTitle("任务完成百分比");
// 设置对话框 显示的内容
pd2.setMessage("耗时任务的完成百分比");
// 设置对话框不能用“取消”按钮关闭
pd2.setCancelable(false);
// 设置对话框的进度条风格
pd2.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
// 设置对话框的进度条是否显示进度
pd2.setIndeterminate(false);
pd2.show(); //③显示进度条的进度对话框
四、菜单
< ------------选项菜单和子菜单----------- >
// 当用户单击MENU键时触发该方法
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
// -------------向menu中添加字体大小的子菜单-------------
SubMenu fontMenu = menu.addSubMenu("字体大小");
// 设置菜单的图标
fontMenu.setIcon(R.drawable.font);
// 设置菜单头的图标
fontMenu.setHeaderIcon(R.drawable.font);
// 设置菜单头的标题
fontMenu.setHeaderTitle("选择字体大小");
fontMenu.add(0, FONT_10, 0, "10号字体");
fontMenu.add(0, FONT_12, 0, "12号字体");
// -------------向menu中添加普通菜单项-------------
menu.add(0, PLAIN_ITEM, 0, "普通菜单项");
// -------------向menu中添加文字颜色的子菜单-------------
SubMenu colorMenu = menu.addSubMenu("字体颜色");
colorMenu.setIcon(R.drawable.color);
// 设置菜单头的图标
colorMenu.setHeaderIcon(R.drawable.color);
// 设置菜单头的标题
colorMenu.setHeaderTitle("选择文字颜色");
colorMenu.add(0, FONT_RED, 0, "红色");
colorMenu.add(0, FONT_GREEN, 0, "绿色");
return super.onCreateOptionsMenu(menu);
}
@Override
// 选项菜单的菜单项被单击后的回调方法
public boolean onOptionsItemSelected(MenuItem mi)
{
//判断单击的是哪个菜单项,并针对性的作出响应。
switch (mi.getItemId())
{
case FONT_10:
edit.setTextSize(10 * 2);
break;
case FONT_12:
edit.setTextSize(12 * 2);
break;
case FONT_RED:
edit.setTextColor(Color.RED);
break;
case FONT_GREEN:
edit.setTextColor(Color.GREEN);
break;
case PLAIN_ITEM:
Toast toast = Toast.makeText(MenuTest.this, "您单击了普通菜单项" , Toast.LENGTH_SHORT).show();
break;
}
return true;
}
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
// -------------向menu中添加子菜单-------------
SubMenu prog = menu.addSubMenu("启动程序");
// 设置菜单头的图标
prog.setHeaderIcon(R.drawable.tools);
// 设置菜单头的标题
prog.setHeaderTitle("选择您要启动的程序");
// 添加菜单项
MenuItem item = prog.add("查看经典Java EE");
//为菜单项设置关联的Activity
item.setIntent(new Intent(this , OtherActivity.class));
return super.onCreateOptionsMenu(menu);
}
< ------------上下文菜单----------- >
// 为文本框注册上下文菜单
registerForContextMenu(txt);
// 创建上下文菜单时触发该方法
@Override
public void onCreateContextMenu(ContextMenu menu, View source,
ContextMenu.ContextMenuInfo menuInfo)
{
menu.add(0, MENU1, 0, "红色");
menu.add(0, MENU2, 0, "绿色");
// 将三个菜单项设为单选菜单项
menu.setGroupCheckable(0, true, true); //第三个参数为true则为单选
//设置上下文菜单的标题、图标
menu.setHeaderIcon(R.drawable.tools);
menu.setHeaderTitle("选择背景色");
}
// 上下菜单的菜单项被单击时触发该方法。
@Override
public boolean onContextItemSelected(MenuItem mi)
{
switch (mi.getItemId())
{
case MENU1:
mi.setChecked(true);
txt.setBackgroundColor(Color.RED);
break;
case MENU2:
mi.setChecked(true);
txt.setBackgroundColor(Color.GREEN);
break;
}
return true;
}
< ------------使用XML资源文件定义菜单----------- >
//当用户单击MENU键时触发该方法
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
MenuInflater inflator = new MenuInflater(this);
// 状态R.menu.context对应的菜单,并添加到menu中
inflator.inflate(R.menu.my_menu, menu);
return super.onCreateOptionsMenu(menu);
}
menu/my_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:title="@string/font_size"
android:icon="@drawable/font">
<menu>
<!-- 定义一组单选菜单项 -->
<group android:checkableBehavior="single">
<!-- 定义多个菜单项 -->
<item
android:id="@+id/font_10"
android:title="@string/font_10"/>
<item
android:id="@+id/font_12"
android:title="@string/font_12"/>
</group>
</menu>
</item>
<!-- 定义一个普通菜单项 -->
<item android:id="@+id/plain_item"
android:title="@string/plain_item">
</item>
<item android:title="@string/font_color"
android:icon="@drawable/color">
<menu>
<!-- 定义一组允许复选的菜单项 -->
<group>
<!-- 定义3个菜单项 -->
<item
android:id="@+id/red_font"
android:title="@string/red_title"/>
<item
android:id="@+id/green_font"
android:title="@string/green_title"/>
</group>
</menu>
</item>
</menu>
@Override
// 选项菜单的菜单项被单击后的回调方法
public boolean onOptionsItemSelected(MenuItem mi)
{
if(mi.isCheckable())
{
mi.setChecked(true); //②
}
// 判断单击的是哪个菜单项,并针对性的作出响应。
switch (mi.getItemId())
{
case R.id.font_10:
txt.setTextSize(10 * 2);
break;
......
}
return true;
}
// 为文本框注册上下文菜单
registerForContextMenu(txt);
// 创建上下文菜单时触发该方法
@Override
public void onCreateContextMenu(ContextMenu menu, View source,
ContextMenu.ContextMenuInfo menuInfo)
{
MenuInflater inflator = new MenuInflater(this);
// 状态R.menu.context对应的菜单,并添加到menu中
inflator.inflate(R.menu.context, menu);
menu.setHeaderIcon(R.drawable.tools);
menu.setHeaderTitle("请选择背景色");
}
menu/context.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 定义一组单选菜单项目 -->
<group android:checkableBehavior="single">
<!-- 定义2个菜单项 -->
<item
android:id="@+id/red"
android:title="@string/red_title"
android:alphabeticShortcut="r"/>
<item
android:id="@+id/green"
android:title="@string/green_title"
android:alphabeticShortcut="g"/>
</group>
</menu>
// 上下文菜单中菜单项被单击时触发该方法。
@Override
public boolean onContextItemSelected(MenuItem mi)
{
mi.setChecked(true); //①
switch (mi.getItemId())
{
case R.id.red:
mi.setChecked(true);
txt.setBackgroundColor(Color.RED);
break;
......
}
return true;
}
< ------------使用PopupMenu创建弹出式菜单----------- >
// 创建PopupMenu对象
PopupMenu popup = = new PopupMenu(this, button);
// 将R.menu.popup_menu菜单资源加载到popup菜单中
getMenuInflater().inflate(R.menu.popup_menu, popup.getMenu());
// 为popup菜单的菜单项单击事件绑定事件监听器
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener()
{
@Override
public boolean onMenuItemClick(MenuItem item)
{
switch (item.getItemId())
{
case R.id.exit:
// 隐藏该对话框
popup.dismiss();
break;
default:
// 使用Toast显示用户点击的菜单项
Toast.makeText(PopupMenuTest.this,"您单击了【" + item.getTitle() + "】菜单项", Toast.LENGTH_SHORT).show();
}
return true;
}
});
popup.show();
menu/popup_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/search"
android:icon="@android:drawable/ic_menu_search"
android:title="查找" />
<item
android:id="@+id/add"
android:icon="@android:drawable/ic_menu_add"
android:title="添加" />
<item
android:id="@+id/edit"
android:icon="@android:drawable/ic_menu_edit"
android:title="编辑">
<menu>
<item
android:id="@+id/copy"
android:title="复制" />
<item
android:id="@+id/cut"
android:title="剪切" />
<item
android:id="@+id/paste"
android:title="粘贴" />
</menu>
</item>
<item
android:id="@+id/exit"
android:title="隐藏菜单" />
</menu>
五、活动条ActionBar(安卓 3.0)
活动条ActionBar位于传统标题栏的位置,也就是显示的屏幕的顶部。ActionBar可显示应用的图标和Activity标题,还可以显示活动项(Action Item).
活动条ActionBar提供了如下功能:
1.显示选项菜单的菜单项(将菜单项显示成Action Item)
2.使用程序图标作为返回Home主屏或向上的导航操作
3.提供交互式View作为Action View
4.提供基于Tab的导航方式,可以切换多个Fragment
5.提供基于下拉的导航
android:theme="@android:style/Theme.Holo.NoActionBar" //关闭ActionBar
< --- 启动ActionBar --- >
// 获取该Activity的ActionBar,
// 只有当应用主题没有关闭ActionBar时,该代码才能返回ActionBar
ActionBar actionBar = getActionBar();
// 显示ActionBar
actionBar.show();
// 隐藏ActionBar
actionBar.hide();
< ------使用ActionBar显示选项菜单------ >
手机如果没有Menu键,可以将选项菜单显示成ActionItem
项目中推荐使用XML来定义菜单
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:title="@string/font_size"
android:showAsAction="always|withText"
/*** android:showAsAction这个属性可接受的值有:
1、always:这个值会使菜单项一直显示在Action Bar上。
2、ifRoom:如果有足够的空间,这个值会使菜单项显示在Action Bar上。
3、never:这个值使菜单项永远都不出现在Action Bar上。
4、withText:这个值使菜单项和它的图标,菜单文本一起显示。
5.collapseActionView:折叠成普通菜单项
***/
android:icon="@drawable/font">
<menu>
<!-- 定义一组单选菜单项 -->
<group android:checkableBehavior="single">
<!-- 定义多个菜单项 -->
<item
android:id="@+id/font_10"
android:title="@string/font_10"/>
<item
android:id="@+id/font_12"
android:title="@string/font_12"/>
</group>
</menu>
</item>
</menu>
ActionBar actionBar = getActionBar();
// 设置是否显示应用程序图标
actionBar.setDisplayShowHomeEnabled(true);
// 将应用程序图标设置为可点击的按钮
actionBar.setHomeButtonEnabled(true);
// 将应用程序图标设置为可点击的按钮,并在图标上添加向左箭头
actionBar.setDisplayHomeAsUpEnabled(true);
android.R.id.home:点击应用图标时响应
< ------添加Action View -------- >
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/search"
android:title="@string/menu_settings"
android:orderInCategory="100"
android:showAsAction="always"
android:actionViewClass="android.widget.SearchView"/> //添加搜索框
<item
android:id="@+id/progress"
android:title="@string/menu_settings"
android:orderInCategory="100"
android:showAsAction="always"
android:actionLayout="@layout/clock"/> //添加模拟时钟(自定义View)
</menu>
clock.xml:
<AnalogClock
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
< ---------使用ActionBar实现Tab导航---------- >
public class ActionBar_TabNav extends Activity implementsActionBar.TabListener
{
private static final String SELECTED_ITEM = "selected_item";
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final ActionBar actionBar = getActionBar();
// 设置ActionBar的导航方式:Tab导航
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// 依次添加3个Tab页,并为3个Tab标签添加事件监听器
actionBar.addTab(actionBar.newTab().setText("第一页")
.setTabListener(this));
actionBar.addTab(actionBar.newTab().setText("第二页")
.setTabListener(this));
actionBar.addTab(actionBar.newTab().setText("第三页")
.setTabListener(this));
}
@Override
public void onRestoreInstanceState(Bundle savedInstanceState)
{
if (savedInstanceState.containsKey(SELECTED_ITEM))
{
// 选中前面保存的索引对应的Fragment页
getActionBar().setSelectedNavigationItem(
savedInstanceState.getInt(SELECTED_ITEM));
}
}
@Override
public void onSaveInstanceState(Bundle outState)
{
// 将当前选中的Fragment页的索引保存到Bundle中
outState.putInt(SELECTED_ITEM,
getActionBar().getSelectedNavigationIndex());
}
@Override
public void onTabUnselected(ActionBar.Tab tab,
FragmentTransaction fragmentTransaction)
{
}
// 当指定Tab被选中时激发该方法
@Override
public void onTabSelected(ActionBar.Tab tab,
FragmentTransaction fragmentTransaction)
{
// 创建一个新的Fragment对象
Fragment fragment = new DummyFragment();
// 创建一个Bundle对象,用于向Fragment传入参数
Bundle args = new Bundle();
args.putInt(DummyFragment.ARG_SECTION_NUMBER,
tab.getPosition() + 1);
// 向fragment传入参数
fragment.setArguments(args);
// 获取FragmentTransaction对象
FragmentTransaction ft = getFragmentManager().beginTransaction();
// 使用fragment代替该Activity中的container组件
ft.replace(R.id.container, fragment);
// 提交事务
ft.commit();
}
@Override
public void onTabReselected(ActionBar.Tab tab,
FragmentTransaction fragmentTransaction)
{
}
}
public class DummyFragment extends Fragment
{
public static final String ARG_SECTION_NUMBER = "section_number";
// 该方法的返回值就是该Fragment显示的View组件
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
TextView textView = new TextView(getActivity());
textView.setGravity(Gravity.CENTER_HORIZONTAL);
// 获取创建该Fragment时传入的参数Bundle
Bundle args = getArguments();
// 设置TextView显示的文本
textView.setText(args.getInt(ARG_SECTION_NUMBER) + "");
textView.setTextSize(30);
// 返回该TextView
return textView;
}
}
< ---------使用ActionBar实现TabSwipe导航---------- >
public class ActionBar_TabSwipeNav extends FragmentActivity
implements ActionBar.TabListener
{
ViewPager viewPager;
ActionBar actionBar;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 获取ActionBar对象
actionBar = getActionBar();
// 获取ViewPager
viewPager = (ViewPager) findViewById(R.id.pager);
// 创建一个FragmentPagerAdapter对象,该对象负责为ViewPager提供多个Fragment
FragmentPagerAdapter pagerAdapter = new FragmentPagerAdapter(
getSupportFragmentManager())
{
// 获取第position位置的Fragment
@Override
public Fragment getItem(int position)
{
Fragment fragment = new DummyFragment();
Bundle args = new Bundle();
args.putInt(DummyFragment.ARG_SECTION_NUMBER, position + 1);
fragment.setArguments(args);
return fragment;
}
// 该方法的返回值i表明该Adapter总共包括多少个Fragment
@Override
public int getCount()
{
return 3;
}
// 该方法的返回值决定每个Fragment的标题
@Override
public CharSequence getPageTitle(int position)
{
switch (position)
{
case 0:
return "第一页";
case 1:
return "第二页";
case 2:
return "第三页";
}
return null;
}
};
// 设置ActionBar使用Tab导航方式
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// 遍历pagerAdapter对象所包含的全部Fragment。
// 每个Fragment对应创建一个Tab标签
for (int i = 0; i < pagerAdapter.getCount(); i++)
{
actionBar.addTab(actionBar.newTab()
.setText(pagerAdapter.getPageTitle(i))
.setTabListener(this));
}
// 为ViewPager组件设置FragmentPagerAdapter
viewPager.setAdapter(pagerAdapter); //①
// 为ViewPager组件绑定事件监听器
viewPager.setOnPageChangeListener(
new ViewPager.SimpleOnPageChangeListener()
{
// 当ViewPager显示的Fragment发生改变时激发该方法
@Override
public void onPageSelected(int position)
{
actionBar.setSelectedNavigationItem(position);
}
});
}
@Override
public void onTabUnselected(ActionBar.Tab tab,
FragmentTransaction fragmentTransaction)
{
}
// 当指定Tab被选中时激发该方法
@Override
public void onTabSelected(ActionBar.Tab tab,
FragmentTransaction fragmentTransaction)
{
viewPager.setCurrentItem(tab.getPosition()); //②
}
@Override
public void onTabReselected(ActionBar.Tab tab,
FragmentTransaction fragmentTransaction)
{
}
}
main.xml:
<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- 定义导航状态条组件 -->
<android.support.v4.view.PagerTitleStrip
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:background="#33b5e5"
android:textColor="#fff"
android:paddingTop="4dp"
android:paddingBottom="4dp" />
</android.support.v4.view.ViewPager>
< ---------使用ActionBar实现下拉式导航---------- >
public class ActionBar_DropDownNav extends Activity implements
ActionBar.OnNavigationListener
{
private static final String SELECTED_ITEM = "selected_item";
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final ActionBar actionBar = getActionBar();
// 设置ActionBar是否显示标题
actionBar.setDisplayShowTitleEnabled(true);
// 设置导航模式,使用List导航
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
// 为actionBar安装ArrayAdapter
actionBar.setListNavigationCallbacks(
new ArrayAdapter<String>(ActionBar_DropDownNav.this,
android.R.layout.simple_list_item_1,
android.R.id.text1, new String[]
{"第一页","第二页","第三页" }), this);
}
@Override
public void onRestoreInstanceState(Bundle savedInstanceState)
{
if (savedInstanceState.containsKey(SELECTED_ITEM))
{
// 选中前面保存的索引对应的Fragment页
getActionBar().setSelectedNavigationItem(
savedInstanceState.getInt(SELECTED_ITEM));
}
}
@Override
public void onSaveInstanceState(Bundle outState)
{
// 将当前选中的Fragment页的索引保存到Bundle中
outState.putInt(SELECTED_ITEM,
getActionBar().getSelectedNavigationIndex());
}
// 当导航项被选中时激发该方法
@Override
public boolean onNavigationItemSelected(int position, long id)
{
// 创建一个新的Fragment对象
Fragment fragment = new DummyFragment();
// 创建一个Bundle对象,用于向Fragment传入参数
Bundle args = new Bundle();
args.putInt(DummyFragment.ARG_SECTION_NUMBER, position + 1);
// 向fragment传入参数
fragment.setArguments(args);
// 获取FragmentTransaction对象
FragmentTransaction ft = getFragmentManager().beginTransaction();
// 使用fragment代替该Activity中的container组件
ft.replace(R.id.container, fragment);
// 提交事务
ft.commit();
return true;
}
}