編輯:Android開發實例
在上篇文章《Android學習系列(22)--App主界面比較》中我們淺略的分析了幾個主界面布局,選了一個最大眾化的經典布局。
今天我們就這個經典布局,用代碼具體的實現它。
1.預覽圖
先看下最終的界面設計圖:
上面頂部是一個9patch背景圖片+標題文字;
下面底部是5個tab標簽,表示應用的5大模塊。
中間內容部分則是各個模塊的具體內容,可以再分類,或者直接顯示內容。
2.准備素材
按照上篇文章的界面,我們需要事先提供兩大方面的素材:頂部+底部。
頂部的素材非常簡單,最重要的事背景(9patch的圖片):
底部的素材稍微多一點:
(1).每個tab的背景都需要正常和選中兩種,一共10張圖片;
(2).每個tab之間有一張分割線,1張圖片;
(3).為了自適應屏幕寬度,並保持圖形不變形,必須tab背景和下面botton這個背景色一致,所以需要1張同背景的背景圖片。
如下:
(1).
(2).
(3).
在這裡呢,我再三考量,決定還是把圖片和文字放在一起,這樣一能大大降低代碼的復雜性,而且能保證漂亮的樣式,我們通過Photoshop來控制,靈活性大大增強。
以上是我在網上隨便找了幾張照片,稍微處理了一下,作為下面我們實現的素材。
3.實現原理
這裡,我采用了getDecorView方法,發現這種方法布局和代碼比較簡潔,看上去性能也不錯(待查)。
用核心代碼來說明一下原理:
//mainTabContainer是一個空布局,做為每個tab的容器
//activity是每個tab對應的activity
//getDecorView是對應的activity的視圖,添加到tab容器中,就能實現切換activity的效果了
mainTabContainer.removeAllViews();
mainTabIntent = new Intent(this,activity);
mainTabContainer.addView(localActivityManager.startActivity(id, mainTabIntent).getDecorView());
通過切換不同的activity的decorView,實現tab的視圖切換。
4.基本框架
布局界面思路非常清晰,頂部+底部+中間tab內容
我采用相對布局(相對於線性布局,我經常選擇幀布局和相對布局,我更喜歡這兩個小巧的布局):
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout android:id="@+id/main_tab_banner"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingLeft="10dip"
android:orientation="horizontal"
android:gravity="center"
android:background="@drawable/main_banner_bg"
android:layout_alignParentTop="true">
<!-- 標題 -->
</LinearLayout>
<LinearLayout android:id="@+id/main_tab"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center"
android:background="@drawable/tab_bg"
android:layout_alignParentBottom="true">
<!-- 內容 -->
</LinearLayout>
<LinearLayout android:id="@+id/main_tab_container"
android:layout_above="@id/main_tab"
android:layout_below="@id/main_tab_banner"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#FFFFE0">
</LinearLayout>
</RelativeLayout>
看起來很復雜的東西,分解一下就簡單的多了。
在標題處,加上一個TextView,做為標題顯示。
在內容處,我們需要填充5個Tab背景和1個分割線,請參考《Android學習系列(5)--App布局初探之簡單模型》 中的模型四,使用了layout_weight的屬性,平均分割了5個tab.
最終我們的布局文件如下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout android:id="@+id/main_tab_banner"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingLeft="10dip"
android:orientation="horizontal"
android:gravity="center"
android:background="@drawable/main_banner_bg"
android:layout_alignParentTop="true">
<TextView android:id="@+id/main_tab_banner_title"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="欣賞美花"
android:textSize="20dip"
android:textColor="#000000"/>
</LinearLayout>
<LinearLayout android:id="@+id/main_tab"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center"
android:background="@drawable/tab_bg"
android:layout_alignParentBottom="true">
<ImageView android:id="@+id/appreciate_tab_btn"
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:gravity="center_horizontal|bottom"
android:src="@drawable/appreciate_press"/>
<ImageView android:gravity="center"
android:layout_gravity="center_vertical"
android:layout_width="5dip"
android:layout_height="wrap_content"
android:src="@drawable/tab_split"/>
<ImageView android:id="@+id/discuss_tab_btn"
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal|bottom"
android:textSize="16dip"
android:src="@drawable/discuss_normal"
android:textColor="#000000"/>
<ImageView android:gravity="center"
android:layout_gravity="center_vertical"
android:layout_width="5dip"
android:layout_height="wrap_content"
android:src="@drawable/tab_split"/>
<ImageView android:id="@+id/identification_tab_btn"
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal|bottom"
android:textSize="16dip"
android:src="@drawable/identification_normal"
android:textColor="#000000"/>
<ImageView android:gravity="center"
android:layout_gravity="center_vertical"
android:layout_width="5dip"
android:layout_height="wrap_content"
android:src="@drawable/tab_split"/>
<ImageView android:id="@+id/favorite_tab_btn"
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal|bottom"
android:textSize="16dip"
android:textColor="#000000"
android:src="@drawable/favorite_normal"/>
<ImageView android:gravity="center"
android:layout_gravity="center_vertical"
android:layout_width="5dip"
android:layout_height="wrap_content"
android:src="@drawable/tab_split"/>
<ImageView android:id="@+id/setting_tab_btn"
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal|bottom"
android:textSize="16dip"
android:src="@drawable/setting_normal"
android:textColor="#000000"/>
</LinearLayout>
<LinearLayout android:id="@+id/main_tab_container"
android:layout_above="@id/main_tab"
android:layout_below="@id/main_tab_banner"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#FFFFE0">
</LinearLayout>
</RelativeLayout>
其中的main_tab_container是容器布局,到時候動態存放切換的activity的視圖。
這時候,效果圖如下:
中間的內容為空,tab點擊也沒有任何效果,我們繼續實現。
這就是布局文件main_tab_frame.xml.
5.事件效果
現在我們把點擊效果,切換標題,這些效果關聯起來。
選擇不同的tab,顯示不同的標題,同時切換不同的activity.
以點擊評花的主要代碼為例子:
//評花
discussImageView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//標題
mainTabTitleTextView.setText("評花論花");
//切換內容
setContainerView("discuss", DiscussTabActivity.class);
//切換tab頁背景
appreciateImageView.setImageResource(R.drawable.appreciate_normal);
discussImageView.setImageResource(R.drawable.discuss_press);
identificationImageView.setImageResource(R.drawable.identification_normal);
favoriteImageView.setImageResource(R.drawable.favorite_normal);
settingImageView.setImageResource(R.drawable.setting_normal);
}
});
//切換activity
public void setContainerView(String id,Class<?> activity){
mainTabContainer.removeAllViews();
mainTabIntent = new Intent(this,activity);
mainTabContainer.addView(localActivityManager.startActivity(id, mainTabIntent).getDecorView());
}
我們繼承ActivityGroup這個類,實現這個完整的類MainTabFrame.java:
public class MainTabFrame extends ActivityGroup {
//Tab Activity Layout
private LocalActivityManager localActivityManager = null;
private LinearLayout mainTabContainer = null;
private Intent mainTabIntent = null;
//Tab banner title
private TextView mainTabTitleTextView = null;
//Tab ImageView
private ImageView appreciateImageView = null;
private ImageView discussImageView = null;
private ImageView identificationImageView = null;
private ImageView favoriteImageView = null;
private ImageView settingImageView = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_tab_frame);
mainTabContainer = (LinearLayout)findViewById(R.id.main_tab_container);
localActivityManager = getLocalActivityManager();
setContainerView("appreciate", AppreciateTabActivity.class);
initTab();
}
/**
* 初始化Tab項
*/
private void initTab() {
mainTabTitleTextView = (TextView)findViewById(R.id.main_tab_banner_title);
appreciateImageView = (ImageView)findViewById(R.id.appreciate_tab_btn);
discussImageView = (ImageView)findViewById(R.id.discuss_tab_btn);
identificationImageView = (ImageView)findViewById(R.id.identification_tab_btn);
favoriteImageView = (ImageView)findViewById(R.id.favorite_tab_btn);
settingImageView = (ImageView)findViewById(R.id.setting_tab_btn);
//賞花
appreciateImageView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mainTabTitleTextView.setText("欣賞美花");
setContainerView("appreciate", AppreciateTabActivity.class);
appreciateImageView.setImageResource(R.drawable.appreciate_press);
discussImageView.setImageResource(R.drawable.discuss_normal);
identificationImageView.setImageResource(R.drawable.identification_normal);
favoriteImageView.setImageResource(R.drawable.favorite_normal);
settingImageView.setImageResource(R.drawable.setting_normal);
}
});
//評花
discussImageView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mainTabTitleTextView.setText("評花論花");
setContainerView("discuss", DiscussTabActivity.class);
appreciateImageView.setImageResource(R.drawable.appreciate_normal);
discussImageView.setImageResource(R.drawable.discuss_press);
identificationImageView.setImageResource(R.drawable.identification_normal);
favoriteImageView.setImageResource(R.drawable.favorite_normal);
settingImageView.setImageResource(R.drawable.setting_normal);
}
});
//識花
identificationImageView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mainTabTitleTextView.setText("亮眼識花");
setContainerView("identification", IdentificationTabActivity.class);
appreciateImageView.setImageResource(R.drawable.appreciate_normal);
discussImageView.setImageResource(R.drawable.discuss_normal);
identificationImageView.setImageResource(R.drawable.identification_press);
favoriteImageView.setImageResource(R.drawable.favorite_normal);
settingImageView.setImageResource(R.drawable.setting_normal);
}
});
//收藏
favoriteImageView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mainTabTitleTextView.setText("我的收藏");
setContainerView("favorite", FavoriteTabActivity.class);
appreciateImageView.setImageResource(R.drawable.appreciate_normal);
discussImageView.setImageResource(R.drawable.discuss_normal);
identificationImageView.setImageResource(R.drawable.identification_normal);
favoriteImageView.setImageResource(R.drawable.favorite_press);
settingImageView.setImageResource(R.drawable.setting_normal);
}
});
//設置
settingImageView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mainTabTitleTextView.setText("定義設置");
setContainerView("setting", SettingTabActivity.class);
appreciateImageView.setImageResource(R.drawable.appreciate_normal);
discussImageView.setImageResource(R.drawable.discuss_normal);
identificationImageView.setImageResource(R.drawable.identification_normal);
favoriteImageView.setImageResource(R.drawable.favorite_normal);
settingImageView.setImageResource(R.drawable.setting_press);
}
});
}
public void setContainerView(String id,Class<?> activity){
mainTabContainer.removeAllViews();
mainTabIntent = new Intent(this,activity);
mainTabContainer.addView(localActivityManager.startActivity(id, mainTabIntent).getDecorView());
}
}
具體的每個activity怎麼顯示的,再通過AppreciateTabActivity,DiscussTabActivity,IdentificationTabActivity,FavoriteTabActivity,SettingTabActivity這些獨自實現,不再累述。
6.擴展建議
這裡補充兩點:
(1).標題欄在上述示例中,我是放在MainTabFrame,這樣做的好處是,統一了,方便了;這樣做的缺點是,如果每個activity的標題欄是不同的按鈕,不同的操作,會有些膨脹。所以,標題欄放在主Acvtivity和子Activity中,考慮一下即可。
(2).tab的切換效果,我做的非常簡單,具體的圖片陰影,凹凸,文字色彩區分都沒有去做(本人對Photoshop實在不熟),美化方面還可以大大改進。
7.小結
通過實現這麼個簡單的主界面框架,能使我們快速的開始我們相應的感興趣項目,提供了一種大眾化得參考,是android學習者必備基礎。
這種東西的積累和分析也是能提高我們感覺應用的審美感。
Android本地化
Android應用程序可以在許多不同地區的許多設備上運行。為了使應用程序更具交互性,應用程序應該處理以適合應用程序將要使用的語言環境方面的文字,數字,文件等。在本章中,我
android monkey自動化測試改為java調用monkeyrunner Api
眾所周知,一般情況下我們使用android中的monkeyrunner進行自動化測試時,使用的是python語言來寫測試腳本。不過,最近發現可以用java調用mo
Android登錄實例
登錄應用程序的屏幕,詢問憑據登錄到一些特定的應用。可能需要登錄到Facebook,微博等本章介紹了,如何創建一個登錄界面,以及如何管理安全問題和錯誤嘗試。首先,必須定義兩
Android中Android Virtual Device(AVD)使用教程
AVD的全稱為:Android Virtual Device,就是Android運行的虛擬設備,他是Android的模擬器識別。建立的Android要運行,必須創