Android2.x中使用Fragment的調查
- Fragment介紹
Fragment是在android3.0中引入的,其功能和Activity基本相似,有自己的回調和生命週期,對於Fragment的理解我們可以解釋爲碎片或片段,這一點和DOM中的片段可以類比。
關於設計哲學、生命週期、事務管理、與Activity通信、ActionBar的使用,官方的文檔給出了比較詳細的說明,這裏不做贅述了。
http://developer.android.com/guide/components/fragments.html
- Fragment應用場景
根據目前調查的情況這裏列出幾點
- 避免太多的Activity切換損傷系統的性能,Fragment較Activity更輕量化
- 爲應用程序提供統一的UI(以更低的成本統一2.x到最新版本的UI)
- 爲大屏設備提供更好的用戶體驗(例如新聞閱讀,標題列表和內容同時展現)
- 在android2.x中使用Fragment
- Google的解決方案:
Google爲Android2.x使用Fragment提供了支持,並提供了官方的類庫,可以從SDK Manager中下載,SDK Manager中的位置爲Extras > Android Support Library,下載後存放於android-sdks\extras\android\support\v4中。
一般情況下如果只使用Fragment的話,那麼該庫就夠用了,但是如果我們想用ActionBar的話,這個支持類庫的功能就不夠了。
- Actionbarsherlock的解決方案:
該方案是使用actionbarsherlock開源類庫,該方案提供了Fragment和ActionBar的支持,其本身的Fragment支持採用的是Google解決方案的類庫。具體的使用類似於GreenDroid,需要使用該方案的應用程序需要導入actionbarsherlock項目。
- 項目實踐:
本次調查因爲涉及到ActionBar,所以主要的輸出內容以actionbarsherlock作爲基礎。
- 代碼獲取:
從actionbarsherlock官方網站下載actionbarsherlock項目及demo,
地址:https://github.com/JakeWharton/ActionBarSherlock/zipball/4.1.0
- Eclipse中導入actionbarsherlock項目:
這裏有幾點需要注意:
1.因爲ADT版本差異,官方網站提供的導入步驟在較高版本的ADT中導入失敗,這裏採用的方法新建Android項目,然後將actionbarsherlock的library目錄作爲項目源碼拷貝到新建項目的根目錄下面,
2.actionbarsherlock中有的內容不好打包,只能通過項目引用的方式來工作。
3.編譯環境的AndroidSDK版本必須在3.2以後,即project.properties中的target必須大於等於13,但工作換進可以是2.x。
- 項目引用:
我們的項目如果需要引用該庫,需要這樣引入:
右鍵 > properties > Android > library > Add > actionbarsherlock項目
而不是這樣:右鍵 > Build Path > Config Build Path > Project > Add > actionbarsherlock項目
- 使用:
ActionBar使用:
- public class MainActivity extends BaseActivity{
- private final static String TAB1 = "home";
- private final static String TAB2 = "live";
- private final static String TAB3 = "column";
- private final static String TAB4 = "news";
- private final static String TAB5 = "setting";
- int mStackLevel = 1;
- HomeFragment homeFragment = new HomeFragment();
- LiveFragment liveFragment = new LiveFragment();
- ColumnFragment columnFragment = new ColumnFragment();
- NewsFragment newsFragment = new NewsFragment();
- SettingFragment settingFragment = new SettingFragment();
- ……………………………
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.fragment_stack);
- final ActionBar bar = getSupportActionBar() ;
- bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
- bar.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_TITLE);
- bar.addTab(bar.newTab().setIcon(R.drawable.tab_icon_home_bg)
- .setText(R.string.tab_label_home)
- .setTabListener(new TabListener(homeFragment,TAB1)));
- bar.addTab(bar.newTab().setIcon(R.drawable.tab_icon_live_bg)
- .setText(R.string.tab_label_live)
- .setTabListener(new TabListener(liveFragment,TAB2)));
- bar.addTab(bar.newTab().setIcon(R.drawable.tab_icon_column_bg)
- .setText(R.string.tab_label_column)
- .setTabListener(new TabListener(columnFragment,TAB3)));
- bar.addTab(bar.newTab().setIcon(R.drawable.tab_icon_news_bg)
- .setText(R.string.tab_label_news)
- .setTabListener(new TabListener(newsFragment,TAB4)));
- bar.addTab(bar.newTab().setIcon(R.drawable.tab_icon_setting_bg)
- .setText(R.string.tab_label_setting)
- .setTabListener(new TabListener(settingFragment,TAB5)));
- if (savedInstanceState != null) {
- bar.setSelectedNavigationItem(savedInstanceState.getInt("tab", 0));
- }
- }
- ……………………
- }
說明:
- 這裏的ActionBar引用的是com.actionbarsherlock.app.ActionBar;
- 獲取ActionBar需要使用getSupportActionBar()方法
- 這裏的Fragment繼承自android.support.v4.app.Fragment;
- bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);表示使用Tab 頁形式展示。
- bar.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_TITLE);顯示標題欄。
Fragment使用:
- public class SettingFragment extends BaseFragment {
- int mNum;
- private Button share;
- private Button clear;
- private Button contact;
- /**
- * 該方法用於Fragment默認構造
- * @return
- */
- public SettingFragment(){
- }
- public SettingFragment(int num){
- this.mNum = num;
- }
- /**
- * When creating, retrieve this instance's number from its arguments.
- */
- @Override
- public void onCreate(Bundle savedInstanceState) {
- Utils.log("onCreate");
- super.onCreate(savedInstanceState);
- mNum = getArguments() != null ? getArguments().getInt("num") : 5;
- }
- /**
- * The Fragment's UI is just a simple text view showing its instance number.
- */
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- Utils.log("onCreateView");
- View v = inflater.inflate(R.layout.setting, container, false);
- getViews(v);
- setListener();
- return v;
- }
- private void getViews(View container){
- share = (Button)container.findViewById(R.id.setting_share_button);
- clear = (Button)container.findViewById(R.id.setting_clear_button);
- contact = (Button)container.findViewById(R.id.setting_contact_button);
- }
- private void setListener(){
- share.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- startActivity(new Intent(getActivity(),ShareActivity.class));
- }
- });
- clear.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- startActivity(new Intent(getActivity(),ClearActivity.class));
- }
- });
- contact.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- startActivity(new Intent(getActivity(),ContactActivity.class));
- }
- });
- }
- }
說明:
fragment第一次繪製它的用戶界面的時候, 系統會調用此方法。爲了繪製fragment的UI,此方法必須返回一個View, 這個view是你的fragment佈局的根view。如果fragment不提供UI, 可以返回null。
- 建議:
根據目前調查的情況,這裏給出幾點建議
- ActionBar的位置位於標題欄位置,而項目中的Tab標籤位於屏幕底部,這裏使用ActionBar可能會給用戶點擊帶來一點小麻煩,可以考慮用戶滑動屏幕自動切換Tab頁。
- Fragment的主題以黑色爲主,直接替換項目可能會有些地方色彩不協調,細節部分可能需要再設計一下
- Fragment框架需要引入主題,該主題會包含一個標題欄,替換之前的自定義標題欄還需要調查(這裏是一個例子,更多的類容再向Fragment靠攏的開發中可能還會遇到)。
- 結論:
項目向Fragment框架靠攏整理方案在技術上是可行的,並能因此提高系統的性能,但是在部分UI和用戶體驗上可能與之前的預期存在一點小差異,可能需要小修改。