1、利用代码来构建UI
nameContainer = new LinearLayout(this);
nameContainer.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT));
nameContainer.setOrientation(LinearLayout.HORIZONTAL);
TextView nameLbl = new TextView(this);
nameLbl.setText("Name: ");
nameContainer.addView(nameLbl);
2、TextView控件:TextView控件知道如何显示文本,但是不允许进行编辑。
如果知道TextView的内容将包含一个URL或者Email,可以将其autoLink属性设置为email|web,这样这段Text就将突出显示,并且点击这个Text可以调出相应程序进行处理。
<TextView ... android:autoLink="email|web" ... />
autoLink可选值包括:web,email,phone,map,none,all
代码中:setAutoLinkMask Linkify.EMAIL_ADDRESSES|Linkify.WEB_ADDRESSES
注意需要在设置Text之前设置autoLink,autoLink不影响之前设置的Text
也可以调用Linkify.addLinks(tv, Linkify.ALL);方法进行设置(tv为一个TextView)
3、EditText控件:是TextView的子类,可编辑文本,默认行为是在一行上显示文本并且根据需要增加行数,但是如果将singleLine属性设置为true,可以强制用户输入一行内容。
inputType:textAutoCorrect:自动更正拼写错误
textCapWords:将单词转换为大写
textMultiline:多行键入
android:hint="your hint text here"提示文本,代码中使用CharSequence或资源ID调用setHint()
4、AutoCompleteTextView控件:具有自动完成功能的TextView
<AutoCompleteTextView android:id="@+id/actv"
android:layout_width="fill_parent" android:layout_height="wrap_content" />
AutoCompleteTextView actv = (AutoCompleteTextView) this.findViewById(R.id.actv);
ArrayAdapter<String> aa = new ArrayAdapter<String>(this,
android.R.layout.simple_dropdown_item_1line,
new String[] {"English", "Hebrew", "Hindi", "Spanish", "German", "Greek"});
actv.setAdapter(aa);
这类控件包含两部分:文本视图控件和显示建议控件。要使用这样的控件,必须创建该控件,创建建议列表并告知控件,还可能告知控件如何显示建议。也可以为建议控件创建第二个控件,然后将两个控件相关联。
5、MultiAutoCompleteTextView控件:AutoCompleteTextView控件仅为文本视图的完整文本提供建议,MultiAutoCompleteTextView控件可以根据设置的令牌规则在句子中的任何地方开始建议
<MultiAutoCompleteTextView android:id="@+id/mactv"
android:layout_width="fill_parent" android:layout_height="wrap_content" />
MultiAutoCompleteTextView mactv = (MultiAutoCompleteTextView) this
.findViewById(R.id.mactv);
ArrayAdapter<String> aa2 = new ArrayAdapter<String>(this,
android.R.layout.simple_dropdown_item_1line,
new String[] {"English", "Hebrew", "Hindi", "Spanish", "German", "Greek" });
mactv.setAdapter(aa2);
mactv.setTokenizer(new MultiAutoCompleteTextView.CommaTokenizer());
其中CommaTokenizer为在遇到逗号后开始建议。
6、Button控件:下面将介绍1.6之前的点击处理事件代码,及新版本的代码
Button btn = (Button)this.findViewById(R.id.ccbtn1);
btn.setOnClickListener(new OnClickListener()
{
public void onClick(View v)
{
Intent intent = new Intent(Intent.ACTION_VIEW,
Uri.parse(“http://www.androidbook.com”));
startActivity(intent);
}
});
新:
<Button ... android:onClick="myClickHandler" ... />
public void myClickHandler(View target) {
switch(target.getId()) {
case R.id.ccbtn1:
…
注意新版本中View代表Button,可以为多个Button设置同一个处理函数。
7、ImageButton控件:在XML中用src设置图像,在代码中用setImageResource设置。
<ImageButton android:id="@+id/p_w_picpathBtn"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:onClick=”myClickHandler”
android:src=”@drawable/icon” />
ImageButton btn = (ImageButton)this.findViewById(R.id.p_w_picpathBtn);
btn.setImageResource(R.drawable.icon);
可以为按钮指定透明背景,结果是一个可单击的图像。
为ImageButton使用选择器:选择器的xml文件必须位于/res/drawable文件夹下。
<?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/button_pressed" /> <!-- pressed -->
<item android:state_focused="true"
android:drawable="@drawable/button_focused" /> <!-- focused -->
<item android:drawable="@drawable/icon" /> <!-- default -->
</selector>
将选择器xml设置成src的属性值
选择项顺序很重要,默认值在最后。
8、ToggleButton控件:在On状态下显示一个绿条(文本设置为On),在Off状态下显示灰条(文本设置为Off)。
<ToggleButton android:id="@+id/cctglBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Toggle Button"
android:textOn=”Stop”
android:textOff=”Run”/>
9、CheckBox控件:调用setChecked()或toggle()来管理复选框的状态。调用isChecked来获取它的状态。
CheckBox fishCB = (CheckBox)findViewById(R.id.fishCB);
if(fishCB.isChecked())
fishCB.toggle(); // flips the checkbox to unchecked if it was checked
fishCB.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton arg0, boolean isChecked) {
Log.v("CheckBoxActivity", "The fish checkbox is now "
+ (isChecked?"checked":"not checked"));
}});
在Android1.6以后可以直接在xml布局文件中定义android:onClick属性:
public void myClickHandler(View view) {
switch(view.getId()) {
case R.id.steakCB:
Log.v("CheckBoxActivity", "The steak checkbox is now " +
(((CheckBox)view).isChecked()?"checked":"not checked"));
}
}
10、RadioButton控件:可以在单选组内包含非单选按钮view
<RadioGroup android:id="@+id/radGrp"
android:layout_width="wrap_content" android:layout_height="wrap_content">
<RadioButton android:id="@+id/chRBtn" android:text="Chicken"
android:layout_width="wrap_content" android:layout_height="wrap_content"/>
<RadioButton android:id="@+id/fishRBtn" android:text="Fish"
android:layout_width="wrap_content" android:layout_height="wrap_content"/>
<RadioButton android:id="@+id/stkRBtn" android:text="Steak"
android:layout_width="wrap_content" android:layout_height="wrap_content"/>
<TextView android:text="My Favorite"
android:layout_width="wrap_content" android:layout_height="wrap_content"/>
</RadioGroup>
RadioButton的点击处理函数与CheckBox大致一样,唯一不同的是其实现的是RadioGroup.OnCheckedChangeListener类,而CheckBox实现的是CompoundButton.OnCheckedChangeListener类。
通过getCheckedRadioButtonId()方法获取当前选择的RadioButton,如果没有选择则返回-1。代码中调用RadioGroup的clearCheck()方法清除所有选择。
RadioGroup radGrp = (RadioGroup)findViewById(R.id.radGrp);
RadioButton newRadioBtn = new RadioButton(this);
newRadioBtn.setText("Pork");
radGrp.addView(newRadioBtn);
11、ImageView控件:图像来源可能来自于文件、ContentProvider或图形对象等资源,甚至可以仅指定一种颜色。
<ImageView android:id="@+id/p_w_picpath1"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:src="@drawable/icon" />
<ImageView android:id="@+id/p_w_picpath2"
android:layout_width="125dip" android:layout_height="25dip"
android:src="#555555" />
<ImageView android:id="@+id/p_w_picpath3"
android:layout_width="wrap_content" android:layout_height="wrap_content" />
<ImageView android:id="@+id/p_w_picpath4"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:src="@drawable/manatee02"
//图像超出最大大小后居中并拉伸图像
android:scaleType="centerInside"
//最大大小
android:maxWidth="35dip" android:maxHeight="50dip"
/>
ImageView imgView = (ImageView)findViewById(R.id.p_w_picpath3);
imgView.setImageResource( R.drawable.icon );
//多种设置方法(如inputstream),网络图像通过此方法设置
imgView.setImageBitmap(BitmapFactory.decodeResource(
this.getResources(), R.drawable.manatee14) );
//mnt:SD卡中
imgView.setImageDrawable(
Drawable.createFromPath("/mnt/sdcard/dave2.jpg") );
//只能设置本地资源,网络资源不能用此方法
imgView.setImageURI(Uri.parse("file://mnt/sdcard/dave2.jpg"));
12、DatePicker和TimePicker控件:
DatePicker dp = (DatePicker)this.findViewById(R.id.datePicker);
dateDefault.setText("Date defaulted to " + (dp.getMonth() + 1) + "/" +
dp.getDayOfMonth() + "/" + dp.getYear());
dp.init(2008, 11, 10, null);
TimePicker tp = (TimePicker)this.findViewById(R.id.timePicker);
java.util.Formatter timeF = new java.util.Formatter();
timeF.format("Time defaulted to %d:%02d", tp.getCurrentHour(),
tp.getCurrentMinute());
tp.setIs24HourView(true);
tp.setCurrentHour(new Integer(10));
tp.setCurrentMinute(new Integer(10));
另外还有模态窗口版本的DatePickerDialog和TimePickerDialog。
13、AnalogClock和DigitalClock控件:这两个控件只能显示当前时间,他们只是时钟。AnalogClock为数字显示,DigitalClock为仪表盘显示。
14、MapView控件:使用地图,相应activity必须扩展自MapActivity。
<com.google.android.maps.MapView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:enabled="true"
android:clickable="true"
android:apiKey="myAPIKey"
/>
15、列表控件是扩展了android.widget.AdapterView类的,包括ListView,GridView,Spinner和Gallery,AdapterView实际上扩展了android.widget.ViewGroup,这意味着ListView,GridView等都是容器,适配器的用途是为AdapterView管理数据,并为其提供子视图。
16、SimpleCursorAdapter(Context context, int childLayout, Cursor c, String[] from, int[] to)
此适配器将游标中的行转换成容器控件上(如ListView)的子视图。ListView调用适配器的getView()方法,使用适配器构造函数中的子视图创建相关行,把结果集中的一条结果放入子视图中的相应位置。如果一个ListView一次显示10行,则仅仅会实例化10几个子视图,而不会把结果集中的所有结构都实例化为子视图。
17、适配器不一定用于列表,其左侧容器可以是一个相册,右侧结果集可以是一组图像。
18、ArrayAdapter:ArrayAdapter是Android中最简单的适配器,它专用于列表控件。
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1,
new string[]{"Dave","Satya",”Dylan”});
没有传递from和to,这里假设子视图只为textView
<Spinner android:id="@+id/spinner"
android:layout_width="wrap_content" android:layout_height="wrap_content" />
Spinner spinner = (Spinner) findViewById(R.id.spinner);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,
R.array.planets, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
<?xml version="1.0" encoding="utf-8"?>
<!-- This file is /res/values/planets.xml -->
<resources>
<string-array name="planets">
<item>Mercury</item>
<item>Venus</item>
<item>Earth</item>
<item>Mars</item>
<item>Jupiter</item>
<item>Saturn</item>
<item>Uranus</item>
ArrayAdapter支持动态修改底层数据,相关方法有add(),insert(),remove(),sort()
19、ArrayAdapter<T>:这个适配器位于一般的任意对象数组的顶部,需要在ListView中使用。
CursorAdapter:也需要在ListView中使用,通过游标向列表提供数据。
SimpleAdapter:通常用于使用静态数据(可能来自资源)填充列表。
ResourceCursorAdapter:扩展了CursorAdapter,知道如何从资源创建视图。
SimpleCursorAdapter:扩展了ResourceCursorAdapter,从游标中的列创建TextView/ImageView视图,这些视图在资源中定义。
20、ListView控件:通常编写一个扩展自android.app.ListActivity的Activity,这样如果想让ListView占满全屏,甚至不需要设置layout
Cursor c = managedQuery(People.CONTENT_URI,null, null, null, People.NAME);
String[] cols = new String[] {People.NAME};
int[] views = new int[] {android.R.id.text1};
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
android.R.layout.simple_list_item_1,
c, cols, views);
this.setListAdapter(adapter);
public void onItemClick(AdapterView<?> adView, View target, int position, long id) {
Log.v("ListViewActivity", "in onItemClick with " + ((TextView) target).getText()
+
". Position = " + position + ". Id = " + id);
Uri selectedPerson = ContentUris.withAppendedId(
People.CONTENT_URI, id);
Intent intent = new Intent(Intent.ACTION_VIEW, selectedPerson);
startActivity(intent);
}
注意ID来源可能不明确。
调用notifyDataSetChanged()方法来让Adapter更新ListView。
21、使用ListView添加其它控件:如果希望向主要布局中添加更多控件,可以提供你自己的布局XML文件。
<?xml version="1.0" encoding="utf-8"?>
<!-- This file is at /res/layout/list.xml -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent" android:layout_height="fill_parent">
<ListView android:id="@android:id/list"
android:layout_width="fill_parent" android:layout_height="0dip"
android:layout_weight=”1” />
<Button android:id=”@+id/btn” android:onClick=”doClick”
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:text="Submit Selection" />
</LinearLayout>
注意ListView的id必须为@android:id/list,必须设置ListView的高度(android:layout_height="0dip"及android:layout_weight=”1”),这样ListView就会占据父容器中的所有空间,此方法为按钮留出了空间,这样按钮就会始终显示在屏幕上。
22、public class ListViewActivity3 extends ListActivity {
private static final String TAG = "ListViewActivity3";
private ListView lv = null;
private Cursor cursor = null;
private int idCol = -1;
private int nameCol = -1;
private int notesCol = -1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//上个练习中设置的xml布局文件
setContentView(R.layout.list);
lv = getListView();
cursor = managedQuery(People.CONTENT_URI, null, null, null,
People.NAME);
String[] cols = new String[] { People.NAME };
idCol = cursor.getColumnIndex(People._ID);
nameCol = cursor.getColumnIndex(People.NAME);
notesCol = cursor.getColumnIndex(People.NOTES);
int[] views = new int[] { android.R.id.text1 };
//simple_list_item_multiple_choice为Android预置的文件,其中用到专门用于 //ListView的TextView的子类CheckedTextView,其ID为text1
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
android.R.layout.simple_list_item_multiple_choice, cursor,
cols, views);
this.setListAdapter(adapter);
//这样用户就可以选择行,默认为CHOICE_MODE_NONE
//还有一个选项为CHOICE_MODE_SINGLE,
//此时需要android.R.layout.simple_list_item_single_choice
lv.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
}
public void doClick(View view) {
int count = lv.getCount();
SparseBooleanArray viewItems = lv.getCheckedItemPositions();
for (int i = 0; i < count; i++) {
if (viewItems.get(i)) {
cursor.moveToPosition(i);
long id = cursor.getLong(idCol);
String name = cursor.getString(nameCol);
String notes = cursor.getString(notesCol);
Log.v(TAG, name + " is checked. Notes: " + notes
+ ". Position = " + i + ". Id = " + id);
}
}
}
}
23、在新版本中读取ListView(2.3)
public class ListViewActivity4 extends ListActivity {
private static final String TAG = "ListViewActivity4";
private static final Uri CONTACTS_URI = ContactsContract.Contacts.CONTENT_URI;
private SimpleCursorAdapter adapter = null;
private ListView lv = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.list);
lv = getListView();
//只取出我们想要的列,这是正确方法
String[] projection = new String[] { ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME };
Cursor c = managedQuery(CONTACTS_URI, projection, null, null,
ContactsContract.Contacts.DISPLAY_NAME);
String[] cols = new String[] { ContactsContract.Contacts.DISPLAY_NAME };
int[] views = new int[] { android.R.id.text1 };
adapter = new SimpleCursorAdapter(this,
android.R.layout.simple_list_item_multiple_choice, c, cols,
views);
this.setListAdapter(adapter);
lv.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
}
public void doClick(View view) {
//getCheckedItemIds方法要求适配器中的基础数据保持稳定,所以先
//调用 hasStableIds方法
//在实际项目中,可能需要更智能的操作,比如启动一个后台线程
//来重试,以及显示一个对话框表明操作正在处理
if (!adapter.hasStableIds()) {
Log.v(TAG, "Data is not stable");
return;
}
long[] viewItems = lv.getCheckedItemIds();
for (int i = 0; i < viewItems.length; i++) {
Uri selectedPerson = ContentUris.withAppendedId(CONTACTS_URI,
viewItems[i]);
Log.v(TAG, selectedPerson.toString() + " is checked.");
}
}
}
24、在Android SDK安装目录/platforms/<android-version>/data/res/layout下可以找到Android预定于的layout文件。
25、GridView控件:网格使用的适配器是ListAdapter
<?xml version="1.0" encoding="utf-8"?>
<!-- This file is at /res/layout/gridview.xml -->
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/dataGrid"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10px"
android:verticalSpacing="10px"
android:horizontalSpacing="10px"
android:numColumns="auto_fit"
android:columnWidth="100px"
android:stretchMode="columnWidth"
android:gravity="center"
/>
//注意扩展自Activity
public class GridViewActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.gridview);
GridView gv = (GridView) findViewById(R.id.gridview);
Cursor c = managedQuery(People.CONTENT_URI, null, null, null,
People.NAME);
String[] cols = new String[] { People.NAME };
int[] views = new int[] { android.R.id.text1 };
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
android.R.layout.simple_list_item_1, c, cols, views);
// 注意ListView为activity.setAdapter()
gv.setAdapter(adapter);
}
}
26、ListView继承自ListActivity,所以可以在onCreate方法中不用设置layout,而GridView 继承自Activity,所以需要设置layout。GridView 的每一行实际为一个简单view,这个简单view为一个list。
27、Spinner控件
<Spinner
android:id="@+id/spinner" android:prompt=”@string/spinnerprompt”
android:layout_width="wrap_content" android:layout_height="wrap_content" />
public class SpinnerActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.spinner);
Spinner spinner = (Spinner) findViewById(R.id.spinner);
// createFromResource:从xml资源文件中提取列表
ArrayAdapter<CharSequence> adapter = ArrayAdapter
.createFromResource(this, R.array.planets,
android.R.layout.simple_spinner_item);
//设置下拉显示效果
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
}
}
28、Gallery控件:是一种可以水平滚动的列表控件,焦点始终位于列表中央,此控件通常在触摸模式下用作相册。可以通过自定义适配器显示图片。
29、自定义适配器:扩展BaseAdapter抽象类,可以通过自定义适配器通过缓存技术来改进性能。
public class GridViewCustomAdapter extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.gridviewcustom);
GridView gv = (GridView) findViewById(R.id.gridview);
ManateeAdapter adapter = new ManateeAdapter(this);
gv.setAdapter(adapter);
}
public static class ManateeAdapter extends BaseAdapter {
private static final String TAG = "ManateeAdapter";
private static int convertViewCounter = 0;
private Context mContext;
private LayoutInflater mInflater;
static class ViewHolder {
ImageView p_w_picpath;
}
private int[] manatees = { R.drawable.manatee00,
R.drawable.manatee01, R.drawable.manatee02,
R.drawable.manatee03, R.drawable.manatee04,
R.drawable.manatee05, R.drawable.manatee06,
R.drawable.manatee07, R.drawable.manatee08,
R.drawable.manatee09, R.drawable.manatee10,
R.drawable.manatee11, R.drawable.manatee12,
R.drawable.manatee13, R.drawable.manatee14,
R.drawable.manatee15, R.drawable.manatee16,
R.drawable.manatee17, R.drawable.manatee18,
R.drawable.manatee19, R.drawable.manatee20,
R.drawable.manatee21, R.drawable.manatee22,
R.drawable.manatee23, R.drawable.manatee24,
R.drawable.manatee25, R.drawable.manatee26,
R.drawable.manatee27, R.drawable.manatee28,
R.drawable.manatee29, R.drawable.manatee30,
R.drawable.manatee31, R.drawable.manatee32,
R.drawable.manatee33 };
private Bitmap[] manateeImages = new Bitmap[manatees.length];
private Bitmap[] manateeThumbs = new Bitmap[manatees.length];
public ManateeAdapter(Context context) {
Log.v(TAG, "Constructing ManateeAdapter");
this.mContext = context;
mInflater = LayoutInflater.from(context);
for (int i = 0; i < manatees.length; i++) {
manateeImages[i] = BitmapFactory.decodeResource(
context.getResources(), manatees[i]);
manateeThumbs[i] = Bitmap.createScaledBitmap(
manateeImages[i], 100, 100, false);
}
}
@Override
public int getCount() {
Log.v(TAG, "in getCount()");
return manatees.length;
}
public int getViewTypeCount() {
Log.v(TAG, "in getViewTypeCount()");
return 1;
}
public int getItemViewType(int position) {
Log.v(TAG, "in getItemViewType() for position " + position);
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
Log.v(TAG, "in getView for position " + position
+ ", convertView is "
+ ((convertView == null) ? "null" : "being recycled"));
if (convertView == null) {
convertView = mInflater.inflate(R.layout.gridp_w_picpath, null);
convertViewCounter++;
Log.v(TAG, convertViewCounter
+ " convertViews have been created");
holder = new ViewHolder();
holder.p_w_picpath = (ImageView) convertView
.findViewById(R.id.gridImageView);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.p_w_picpath.setImageBitmap(manateeThumbs[position]);
return convertView;
}
@Override
public Object getItem(int position) {
Log.v(TAG, "in getItem() for position " + position);
return manateeImages[position];
}
@Override
public long getItemId(int position) {
Log.v(TAG, "in getItemId() for position " + position);
return position;
}
}
}
30、ScrollView是设置带有垂直滚动条的View容器的控件,ProgressBar和RatingBar控件类似于滑块,第一个用于直观的显示某项操作的进度,而二个用于显示评价的星级,Chronometer控件是一个累积的计时器,如果希望显示一个倒计时器,可以用CountDownTimer类。WebView是一种显示HTML的特殊视图。
31、使用样式:
对于Text,可以直接设置HTML样式:
<string name="styledText"><i>Static</i> style in a <b>TextView</b>.</string>
<i>,<b>,<u>,<sup>(上标),<sub>(下标),<strike>(删除线),<big>,<small>,<monospace>