Android 5.1 Contacts源码分析:PeopleActivity

Posted ximsfei

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 5.1 Contacts源码分析:PeopleActivity相关的知识,希望对你有一定的参考价值。

1. PeopleActivity主界面UI显示

下图为联系人主界面(PeopleActivity)的类图:

PeopleActivity除了实现了类图中的四个接口,还实现了View.OnCreateContextMenuListener和View.OnClickListener,其中Activity源码中已经实现了OnCreateContextMenuListener:

public class Activity extends ContextThemeWrapper
        implements LayoutInflater.Factory2,
        Window.Callback, KeyEvent.Callback,
        OnCreateContextMenuListener, ComponentCallbacks2,
        Window.OnWindowDismissedCallback 

故子类中并不需要去实现OnCreateContextMenuListener了,只需要重写
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo)
该方法,并调用registerForContextMenu(View view)和unregisterForContextMenu(View view)即可。

跟主界面UI息息相关的类主要有
ActionBarAdapter:Adapter for the action bar at the top of the Contacts activity
ViewPagerTabs:ActionBar中添加Tab及其点击事件,联系人、收藏。
以及几个内部类:

private class TabPagerListener implements ViewPager.OnPageChangeListener 
private class TabPagerAdapter extends PagerAdapter 


上图为PeopleActivity UI显示的部分时序图
在createViewsAndFragments中:

private void createViewsAndFragments(Bundle savedState) 
    // Disable the ActionBar so that we can use a Toolbar. This needs to be called before
    // setContentView().
    getWindow().requestFeature(Window.FEATURE_NO_TITLE);

    setContentView(R.layout.people_activity);

    final FragmentManager fragmentManager = getFragmentManager();

    // Hide all tabs (the current tab will later be reshown once a tab is selected)
    final FragmentTransaction transaction = fragmentManager.beginTransaction();

    mTabTitles = new String[TabState.COUNT];
    mTabTitles[TabState.FAVORITES] = getString(R.string.favorites_tab_label);
    mTabTitles[TabState.ALL] = getString(R.string.all_contacts_tab_label);
    mTabPager = getView(R.id.tab_pager);
    mTabPagerAdapter = new TabPagerAdapter();
    mTabPager.setAdapter(mTabPagerAdapter);
    mTabPager.setOnPageChangeListener(mTabPagerListener);

    // Configure toolbar and toolbar tabs. If in landscape mode, we  configure tabs differntly.
    final Toolbar toolbar = getView(R.id.toolbar);
    setActionBar(toolbar);
    final ViewPagerTabs portraitViewPagerTabs
            = (ViewPagerTabs) findViewById(R.id.lists_pager_header);
    ViewPagerTabs landscapeViewPagerTabs = null;
    if (portraitViewPagerTabs ==  null) 
        landscapeViewPagerTabs = (ViewPagerTabs) getLayoutInflater().inflate(
                R.layout.people_activity_tabs_lands, toolbar, /* attachToRoot = */ false);
        mViewPagerTabs = landscapeViewPagerTabs;
     else 
        mViewPagerTabs = portraitViewPagerTabs;
    
    mViewPagerTabs.setViewPager(mTabPager);

    final String FAVORITE_TAG = "tab-pager-favorite";
    final String ALL_TAG = "tab-pager-all";

    // Create the fragments and add as children of the view pager.
    // The pager adapter will only change the visibility; it'll never create/destroy
    // fragments.
    // However, if it's after screen rotation, the fragments have been re-created by
    // the fragment manager, so first see if there're already the target fragments
    // existing.
    mFavoritesFragment = (ContactTileListFragment)
            fragmentManager.findFragmentByTag(FAVORITE_TAG);
    mAllFragment = (DefaultContactBrowseListFragment)
            fragmentManager.findFragmentByTag(ALL_TAG);

    if (mFavoritesFragment == null) 
        mFavoritesFragment = new ContactTileListFragment();
        mAllFragment = new DefaultContactBrowseListFragment();

        transaction.add(R.id.tab_pager, mFavoritesFragment, FAVORITE_TAG);
        transaction.add(R.id.tab_pager, mAllFragment, ALL_TAG);
    

    mFavoritesFragment.setListener(mFavoritesFragmentListener);

    mAllFragment.setOnContactListActionListener(new ContactBrowserActionListener());

    // Hide all fragments for now.  We adjust visibility when we get onSelectedTabChanged()
    // from ActionBarAdapter.
    transaction.hide(mFavoritesFragment);
    transaction.hide(mAllFragment);

    transaction.commitAllowingStateLoss();
    fragmentManager.executePendingTransactions();

    // Setting Properties after fragment is created
    mFavoritesFragment.setDisplayType(DisplayType.STREQUENT);

    mActionBarAdapter = new ActionBarAdapter(this, this, getActionBar(),
            portraitViewPagerTabs, landscapeViewPagerTabs, toolbar);
    mActionBarAdapter.initialize(savedState, mRequest);

    // Add shadow under toolbar
    ViewUtil.addRectangularOutlineProvider(findViewById(R.id.toolbar_parent), getResources());

    // Configure action button
    final View floatingActionButtonContainer = findViewById(
            R.id.floating_action_button_container);
    ViewUtil.setupFloatingActionButton(floatingActionButtonContainer, getResources());
    final ImageButton floatingActionButton = (ImageButton) findViewById(R.id.floating_action_button);
    floatingActionButton.setOnClickListener(this);

    invalidateOptionsMenuIfNeeded();

从Activity.java源码中可以看到:

public void setActionBar(@Nullable Toolbar toolbar) 
    if (getActionBar() instanceof WindowDecorActionBar) 
        throw new IllegalStateException("This Activity already has an action bar supplied " +
                "by the window decor. Do not request Window.FEATURE_ACTION_BAR and set " +
                "android:windowActionBar to false in your theme to use a Toolbar instead.");
    
    ToolbarActionBar tbab = new ToolbarActionBar(toolbar, getTitle(), this);
    mActionBar = tbab;
    mWindow.setCallback(tbab.getWrappedWindowCallback());
    mActionBar.invalidateOptionsMenu();

public void setContentView(View view, ViewGroup.LayoutParams params) 
    getWindow().setContentView(view, params);
    initWindowDecorActionBar();

private void initWindowDecorActionBar() 
    Window window = getWindow();

    // Initializing the window decor can change window feature flags.
    // Make sure that we have the correct set before performing the test below.
    window.getDecorView();

    if (isChild() || !window.hasFeature(Window.FEATURE_ACTION_BAR) || mActionBar != null) 
        return;
    

    mActionBar = new WindowDecorActionBar(this);
    mActionBar.setDefaultDisplayHomeAsUpEnabled(mEnableDefaultActionBarUp);

    mWindow.setDefaultIcon(mActivityInfo.getIconResource());
    mWindow.setDefaultLogo(mActivityInfo.getLogoResource());

我们想要在Activity中使用ToolBar,必须调用getWindow().requestFeature(Window.FEATURE_NO_TITLE);去掉默认的ActionBar,否则会抛出异常,并且在setContentView()中会初始化系统的ActionBar,所以想要去掉默认ActionBar,该方法必须在setContentView()之前调用。

mTabTitles = new String[TabState.COUNT];
mTabTitles[TabState.FAVORITES] = getString(R.string.favorites_tab_label);
mTabTitles[TabState.ALL] = getString(R.string.all_contacts_tab_label);

PeopleActivity的ViewPager中有两个页面,一个是收藏页面(ContactTileListFragment),另一个是所有联系人页面(DefaultContactBrowseListFragment)。
类似的我从Android4.4源码中提取过一个Demo:
在Android中使用ViewPager实现左右滑动页面
PeopleActivity Menu:

public boolean onCreateOptionsMenu(Menu menu) 
    if (!areContactsAvailable()) 
        // If contacts aren't available, hide all menu items.
        return false;
    
    super.onCreateOptionsMenu(menu);

    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.people_options, menu);

    return true;

在onPrepareOptionsMenu(Menu menu)中会根据是否为搜索模式(isSearchMode),当前在那个页面中(mActionBarAdapter.getCurrentTab())决定菜单的显示情况。

以上是关于Android 5.1 Contacts源码分析:PeopleActivity的主要内容,如果未能解决你的问题,请参考以下文章

Android 5.1 Contacts源码分析:Contacts模块ListView Adapter结构

Android 5.1 Contacts源码分析:Contacts模块Fargment结构

Android 5.1 Contacts源码分析:PeopleActivity

Android 5.1系统源码Wifi模块中wifiSettings源码分析

Orchard源码分析(5.1):Host初始化(DefaultOrchardHost.Initialize方法)

Android 5.1 Settings源代码简要分析