歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

百度貼吧布局框架的研究與實現(Android版本)

還記得幾個月前剛接觸“百度貼吧”這款應用時,瞬間就被它的懸浮式標題欄以及標簽欄所吸引,雖然當時身邊有個UI的MM說懸浮式一般都是具備隱藏的功能時才設計成這樣的,一般情況下還是用直通式的好,在這裡我也不討論孰優孰劣,截取兩個圖,大家自己品味下。

懸浮式標題欄和標簽欄:(百度貼吧);直通式標題欄和標簽欄:(QQ空間)

  

本文的目的就是研究下百度貼吧的這個標題欄和標簽欄的實現原理;

1、 懸浮式標題欄的實現

實現原理有兩種:1)在布局文件中設置標題欄的layout_margin屬性;2)給標題欄設置一個9-patch格式的background圖片,在這種圖片上設置上下左右的空白間隔,如下圖所示,背景圖片的top、left和right分別有一個像素的空白,bottom則是兩個像素。

使用第二種方式實現的標題欄的布局文件如下:

  1. <!-- 標題欄 -->  
  2.     <LinearLayout  
  3.         Android:id="@+id/home_layout_bar"  
  4.         android:layout_width="fill_parent"  
  5.         android:layout_height="wrap_content"  
  6.         android:layout_alignParentTop="true"  
  7.         android:layout_gravity="top"  
  8.         android:background="@drawable/title_bg"  
  9.         android:gravity="center" >  
  10.   
  11.         <LinearLayout  
  12.             android:layout_width="fill_parent"  
  13.             android:layout_height="wrap_content"  
  14.             android:background="@drawable/home_topbar_bg"  
  15.             android:gravity="center"  
  16.             android:orientation="horizontal" >  
  17.   
  18.             <!-- 我的貼吧 -->  
  19.             <ImageButton  
  20.                 android:id="@+id/home_bt_like"  
  21.                 android:layout_width="fill_parent"  
  22.                 android:layout_height="fill_parent"  
  23.                 android:layout_gravity="center"  
  24.                 android:layout_margin="0.0dip"  
  25.                 android:layout_weight="1.0"  
  26.                 android:background="@null"  
  27.                 android:padding="0.0dip"  
  28.                 android:paddingBottom="2.0dip"  
  29.                 android:scaleType="center"  
  30.                 android:src="@drawable/home_bt_like_on" />  
  31.   
  32.             <!-- 我的標簽 -->  
  33.             <ImageButton  
  34.                 android:id="@+id/home_bt_mark"  
  35.                 android:layout_width="fill_parent"  
  36.                 android:layout_height="fill_parent"  
  37.                 android:layout_gravity="center"  
  38.                 android:layout_margin="0.0dip"  
  39.                 android:layout_weight="1.0"  
  40.                 android:background="@null"  
  41.                 android:padding="0.0dip"  
  42.                 android:paddingBottom="2.0dip"  
  43.                 android:scaleType="center"  
  44.                 android:src="@drawable/home_bt_mark" />  
  45.         </LinearLayout>  
  46.     </LinearLayout>  
其中title_bg就是用來實現懸浮效果的9-patch背景圖片,這裡為了優化視覺上的效果,在背景圖片上又加了一層圖片,也就是home_topbar_bg,加與不加的對比效果如圖:

我的貼吧和我的書簽這兩個按鈕的按下與松開的是通過切換android:background和android:src的圖片資源來實現的,而沒有采用通常的selector方式,代碼中設置按鈕的單擊響應函數,更換按鈕圖片資源的關鍵代碼如下:

  1. mButtonLike.setBackgroundResource(R.drawable.home_topbar_bt);  
  2. mButtonLike.setImageResource(R.drawable.home_bt_like_on);  
  3. mButtonMark.setBackgroundDrawable(null);  
  4. mButtonMark.setImageResource(R.drawable.home_bt_mark);  

2、 懸浮式標簽欄的實現

標簽欄的實現有很多種組合,比較省事的是使用系統提供的TabHost+TabWidget,比較自由的是使用TabHost+RadioGroup,下面使用第二種方式。

標簽欄懸浮效果同樣是通過9-patch背景圖片實現的,如下圖:

標簽欄的實現必須具備三個基本元素,如下圖所示,分別是1)id為@android:id/tabhost的<TabHost>標簽;2)id為@android:id/tabcontent的<FrameLayout>標簽;3)id為@android:id/tabs的<TabWidget>標簽。如下圖所示:

由於這裡我們使用TabHost+RadioGroup的方式,也就是使用RadioGroup代替TabWidget,所以布局文件中TabWidget的可見性設置為gone,緊接上面布局的是RadioGroup的布局:

  1. <FrameLayout  
  2.     android:layout_width="fill_parent"  
  3.     android:layout_height="wrap_content"  
  4.     android:layout_gravity="bottom"  
  5.     android:layout_marginTop="-10.0dip"  
  6.     android:background="@drawable/maintab_toolbar_bg"  
  7.     android:paddingLeft="7.0dip"  
  8.     android:paddingRight="7.0dip" >  
  9.   
  10.     <RadioGroup  
  11.         android:id="@+id/main_radio"  
  12.         android:layout_width="fill_parent"  
  13.         android:layout_height="wrap_content"  
  14.         android:gravity="center_vertical"  
  15.         android:orientation="horizontal" >  
  16.   
  17.         <RadioButton  
  18.             android:id="@+id/radio_home"  
  19.               
  20.             android:drawableTop="@drawable/tabs_home"  
  21.             android:text="@string/bar" />  
  22.   
  23.         <RadioButton  
  24.             android:id="@+id/radio_mention"  
  25.               
  26.             android:drawableTop="@drawable/tabs_sort"  
  27.             android:text="@string/remind" />  
  28.   
  29.         <RadioButton  
  30.             android:id="@+id/radio_person_info"  
  31.               
  32.             android:drawableTop="@drawable/tabs_search"  
  33.             android:text="@string/person_info" />  
  34.   
  35.         <RadioButton  
  36.             android:id="@+id/radio_more"  
  37.               
  38.             android:drawableTop="@drawable/tabs_more"  
  39.             android:text="@string/more" />  
  40.     </RadioGroup>  
  41.   
  42.     <TextView  
  43.         android:id="@+id/message_mention"  
  44.         android:layout_width="wrap_content"  
  45.         android:layout_height="wrap_content"  
  46.         android:layout_gravity="top|left|center"  
  47.         android:layout_marginLeft="115.0dip"  
  48.         android:layout_marginTop="-5.0dip"  
  49.         android:background="@drawable/message_tips"  
  50.         android:gravity="center"  
  51.         android:text=""  
  52.         android:textColor="#ffffffff"  
  53.         android:textSize="13.0sp"  
  54.         android:visibility="visible" />  
  55.   
  56.     <TextView  
  57.         android:id="@+id/message_person"  
  58.         android:layout_width="wrap_content"  
  59.         android:layout_height="wrap_content"  
  60.         android:layout_gravity="top|left|center"  
  61.         android:layout_marginLeft="190.0dip"  
  62.         android:layout_marginTop="-5.0dip"  
  63.         android:background="@drawable/message_tips"  
  64.         android:gravity="center"  
  65.         android:text=""  
  66.         android:textColor="#ffffffff"  
  67.         android:textSize="13.0sp"  
  68.         android:visibility="visible" />  
  69. </FrameLayout>  

其中

1) maintab_toolbar_bg 是標簽欄的背景圖,實現懸浮效果;

2) RadioButton中的                   

android:drawableTop="@drawable/tabs_sort"

android:text="@string/remind"

組合可以輕松實現圖片上文字下的效果;

3) FrameLayout中的android:layout_marginTop="-10.0dip"實現標簽欄與上方id為tabcontent的FrameLayout部分重疊的效果(10.0dip);

4)兩個TextView和FrameLayout配合實現下圖中標簽右上角的消息個數提示功能

接下來就是代碼如何實現標簽的添加,標簽的點擊響應等等,直接看代碼了:

  1. package com.hust.iprai.wen;  
  2.   
  3. import android.app.AlertDialog;  
  4. import android.app.TabActivity;  
  5. import android.content.DialogInterface;  
  6. import android.content.Intent;  
  7. import android.os.Bundle;  
  8. import android.view.KeyEvent;  
  9. import android.widget.CompoundButton;  
  10. import android.widget.RadioButton;  
  11. import android.widget.TabHost;  
  12. import android.widget.TextView;  
  13.   
  14. public class TiebaActivity extends TabActivity implements  
  15.         CompoundButton.OnCheckedChangeListener {  
  16.   
  17.     private static final String HOME_TAB = "home_tab";  
  18.     private static final String MENTION_TAB = "mention_tab";  
  19.     private static final String PERSON_TAB = "person_tab";  
  20.     private static final String MORE_TAB = "more_tab";  
  21.   
  22.     private Intent mHomeIntent = null;  
  23.     private Intent mMentionIntent = null;  
  24.     private Intent mPersonIntent = null;  
  25.     private Intent mMoreIntent = null;  
  26.   
  27.     private TabHost mTabHost = null;  
  28.   
  29.     private TextView mMessageTipsMention = null;  
  30.     private TextView mMessageTipsPerson = null;  
  31.   
  32.     @Override  
  33.     public void onCreate(Bundle savedInstanceState) {  
  34.         super.onCreate(savedInstanceState);  
  35.         setContentView(R.layout.maintabs_activity);  
  36.   
  37.         mTabHost = getTabHost();  
  38.         initIntents();  
  39.         initTips();  
  40.         initRadios();  
  41.         setupIntents();  
  42.     }  
  43.       
  44.     private void initIntents() {  
  45.         mHomeIntent = new Intent(this, HomeActivity.class);  
  46.         mMentionIntent = new Intent(this, MentionActivity.class);  
  47.         mPersonIntent = new Intent(this, PersonInfoActivity.class);  
  48.         mMoreIntent = new Intent(this, MoreActivity.class);  
  49.     }  
  50.       
  51.     private void initTips() {  
  52.         mMessageTipsMention = (TextView) findViewById(R.id.message_mention);  
  53.         mMessageTipsPerson = (TextView) findViewById(R.id.message_person);  
  54.         mMessageTipsMention.setText("2");  
  55.         mMessageTipsPerson.setText("4");  
  56.     }  
  57.   
  58.     private void initRadios() {  
  59.         ((RadioButton) findViewById(R.id.radio_home))  
  60.                 .setOnCheckedChangeListener(this);  
  61.         ((RadioButton) findViewById(R.id.radio_mention))  
  62.                 .setOnCheckedChangeListener(this);  
  63.         ((RadioButton) findViewById(R.id.radio_person_info))  
  64.                 .setOnCheckedChangeListener(this);  
  65.         ((RadioButton) findViewById(R.id.radio_more))  
  66.                 .setOnCheckedChangeListener(this);  
  67.     }  
  68.   
  69.     private void setupIntents() {  
  70.         ((RadioButton) findViewById(R.id.radio_home)).setChecked(true);  
  71.         mTabHost.addTab(buildTabSpec(HOME_TAB, mHomeIntent));  
  72.         mTabHost.addTab(buildTabSpec(MENTION_TAB, mMentionIntent));  
  73.         mTabHost.addTab(buildTabSpec(PERSON_TAB, mPersonIntent));  
  74.         mTabHost.addTab(buildTabSpec(MORE_TAB, mMoreIntent));  
  75.         mTabHost.setCurrentTabByTag(HOME_TAB);  
  76.     }  
  77.   
  78.     private TabHost.TabSpec buildTabSpec(String tag, Intent intent) {  
  79.         TabHost.TabSpec tabSpec = mTabHost.newTabSpec(tag);  
  80.         tabSpec.setContent(intent).setIndicator("",  
  81.                 getResources().getDrawable(R.drawable.icon));  
  82.         return tabSpec;  
  83.     }  
  84.   
  85.     public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {  
  86.         if (isChecked) {  
  87.             switch (buttonView.getId()) {  
  88.             case R.id.radio_home:  
  89.                 mTabHost.setCurrentTabByTag(HOME_TAB);  
  90.                 break;  
  91.             case R.id.radio_mention:  
  92.                 mTabHost.setCurrentTabByTag(MENTION_TAB);  
  93.                 break;  
  94.             case R.id.radio_person_info:  
  95.                 mTabHost.setCurrentTabByTag(PERSON_TAB);  
  96.                 break;  
  97.             case R.id.radio_more:  
  98.                 mTabHost.setCurrentTabByTag(MORE_TAB);  
  99.                 break;  
  100.             default:  
  101.                 break;  
  102.             }  
  103.         }  
  104.     }  
  105.   
  106.     @Override  
  107.     public boolean dispatchKeyEvent(KeyEvent event) {  
  108.         if ((event.getAction() == KeyEvent.ACTION_DOWN)  
  109.                 && (event.getKeyCode() == KeyEvent.KEYCODE_BACK)) {  
  110.             quitDialog();  
  111.         }  
  112.         return super.dispatchKeyEvent(event);  
  113.     }  
  114.   
  115.     private void quitDialog() {  
  116.         new AlertDialog.Builder(this)  
  117.                 .setTitle(R.string.alerm_title)  
  118.                 .setIcon(null)  
  119.                 .setCancelable(false)  
  120.                 .setMessage(R.string.alert_quit_confirm)  
  121.                 .setPositiveButton(R.string.alert_yes_button,  
  122.                         new DialogInterface.OnClickListener() {  
  123.   
  124.                             public void onClick(DialogInterface dialog,  
  125.                                     int which) {  
  126.                                 TiebaActivity.this.finish();  
  127.                             }  
  128.                         })  
  129.                 .setNegativeButton(R.string.alert_no_button,  
  130.                         new DialogInterface.OnClickListener() {  
  131.   
  132.                             public void onClick(DialogInterface dialog,  
  133.                                     int which) {  
  134.                                 dialog.dismiss();  
  135.                             }  
  136.                         }).create().show();  
  137.     }  
  138. }  
Copyright © Linux教程網 All Rights Reserved