經過前面兩篇:html
咱們對Android應用程序運行原理及佈局文件可謂有了比較深入的認識和理解,而且用「Hello World!」程序來實踐證實了。在繼續深刻Android開發之旅以前,有必要解決前兩篇中沒有介紹的遺留問題:View的幾種佈局顯示方法,之後就不會在針對佈局方面作過多的介紹。View的佈局顯示方式有下面幾種:線性佈局(Linear Layout)、相對佈局(Relative Layout)、表格佈局(Table Layout)、網格視圖(Grid View)、標籤佈局(Tab Layout)、列表視圖(List View)、絕對佈局(AbsoluteLayout)。本文雖然是介紹View的佈局方式,但不只僅是這樣,其中涉及了不少小的知識點,絕對能給你帶來Android大餐!java
本文的主要內容就是分別介紹以上視圖的七種佈局顯示方式效果及實現,大綱以下:android
經過前面的學習咱們知道:在一個Android應用程序中,用戶界面經過View和ViewGroup對象構建。Android中有不少種View和ViewGroup,他們都繼承自View類。View對象是Android平臺上表示用戶界面的基本單元。數據庫
View的佈局顯示方式直接影響用戶界面,View的佈局方式是指一組View元素如何佈局,準確的說是一個ViewGroup中包含的一些View怎麼樣佈局。ViewGroup類是佈局(layout)和視圖容器(View container)的基類,此類也定義了ViewGroup.LayoutParams類,它做爲佈局參數的基類,此類告訴父視圖其中的子視圖想如何顯示。例如,XML佈局文件中名爲layout_something的屬性(參加上篇的4.2節)。咱們要介紹的View的佈局方式的類,都是直接或間接繼承自ViewGroup類,以下圖所示:
編程
圖一、繼承自ViewGroup的一些佈局類
數組
其實,全部的佈局方式均可以歸類爲ViewGroup的5個類別,即ViewGroup的5個直接子類。其它的一些佈局都擴展自這5個類。下面分小節分別介紹View的七種佈局顯示方式。app
線性佈局:是一個ViewGroup以線性方向顯示它的子視圖(view)元素,即垂直地或水平地。以前咱們的Hello World!程序中view的佈局方式就是線性佈局的,必定不陌生!以下所示res/layour/main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal"><!-- have an eye on ! -->
<Button android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello, I am a Button1"
android:layout_weight="1"
/>
<Button android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello, I am a Button2"
android:layout_weight="1"
/>
<Button android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello, I am a Button3"
android:layout_weight="1"
/>
<Button android:id="@+id/button4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello, I am a Button4"
android:layout_weight="1"
/>
<Button android:id="@+id/button5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello, I am a Button5"
android:layout_weight="1"
/>
</LinearLayout>ide
從上面能夠看出根LinearLayout視圖組(ViewGroup)包含5個Button,它的子元素是以線性方式(horizontal,水平的)佈局,運行效果以下圖所示:函數
圖二、線性佈局(水平或者說是橫向)工具
若是你在android:orientation="horizontal"設置爲vertical,則是是垂直或者說是縱向的,以下圖所示:
圖三、線性佈局(垂直或者說是縱向)
這個屬性很關鍵,若是你沒有顯示設置它,它默認爲0。把上面佈局文件(水平顯示的那個)中的這個屬性都去掉,運行會得出以下結果:
圖四、layout_weight屬性
沒有了這個屬性,咱們原本定義的5個Button運行後卻只顯示了2個Button,爲何呢??
"weight"顧名思義是權重的意思,layout_weight 用於給一個線性佈局中的諸多視圖的重要程度賦值。全部的視圖都有一個layout_weight值,默認爲零,意思是須要顯示多大的視圖就佔據多大的屏幕空間。這就不難解釋爲何會形成上面的狀況了:Button1~Button5都設置了layout_height和layout_width屬性爲wrap_content即包住文字內容,他們都沒有設置layout_weight 屬性,即默認爲0.,這樣Button1和Button2根據須要的內容佔據了整個屏幕,別的就顯示不了啦!
若賦一個高於零的值,則將父視圖中的可用空間分割,分割大小具體取決於每個視圖的layout_weight值以及該值在當前屏幕布局的總體layout_weight值和在其它視圖屏幕布局的layout_weight值中所佔的比率而定。舉個例子:好比說咱們在 水平方向上有一個文本標籤和兩個文本編輯元素。該文本標籤並沒有指定layout_weight值,因此它將佔據須要提供的最少空間。若是兩個文本編輯元素每個的layout_weight值都設置爲1,則二者平分在父視圖佈局剩餘的寬度(由於咱們聲明這二者的重要度相等)。若是兩個文本編輯元素其中第一個的layout_weight值設置爲1,而第二個的設置爲2,則剩餘空間的三分之二分給第一個,三分之一分給第二個(數值越小,重要度越高)。
相對佈局:是一個ViewGroup以相對位置顯示它的子視圖(view)元素,一個視圖能夠指定相對於它的兄弟視圖的位置(例如在給定視圖的左邊或者下面)或相對於RelativeLayout的特定區域的位置(例如底部對齊,或中間偏左)。
相對佈局是設計用戶界面的有力工具,由於它消除了嵌套視圖組。若是你發現你使用了多個嵌套的
LinearLayout
視圖組後,你能夠考慮使用一個RelativeLayout
視圖組了。看下面的res/layour/main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:id="@+id/label"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Type here:"/>
<EditText
android:id="@+id/entry"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@android:drawable/editbox_background"
android:layout_below="@id/label"/><!-- have an eye on ! -->
<Button
android:id="@+id/ok"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/entry" <!-- have an eye on ! -->
android:layout_alignParentRight="true" <!-- have an eye on ! -->
android:layout_marginLeft="10dip"
android:text="OK" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toLeftOf="@id/ok" <!-- have an eye on ! -->
android:layout_alignTop="@id/ok" <!-- have an eye on ! -->
android:text="Cancel" />
</RelativeLayout>
從上面的佈局文件咱們知道,RelativeLayout視圖組包含一個TextView、一個EditView、兩個Button,注意標記了<!-- have an eye on ! -->(請注意運行代碼的時候,請把這些註釋去掉,不然會運行出錯,上面加上是爲了更加醒目!)的屬性,在使用相對佈局方式中就是使用這些相似的屬性來定位視圖到你想要的位置,它們的值是你參照的視圖的id。這些屬性的意思很簡單,就是英文單詞的直譯,就很少作介紹了。運行以後,得以下結果:
圖五、相對佈局
表格佈局:是一個ViewGroup以表格顯示它的子視圖(view)元素,即行和列標識一個視圖的位置。其實Android的表格佈局跟HTML中的表格佈局很是相似,TableRow
就像HTML表格的<tr>標記。
用表格佈局須要知道如下幾點:
看下面的res/layour/main.xml:
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:shrinkColumns="0,1,2"><!-- have an eye on ! -->
<TableRow><!-- row1 -->
<Button android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello, I am a Button1"
android:layout_column="0"
/>
<Button android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello, I am a Button2"
android:layout_column="1"
/>
</TableRow>
<TableRow><!-- row2 -->
<Button android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello, I am a Button3"
android:layout_column="1"
/>
<Button android:id="@+id/button4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello, I am a Button4"
android:layout_column="1"
/>
</TableRow>
<TableRow>
<Button android:id="@+id/button5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello, I am a Button5"
android:layout_column="2"
/>
</TableRow>
</TableLayout>
運行以後能夠得出下面的結果:
圖六、表格佈局
列表佈局:是一個ViewGroup以列表顯示它的子視圖(view)元素,列表是可滾動的列表。列表元素經過ListAdapter自動插入到列表。
ListAdapter
:擴展自Adapter
,它是ListView
和數據列表之間的橋樑。ListView能夠顯示任何包裝在ListAdapter中的數據。該類提供兩個公有類型的抽象方法:
下面經過一個例子來,建立一個可滾動的列表,並從一個字符串數組讀取列表元素。當一個元素被選擇時,顯示該元素在列表中的位置的消息。
1)、首先,將res/layour/main.xml的內容置爲以下:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10dp"
android:textSize="16sp" >
</TextView>
這樣就定義了元素在列表中的佈局。
2)、src/skynet.com.cnblogs.www/HelloWorld.java文件的代碼以下:
package skynet.com.cnblogs.www; import android.app.ListActivity; import android.os.Bundle; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; import android.widget.AdapterView.OnItemClickListener; public class HelloWorld extends ListActivity {
//注意這裏Helloworld類不是擴展自Acitvity,而是擴展自ListAcitivty /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setListAdapter(new ArrayAdapter<String>(this, R.layout.main, COUNTRIES)); ListView lv = getListView(); lv.setTextFilterEnabled(true); lv.setOnItemClickListener(new OnItemClickListener() { public void onItemClick(AdapterView<?> parent, View view, int position, long id) { // When clicked, show a toast with the TextView text Toast.makeText(getApplicationContext(), ((TextView) view).getText(), Toast.LENGTH_SHORT).show(); } }); } static final String[] COUNTRIES = new String[] { "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24" }; }
Note:onCreate()函數中並不像往常同樣經過setContentView()爲活動(Activity)加載佈局文件,替代的是經過setListAdapter(ListAdapter)自動添加一個ListView填充整個屏幕的ListActivity。在此文件中這個方法以一個ArrayAdapter爲參數:setListAdapter(new ArrayAdapter<String>(this, R.layout.main, COUNTRIES)),這個ArrayAdapter管理填入ListView中的列表元素。ArrayAdapter的構造函數的參數爲:this(表示應用程序的上下文context)、表示ListViewde佈局文件(這裏是R.layout.main)、插入ListView的List對象對數組(這裏是COUNTRES)。
setOnItemClickListener(OnItemClickListener)定義了每一個元素的點擊(on-click)的監聽器,當ListView中的元素被點擊時,
onItemClick()方法被調用,在這裏是即一個
Toast
消息——每一個元素的位置將顯示。
3)、運行應用程序得以下結果(點擊1以後,在下面顯示了1):
圖七、列表佈局
NOTE:若是你改了HelloWorld extends ListActivity 而不是Activity以後,運行程序是提示:「Conversion to Dalvik format failed with error 1」。能夠這麼解決:解決辦法是 Project > Clean... > Clean project selected below > Ok
上面咱們是把要填充到ListView中的元素硬編碼到HelloWorld.java文件中,這樣就缺少靈活性!也不符合推薦的應用程序的界面與控制它行爲的代碼更好地分離的準則!
其實咱們能夠把要填充到ListView的元素寫到res/values/strings.xml
文件中的<string-array>
元素中,而後再源碼中動態地讀取。這樣strings.xml的內容相似下面:
<?xml version="1.0" encoding="utf-8"?> <resources> <string-array name="countries_array"> <item>1</item> <item>2</item> <item>3</item> <item>4</item> <item>5</item> <item>6</item> <item>7</item> </string-array> </resources>
然而HelloWorld.java文件中的onCreate()函數,則這樣動態訪問這個數組及填充到ListVies:
String[] countries = getResources().getStringArray(R.array.countries_array);
setListAdapter(new ArrayAdapter<String>(this, R.layout.list_item, countries));
首先總結一下列表佈局的關鍵部分:
其中Adapter是ListView和數據源之間的橋樑,根據數據源的不一樣Adapter能夠分爲三類:
使用ArrayAdapter(數組適配器)顧名思義,須要把數據放入一個數組以便顯示,上面的例子就是這樣的;SimpleAdapter能定義各類各樣的佈局出來,能夠放上ImageView(圖片),還能夠放上Button(按鈕),CheckBox(複選框)等等;SimpleCursorAdapter是和數據庫有關的東西。篇幅有限後面兩種就不舉例實踐了。你能夠參考android ListView詳解orArrayAdapter ,SimpleAdapter ,SimpleCursorAdapter 區別。
網格佈局:是一個ViewGroup以網格顯示它的子視圖(view)元素,即二維的、滾動的網格。網格元素經過ListAdapter自動插入到網格。
ListAdapter跟上面的列表佈局是同樣的,這裏就不重複累述了。
下面也經過一個例子來,建立一個顯示圖片縮略圖的網格。當一個元素被選擇時,顯示該元素在列表中的位置的消息。
1)、首先,將上面實踐截取的圖片放入res/drawable/
2)、res/layour/main.xml的內容置爲以下:這個GridView填滿整個屏幕,並且它的屬性都很好理解,按英文單詞的意思就對了。
<?xml version="1.0" encoding="utf-8"?> <GridView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/gridview" android:layout_width="fill_parent" android:layout_height="fill_parent" android:columnWidth="90dp" android:numColumns="auto_fit" android:verticalSpacing="10dp" android:horizontalSpacing="10dp" android:stretchMode="columnWidth" android:gravity="center" />
3)、而後,HelloWorld.java文件中onCreate()函數以下:
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); GridView gridview = (GridView) findViewById(R.id.gridview); gridview.setAdapter(new ImageAdapter(this)); gridview.setOnItemClickListener(new OnItemClickListener() { public void onItemClick(AdapterView<?> parent, View v, int position, long id) { Toast.makeText(HelloWorld.this, " " + position, Toast.LENGTH_SHORT).show(); } }); }
onCreate()函數跟一般同樣,首先調用超類的onCreate()函數函數,而後經過setContentView()爲活動(Activity)加載佈局文件。緊接着是,經過GridView的id獲取佈局文件中的gridview,而後調用它的setListAdapter(ListAdapter)
函數填充它,它的參數是一個咱們自定義的ImageAdapter。後面的工做跟列表佈局中同樣,爲監聽網格中的元素被點擊的事件而作的工做。
4)、實現咱們自定義ImageAdapter,新添加一個類文件,它的代碼以下:
package skynet.com.cnblogs.www; import android.content.Context; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.GridView; import android.widget.ImageView; public class ImageAdapter extends BaseAdapter { private Context mContext; public ImageAdapter(Context c) { mContext = c; } public int getCount() { return mThumbIds.length; } public Object getItem(int position) { return null; } public long getItemId(int position) { return 0; } // create a new ImageView for each item referenced by the Adapter public View getView(int position, View convertView, ViewGroup parent) { ImageView imageView; if (convertView == null) { // if it's not recycled, initialize some attributes imageView = new ImageView(mContext); imageView.setLayoutParams(new GridView.LayoutParams(85, 85)); imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); imageView.setPadding(8, 8, 8, 8); } else { imageView = (ImageView) convertView; } imageView.setImageResource(mThumbIds[position]); return imageView; } // references to our images private Integer[] mThumbIds = { R.drawable.linearlayout1, R.drawable.linearlayout2, R.drawable.linearlayout3, R.drawable.listview, R.drawable.relativelayout, R.drawable.tablelayout }; }
ImageAdapter類擴展自BaseAdapter,因此首先得實現它所要求必須實現的方法。構造函數和getcount()函數很好理解,而getItem(int)應該返回實際對象在適配器中的特定位置,可是這裏咱們不須要。相似地,getItemId(int)應該返回元素的行號,可是這裏也不須要。
這裏重點要介紹的是getView()方法,它爲每一個要添加到ImageAdapter的圖片都建立了一個新的View。當調用這個方法時,一個View是循環再用的,所以要確認對象是否爲空。若是是空的話,一個
ImageView
就被實例化且配置想要的顯示屬性:
setLayoutParams(ViewGroup.LayoutParams)
:設置View的高度和寬度,這確保無論drawable中圖片的大小,每一個圖片都被從新設置大小且剪裁以適應這些尺寸。setScaleType(ImageView.ScaleType)
:聲明圖片應該向中心剪裁(若是須要的話)。setPadding(int, int, int, int)
:定義補距,若是圖片有不一樣的橫縱比,小的補距將致使更多的剪裁以適合設置的ImageView的高度和寬度。若是View傳到getView()不是空的,則本地的ImageView初始化時將循環再用View對象。在getView()方法末尾,position整數傳入setImageResource()方法以從mThumbIds數組中選擇圖片。
運行程序會獲得以下結果(點擊第一張圖片以後):
圖八、網格佈局
絕對佈局:是一個ViewGroup以絕對方式顯示它的子視圖(view)元素,即以座標的方式來定位在屏幕上位置。
這種佈局方式很好理解,在佈局文件或編程地設置View的座標,從而絕對地定位。以下所示佈局文件:
<AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/AbsoluteLayout01" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:id="@+id/txtIntro" android:text="絕對佈局" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_x="20dip"<!-- have an eye on ! --> android:layout_y="20dip"><!-- have an eye on ! --> </TextView> </AbsoluteLayout>
簡單吧,這裏不在深刻了!
注意:4.0後,標籤佈局已推薦使用FragmentActivity來實現,相關閱讀: http://www.cnblogs.com/ronli/p/3330065.html。
標籤佈局:是一個ViewGroup以標籤的方式顯示它的子視圖(view)元素,就像在Firefox中的一個窗口中顯示多個網頁同樣。
爲了狂建立一個標籤UI(tabbed UI),須要使用到TabHost
和TabWidget。
TabHost
必須是佈局的根節點,它包含爲了顯示標籤的TabWidget和顯示標籤內容的
FrameLayout
。
能夠有兩種方式實現標籤內容:使用標籤在同一個活動中交換視圖、使用標籤在徹底隔離的活動之間改變。根據你的須要,選擇不一樣的方式,可是若是每一個標籤提供不一樣的用戶活動,爲每一個標籤選擇隔離的活動,所以你能夠更好地以分離的組管理應用程序,而不是一個巨大的應用程序和佈局。
下面還有一個例子來建立一個標籤UI,每一個標籤使用隔離的活動。
1)、在項目中創建三個隔離的Activity類:ArtistisActivity、AlbumActivity、SongActivity。它們每一個表示一個分隔的標籤。每一個經過TextView顯示簡單的一個消息,例如:
public class ArtistsActivity extends Activity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); TextView textview = new TextView(this); textview.setText("This is the Artists tab"); setContentView(textview); } }
其它兩個類也相似。
2)、設置每一個標籤的圖標,每一個圖標應該有兩個版本:一個是選中時的,一個是未選中時的。一般的設計建議是,選中的圖標應該是深色(灰色),未選中的圖標是淺色(白色)。
如今建立一個state-list drawable指定哪一個圖標表示標籤的狀態:將圖片放到res/drawable目錄下並建立一個新的XML文件命名爲ic_tab_artists.xml
,內容以下:
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <!-- When selected, use grey --> <item android:drawable="@drawable/ic_tab_artists_grey" android:state_selected="true" /> <!-- When not selected, use white--> <item android:drawable="@drawable/ic_tab_artists_white" /> </selector>
3)、res/layour/main.xml的內容置爲以下:
<?xml version="1.0" encoding="utf-8"?> <TabHost xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/tabhost" android:layout_width="fill_parent" android:layout_height="fill_parent"> <LinearLayout android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" android:padding="5dp"> <TabWidget android:id="@android:id/tabs" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <FrameLayout android:id="@android:id/tabcontent" android:layout_width="fill_parent" android:layout_height="fill_parent" android:padding="5dp" /> </LinearLayout> </TabHost>
這個佈局將顯示標籤和提供上面建立的活動之間的導航。TabHost
要求包含一個TabWidget和一個
FrameLayout
。TabWidget和FrameLayout
TabHost
以線性垂直地顯示。
4)、HelloWorld.java文件源碼以下:
package skynet.com.cnblogs.www; import android.widget.TabHost; import android.app.TabActivity; import android.content.Intent; import android.content.res.Resources; import android.os.Bundle; public class HelloWorld extends TabActivity{ /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Resources res = getResources(); // Resource object to get Drawables TabHost tabHost = getTabHost(); // The activity TabHost TabHost.TabSpec spec; // Resusable TabSpec for each tab Intent intent; // Reusable Intent for each tab // Create an Intent to launch an Activity for the tab (to be reused) intent = new Intent().setClass(this, ArtistsActivity.class); // Initialize a TabSpec for each tab and add it to the TabHost spec = tabHost.newTabSpec("artists").setIndicator("Artists", res.getDrawable(R.drawable.ic_tab_artists)) .setContent(intent); tabHost.addTab(spec); // Do the same for the other tabs intent = new Intent().setClass(this, AlbumsActivity.class); spec = tabHost.newTabSpec("albums").setIndicator("Albums", res.getDrawable(R.drawable.ic_tab_artists)) .setContent(intent); tabHost.addTab(spec); intent = new Intent().setClass(this, SongsActivity.class); spec = tabHost.newTabSpec("songs").setIndicator("Songs", res.getDrawable(R.drawable.ic_tab_artists)) .setContent(intent); tabHost.addTab(spec); tabHost.setCurrentTab(2); } }
設置每一個標籤的文字和圖標,並分配每一個標籤一個活動(這裏爲了方便三個標籤都有相同的圖標)。TabHost的引用第一次經過getTabHost()獲取。而後,爲每一個標籤,建立
TabHost.TabSpec定義標籤的屬性。
newTabSpec(String)
方法建立一個新的TabHost.TabSpec
以給定的字符串標識標籤。調用TabHost.TabSpec
, setIndicator(CharSequence, Drawable)
爲每一個標籤設置文字和圖標,調用setContent(Intent)
指定Intent
去打開合適的活動。每一個TabHost.TabSpec
經過調用addTab(TabHost.TabSpec)添加到TabHost。
最後,
setCurrentTab(int)
設置打開默認顯示的標籤,經過索引標籤的位置。
5)、打開Android的清單文件AndroidManifest.xml,添加NoTitleBar主題到HelloWorld的
<activity>標記。這將移除默認應用程序的標題和頂端佈局,給標籤騰出位置。
<activity>
標記應該像這樣:
<activity android:name=".HelloWorld" android:label="@string/app_name" android:theme="@android:style/Theme.NoTitleBar">
你運行這個程序可以獲得什麼結果呢?請自行檢查。不過我在這裏告訴你頗有可能會運行不了,報「java.lang.NullPointerException」錯!我想運行這個例子的不少人都會有這個問題,不信你試試!
PS:其實這也算是Android的一個bug,並且這個bug在2.2中尚未解決,這個問題全球N多人都碰到了,並在http://code.google.com/p/android/issues中掛號了,相關問題的編號有不止一個。
接着往下看……
若是你看了我這篇文章,你必定會是個幸運兒!通過我艱苦的調試+找資料,我找到了解決方法:
在清單文件AndroidManifest.xml,添加下面三個Activity:
<activity android:name=".AlbumsActivity" android:label="@string/app_name"></activity>
<activity android:name=".ArtistsActivity" android:label="@string/app_name"></activity>
<activity android:name=".SongsActivity" android:label="@string/app_name"></activity>
如今運行能夠看到以下結果: