1. 程式人生 > >Android 開源框架ActionBarSherlock 和 ViewPager 仿網易新聞客戶端

Android 開源框架ActionBarSherlock 和 ViewPager 仿網易新聞客戶端

               

大家都知道Android的ActionBar是在3.0以上才有的,那麼在3.0以下呢,google並沒有給我提供在3.0以下支援ActionBar的包,但是外國的大牛JakeWharton實現了在3.0以下使用ActionBar, JakeWharton這位大牛是ActionBarSherlock,Android-ViewPagerIndicator ,NineOldAndroids的作者,非常厲害的一個人,Github的關注量超過2.6K,我左側的友情連結裡面有他的Github的主頁連結,有興趣的朋友可以去follow下他,今天我們使用的是他的開源框架ActionBarSherlock,ActionBarSherlock是讓Action Bar功能支援2.X後的所有平臺,而且他會自動的判斷是呼叫原生Action Bar還是使用擴充套件ActionBar,很多知名的應用也使用這個庫,我之前對ActionBar也不瞭解,所以就去下了ActionBarSherlock來好好的瞭解瞭解ActionBar的使用

把紅色框框標記的檔案匯入Eclipse裡面,我們可以先看下例子,來了解下ActionBar的一些使用情況

  • 我們新建一個Android工程,叫ViewPagerAndTab,然後指定ActionBarSherlock為ViewPagerAndTab的庫工程,右鍵工程--->Properties

通過上面的幾步我們就指定ActionBarSherlock為ViewPagerAndTab的庫工程,接下來我們就能在3.0以下使用ActionBar,我這裡使用的是ActionBar  Tab和ViewPager仿網易新聞,我們看看主要程式碼的編寫

1.先看佈局檔案,裡面一個ViewPager,非常簡單

<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:background="@android:color/white">
        <android.support.v4.view.ViewPager            android:id="@+id/viewPager"
            android:layout_width="fill_parent"            android:layout_height="wrap_content" />
   </RelativeLayout>

2.MainActivity程式碼,點選ActionBar的Tab,ViewPager切換不同的Fragment,滑動ViewPager,選中相對應的ActiionBar Tab

package com.example.viewpagerandtabdemo;import java.util.ArrayList;import java.util.List;import android.os.Bundle;import android.support.v4.app.Fragment;import android.support.v4.app.FragmentTransaction;import android.support.v4.view.ViewPager;import android.support.v4.view.ViewPager.OnPageChangeListener;import com.actionbarsherlock.app.ActionBar;import com.actionbarsherlock.app.ActionBar.Tab;import com.actionbarsherlock.app.SherlockFragmentActivity;public class MainActivity extends SherlockFragmentActivity implements ActionBar.TabListener, OnPageChangeListener/**  * 頂部Tab的title  */ private String [] mTabTitles;  /**  * ViewPager物件的引用  */ private ViewPager mViewPager;  /**  * 裝載Fragment的容器,我們的每一個介面都是一個Fragment  */ private List<Fragment> mFragmentList;  /**  * ActionBar物件的引用  */ private ActionBar mActionBar; @Override protected void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  setContentView(R.layout.activity_main);    //從資原始檔在獲取Tab的title  mTabTitles = getResources().getStringArray(R.array.tab_title);  mFragmentList =  new ArrayList<Fragment>();    mViewPager = (ViewPager) findViewById(R.id.viewPager);  //設定Adapter  mViewPager.setAdapter(new TabPagerAdapter(getSupportFragmentManager(), mFragmentList));  //設定監聽  mViewPager.setOnPageChangeListener(this);      //獲取Action例項我們使用getSupportActionBar()方法  mActionBar = getSupportActionBar();    //隱藏Title  mActionBar.setDisplayShowTitleEnabled(false);  //隱藏Home logo  mActionBar.setDisplayShowHomeEnabled(false);  //設定ActionBar的導航模式為Tab  mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);      //為ActionBar新增Tab並設定TabListener  for(int i=0; i<mTabTitles.length; i++){    ActionBar.Tab tab = mActionBar.newTab();    tab.setText(mTabTitles[i]);    tab.setTabListener(this);    mActionBar.addTab(tab, i);  }      //將Fragment加入到List中,並將Tab的title傳遞給Fragment  for(int i=0; i<mTabTitles.length; i++){   Fragment fragment = new ItemFragment();   Bundle args = new Bundle();   args.putString("arg", mTabTitles[i]);   fragment.setArguments(args);      mFragmentList.add(fragment);  }   }   @Override public void onTabSelected(Tab tab, FragmentTransaction ft) {  //點選ActionBar Tab的時候切換不同的Fragment介面  mViewPager.setCurrentItem(tab.getPosition()); } @Override public void onTabUnselected(Tab tab, FragmentTransaction ft) { } @Override public void onTabReselected(Tab tab, FragmentTransaction ft) {   }   @Override public void onPageScrollStateChanged(int arg0) {   } @Override public void onPageScrolled(int arg0, float arg1, int arg2) {   } @Override public void onPageSelected(int arg0) {  //滑動ViewPager的時候設定相對應的ActionBar Tab被選中  mActionBar.setSelectedNavigationItem(arg0); }}
我們使用ActionBarSherlock的時候不再是繼承Activity,而是繼承SherlockActivity,SherlockDialogFragment,SherlockFragmentActivity等等,我這裡用到Fragment,所以繼承SherlockFragmentActivity,我們不能隨便設定Activity的theme,以後我們要全屏顯示的時候直接設定android:theme="@android:style/Theme.Black.NoTitleBar",我們使用ActionBar就不能這樣設定了,並且不能隨便設定他的Theme,必須是Theme.Sherlock, Theme.Sherlock.Light, Theme.Sherlock.Light.DarkActionBar,或者是他們的子樣式,不然就會出java.lang.IllegalStateException異常,所以為了自定義ActionBar的Tab,我們必須修改其style

注意:我們還必須刪除ViewPagerAndTab工程libs下面的android-support-v4.jar包,因為在ActionBarSherlock已經包含android-support-v4.jar

3.ViewPager的介面卡TabPagerAdapter,因為我們用到Fragment,所以我們繼承FragmentStatePagerAdapter而不是PagerAdapter

package com.example.viewpagerandtabdemo;import java.util.List;import android.support.v4.app.Fragment;import android.support.v4.app.FragmentManager;import android.support.v4.app.FragmentStatePagerAdapter;public class TabPagerAdapter extends FragmentStatePagerAdapter private List<Fragment> list;  //建構函式 public TabPagerAdapter(FragmentManager fm, List<Fragment> list) {  super(fm);  this.list = list; } @Override public Fragment getItem(int arg0) {  return list.get(arg0); } @Override public int getCount() {  return list.size(); }}

4.ItemFragment 繼承SherlockFragment,也可以直接繼承Fragment,裡面的的佈局比較簡單,一個TextView用來顯示從Activity傳遞過來的ActionBar Tab的title

package com.example.viewpagerandtabdemo;import android.os.Bundle;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.TextView;import com.actionbarsherlock.app.SherlockFragment;public class ItemFragment extends SherlockFragment @Override public View onCreateView(LayoutInflater inflater, ViewGroup container,   Bundle savedInstanceState) {    View contextView = inflater.inflate(R.layout.fragment_item, container, false);  TextView mTextView = (TextView) contextView.findViewById(R.id.textview);    //獲取Activity傳遞過來的引數  Bundle mBundle = getArguments();  String title = mBundle.getString("arg");    mTextView.setText(title);    return contextView; } @Override public void onActivityCreated(Bundle savedInstanceState) {  super.onActivityCreated(savedInstanceState); }}
然後我們將上面的Activity的theme設定成android:theme="@style/Theme.Sherlock.Light.DarkActionBar" 執行專案看看效果,下圖一是專案的效果,圖二是網易的效果

是不是相差很大呢?人家下面的指示條是紅色的,我們做出來的是藍色的,人家選中Tab的字型顏色是紅色,我們的不變色等等,那麼我們要怎麼才能做出網易新聞的那樣子的效果,我們需要改變其style,改變如下

    <style name="Themes.ActionBarTab" parent="@style/Theme.Sherlock">        <!-- 去除ActionBar的Divider -->        <item name="actionBarDivider">@null</item>                <!-- 設定ActionBar Tab的高度 -->        <item name="actionBarSize">45dip</item>                <!-- 設定ActionBar Tab字型的樣式 -->        <item name="actionBarTabTextStyle">@style/Widget.Sherlock.ActionBar.TabText</item>                <!-- 設定ActionBar Tab的樣式,例如下面的紅色指引,Tab之間的間隙等等 -->        <item name="actionBarTabStyle">@style/Widget.Sherlock.ActionBar.TabView</item>                <!-- 設定ActionBar的樣式,這裡簡單的設定了ActionBar的背景 -->        <item name="actionBarStyle">@style/Widget.Slider.ActionBar</item>    </style>             <style name="Widget.Slider.ActionBar" parent="@style/Widget.Sherlock.ActionBar">          <item name="backgroundStacked">@drawable/base_action_bar_bg</item>    </style>    <style name="Widget.Sherlock.ActionBar.TabText" parent="android:Widget.Holo.ActionBar.TabText">        <item name="android:textColor">@drawable/selector_tabtext</item>        <item name="android:textSize">15sp</item>    </style>    <style name="Widget.Sherlock.ActionBar.TabView" parent="Widget">        <item name="android:background">@drawable/tab_indicator</item>        <item name="android:paddingLeft">8dip</item>        <item name="android:paddingRight">8dip</item>    </style> 
還有一些圖片,selector我沒有貼出來,可以去下載程式碼看看效果,改變style執行效果

很多朋友說自己在4.1上面怎麼設定style沒效果,首先這個庫是在2.X的機器上面使用ActionBar,3.0以後就是使用Andriod自帶的ActionBar,所以在3.0以上的系統使用的style為android自帶的style,所以我們要將style檔案做下修改,如下

    <style name="Themes.ActionBarTab" parent="@style/Theme.Sherlock">        <!-- 去除ActionBar的Divider -->        <item name="actionBarDivider">@null</item>  <item name="android:actionBarDivider">@null</item>                <!-- 設定ActionBar Tab的高度 -->        <item name="actionBarSize">45dip</item>  <item name="android:actionBarSize">45dip</item>                <!-- 設定ActionBar Tab字型的樣式 -->        <item name="actionBarTabTextStyle">@style/Widget.Sherlock.ActionBar.TabText</item>  <item name="android:actionBarTabTextStyle">@style/Widget.Sherlock.ActionBar.TabText</item>                <!-- 設定ActionBar Tab的樣式,例如下面的紅色指引,Tab之間的間隙等等 -->        <item name="actionBarTabStyle">@style/Widget.Sherlock.ActionBar.TabView</item>  <item name="android:actionBarTabStyle">@style/Widget.Sherlock.ActionBar.TabView</item>                <!-- 設定ActionBar的樣式,這裡簡單的設定了ActionBar的背景 -->        <item name="actionBarStyle">@style/Widget.Slider.ActionBar</item>  <item name="android:actionBarStyle">@style/Widget.Slider.ActionBar</item>    </style>             <style name="Widget.Slider.ActionBar" parent="@style/Widget.Sherlock.ActionBar">          <item name="backgroundStacked">@drawable/base_action_bar_bg</item>  <item name="android:backgroundStacked">@drawable/base_action_bar_bg</item>    </style>    <style name="Widget.Sherlock.ActionBar.TabText" parent="android:Widget.Holo.ActionBar.TabText">        <item name="android:textColor">@drawable/selector_tabtext</item>        <item name="android:textSize">15sp</item>    </style>    <style name="Widget.Sherlock.ActionBar.TabView" parent="Widget">        <item name="android:background">@drawable/tab_indicator</item>        <item name="android:paddingLeft">8dip</item>        <item name="android:paddingRight">8dip</item>    </style>