最近由Android2.3切换到Android4.0的开发,一下子居然有点不适应,Android4.0新增了一些功能模块如ActionBar,Fragment等其实在Android3.0就有了,但一直没有做过平板上的开发,所以对这些模块非常陌生,一下子感觉Android4.0的开发难度甚大,经过十来天的努力,终于略微有所悟,在看通讯录的时候,感觉如果将其效果模仿出来岂不是初步达到掌握这些模块。
先看图,再列举出代码:
按住左右滑动时会自动切换。
源代码下载:http://download.csdn.net/detail/hjj0212/5023509
主要代码如下:
package com.example.testtabactionbar;
import android.net.Uri;
import android.os.Bundle;
import android.os.Parcelable;
import android.provider.ContactsContract.Contacts;
import android.app.ActionBar;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.app.ListFragment;
import android.app.ActionBar.Tab;
import android.app.LoaderManager.LoaderCallbacks;
import android.content.CursorLoader;
import android.content.Loader;
import android.database.Cursor;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.text.TextUtils;
import android.util.Log;
import android.view.ContextMenu;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.ContextMenu.ContextMenuInfo;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.widget.Toast;
import android.widget.SearchView.OnQueryTextListener;
public class MainActivity extends Activity {
private ActionBar mActionBar;
private static final TabState DEFAULT_TAB = TabState.GROUPS;
private TabState mCurrentTab = DEFAULT_TAB;
private final MyTabListener mTabListener = new MyTabListener();
private ArraListFragment mArrayFragment;
private CursorLoaderFragment mCursorFragment;
private ContextMenuFragment mContextMenuFragment;
private ViewPager mTabPager;
private TabPagerAdapter mTabPagerAdapter;
private final TabPagerListener mTabPagerListener = new TabPagerListener();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.tab_view_pager);
initActionBar();
createViewAndFragment();
}
private void createViewAndFragment(){
final FragmentManager fragmentManager = getFragmentManager();
final FragmentTransaction transaction = fragmentManager.beginTransaction();
mTabPager = getView(R.id.tab_pager);
mTabPagerAdapter = new TabPagerAdapter();
mTabPager.setAdapter(mTabPagerAdapter);
mTabPager.setOnPageChangeListener(mTabPagerListener);
final String FAVORITE_TAG = "tab-pager-favorite";
final String ALL_TAG = "tab-pager-all";
final String GROUPS_TAG = "tab-pager-groups";
// 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.
mContextMenuFragment = (ContextMenuFragment) fragmentManager
.findFragmentByTag(FAVORITE_TAG);
mArrayFragment = (ArraListFragment) fragmentManager
.findFragmentByTag(ALL_TAG);
mCursorFragment = (CursorLoaderFragment) fragmentManager
.findFragmentByTag(GROUPS_TAG);
if (mContextMenuFragment == null) {
Log.e("HJJ", "ContextMenuFragmentd == null");
mContextMenuFragment = new ContextMenuFragment();
mArrayFragment = new ArraListFragment();
mCursorFragment = new CursorLoaderFragment();
transaction.add(R.id.tab_pager, mContextMenuFragment, FAVORITE_TAG);
transaction.add(R.id.tab_pager, mArrayFragment, ALL_TAG);
transaction.add(R.id.tab_pager, mCursorFragment, GROUPS_TAG);
}
// Hide all fragments for now. We adjust visibility when we get
// onSelectedTabChanged()
// from ActionBarAdapter.
transaction.hide(mContextMenuFragment);
transaction.hide(mArrayFragment);
transaction.hide(mCursorFragment);
transaction.commitAllowingStateLoss();
fragmentManager.executePendingTransactions();
}
private class TabPagerListener implements ViewPager.OnPageChangeListener {
@Override
public void onPageScrollStateChanged(int state) {
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
// Make sure not in the search mode, in which case position != TabState.ordinal().
TabState selectedTab = TabState.fromInt(position);
setCurrentTab(selectedTab, false);
invalidateOptionsMenu();
}
}
private void initActionBar(){
mActionBar = getActionBar();
mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// 去掉默认标题栏
mActionBar.setDisplayShowHomeEnabled(false);
mActionBar.setDisplayShowTitleEnabled(false);
// Set up tabs
addTab(TabState.GROUPS, R.drawable.ic_tab_groups);
addTab(TabState.ALL, R.drawable.ic_tab_all);
addTab(TabState.FAVORITES, R.drawable.ic_tab_starred);
}
private class TabPagerAdapter extends PagerAdapter {
private final FragmentManager mFragmentManager;
private FragmentTransaction mCurTransaction = null;
private boolean mTabPagerAdapterSearchMode;
private Fragment mCurrentPrimaryItem;
public TabPagerAdapter() {
mFragmentManager = getFragmentManager();
}
@Override
public int getCount() {
return mTabPagerAdapterSearchMode ? 1 : TabState.values().length;
}
/** Gets called when the number of items changes. */
@Override
public int getItemPosition(Object object) {
if (mTabPagerAdapterSearchMode) {
if (object == mArrayFragment) {
return 0; // Only 1 page in search mode
}
} else {
if (object == mContextMenuFragment) {
return TabState.FAVORITES.ordinal();
}
if (object == mArrayFragment) {
return TabState.ALL.ordinal();
}
if (object == mCursorFragment) {
return TabState.GROUPS.ordinal();
}
}
return POSITION_NONE;
}
@Override
public void startUpdate(View container) {
}
private Fragment getFragment(int position) {
if (position == TabState.FAVORITES.ordinal()) {
return mContextMenuFragment;
} else if (position == TabState.ALL.ordinal()) {
return mArrayFragment;
} else if (position == TabState.GROUPS.ordinal()) {
return mCursorFragment;
}
throw new IllegalArgumentException("position: " + position);
}
@Override
public Object instantiateItem(View container, int position) {
if (mCurTransaction == null) {
mCurTransaction = mFragmentManager.beginTransaction();
}
Fragment f = getFragment(position);
mCurTransaction.show(f);
// Non primary pages are not visible.
//f.setUserVisibleHint(f == mCurrentPrimaryItem);
return f;
}
@Override
public void destroyItem(View container, int position, Object object) {
if (mCurTransaction == null) {
mCurTransaction = mFragmentManager.beginTransaction();
}
mCurTransaction.hide((Fragment) object);
}
@Override
public void finishUpdate(View container) {
if (mCurTransaction != null) {
mCurTransaction.commitAllowingStateLoss();
mCurTransaction = null;
mFragmentManager.executePendingTransactions();
}
}
@Override
public boolean isViewFromObject(View view, Object object) {
return ((Fragment) object).getView() == view;
}
@Override
public void setPrimaryItem(View container, int position, Object object) {
Fragment fragment = (Fragment) object;
if (mCurrentPrimaryItem != fragment) {
if (mCurrentPrimaryItem != null) {
//mCurrentPrimaryItem.setUserVisibleHint(false);
}
if (fragment != null) {
//fragment.setUserVisibleHint(true);
}
mCurrentPrimaryItem = fragment;
}
}
@Override
public Parcelable saveState() {
return null;
}
@Override
public void restoreState(Parcelable state, ClassLoader loader) {
}
}
@SuppressWarnings("unchecked")
public <T extends View> T getView(int id) {
T result = (T)findViewById(id);
if (result == null) {
throw new IllegalArgumentException("view 0x" + Integer.toHexString(id)
+ " doesn't exist");
}
return result;
}
protected static void showFragment(FragmentTransaction ft, Fragment f) {
if ((f != null) && f.isHidden()) ft.show(f);
}
protected static void hideFragment(FragmentTransaction ft, Fragment f) {
if ((f != null) && !f.isHidden()) ft.hide(f);
}
private void addTab(TabState tabState, int icon) {
final Tab tab = mActionBar.newTab();
tab.setTag(tabState);
tab.setTabListener(mTabListener);
tab.setIcon(icon);
mActionBar.addTab(tab);
}
public enum TabState {
GROUPS, ALL, FAVORITES;
public static TabState fromInt(int value) {
if (GROUPS.ordinal() == value) {
return GROUPS;
}
if (ALL.ordinal() == value) {
return ALL;
}
if (FAVORITES.ordinal() == value) {
return FAVORITES;
}
throw new IllegalArgumentException("Invalid value: " + value);
}
}
private class MyTabListener implements ActionBar.TabListener {
/**
* If true, it won't call {@link #setCurrentTab} in {@link #onTabSelected}.
* This flag is used when we want to programmatically update the current tab without
* {@link #onTabSelected} getting called.
*/
public boolean mIgnoreTabSelected;
@Override public void onTabReselected(Tab tab, FragmentTransaction ft) { }
@Override public void onTabUnselected(Tab tab, FragmentTransaction ft) { }
@Override public void onTabSelected(Tab tab, FragmentTransaction ft) {
Log.e("HJJ", "onTabSelected..tag:" + tab.getTag());
if (!mIgnoreTabSelected) {
setCurrentTab((TabState)tab.getTag());
}
}
}
/**
* Change the current tab, and notify the listener.
*/
public void setCurrentTab(TabState tab) {
setCurrentTab(tab, true);
}
/**
* Change the current tab
*/
public void setCurrentTab(TabState tab, boolean notifyListener) {
if (tab == null) throw new NullPointerException();
//实际上按照Contacts中的设计,这个是应该有效的,但在此模拟程序中,它会出现问题,因此暂时将此段去掉
// if (tab == mCurrentTab) {
// return;
// }
mCurrentTab = tab;
int index = mCurrentTab.ordinal();
if ((mActionBar.getNavigationMode() == ActionBar.NAVIGATION_MODE_TABS)
&& (index != mActionBar.getSelectedNavigationIndex())) {
mActionBar.setSelectedNavigationItem(index);
}
if (notifyListener) onSelectedTabChanged(tab);
}
private void onSelectedTabChanged(TabState tab){
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction ft = fragmentManager.beginTransaction();
int tabIndex = tab.ordinal();
Log.e("HJJ", "tabIndex:" + tabIndex);
switch (tab) {
case FAVORITES:
if(mContextMenuFragment!=null){
mTabPager.setCurrentItem(tabIndex, false);
}
showFragment(ft, mContextMenuFragment);
hideFragment(ft, mArrayFragment);
hideFragment(ft, mCursorFragment);
break;
case ALL:
if(mArrayFragment!=null){
mTabPager.setCurrentItem(tabIndex, false);
}
hideFragment(ft, mContextMenuFragment);
hideFragment(ft, mCursorFragment);
showFragment(ft, mArrayFragment);
break;
case GROUPS:
if(mCursorFragment!=null){
mTabPager.setCurrentItem(tabIndex, false);
}
hideFragment(ft, mContextMenuFragment);
hideFragment(ft, mArrayFragment);
showFragment(ft, mCursorFragment);
break;
}
if (!ft.isEmpty()) {
Log.e("HJJ", "not ft isEmpty");
ft.commitAllowingStateLoss();
fragmentManager.executePendingTransactions();
// When switching tabs, we need to invalidate options menu, but executing a
// fragment transaction does it implicitly. We don't have to call invalidateOptionsMenu
// manually.
}
}
public static class ArraListFragment extends ListFragment{
@Override
public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);
String [] array = new String[]{"C", "C++", "Java"};
setListAdapter(new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_list_item_1, array));
}
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
// TODO Auto-generated method stub
super.onListItemClick(l, v, position, id);
}
}
public static class CursorLoaderFragment extends ListFragment implements
OnQueryTextListener, LoaderCallbacks<Cursor> {
SimpleCursorAdapter mAdapter;
String mCurFilter;
final String[] CONTACTS_SUMMARY_PROJECTION = new String[] {
Contacts._ID, Contacts.DISPLAY_NAME, Contacts.CONTACT_STATUS,
Contacts.CONTACT_PRESENCE, Contacts.PHOTO_ID,
Contacts.LOOKUP_KEY, };
@Override
public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);
setEmptyText("No phone numbers");
setHasOptionsMenu(true);
mAdapter = new SimpleCursorAdapter(getActivity(),
android.R.layout.simple_list_item_2, null, new String[] {
Contacts.DISPLAY_NAME, Contacts.CONTACT_STATUS },
new int[] { android.R.id.text1, android.R.id.text2 }, 0);
setListAdapter(mAdapter);
setListShown(false);
getLoaderManager().initLoader(0, null, this);
}
// @Override
// public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// // TODO Auto-generated method stub
// MenuItem item = menu.add("Search");
// item.setIcon(android.R.drawable.ic_menu_search);
// item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM
// | MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);
// SearchView sv = new SearchView(getActivity());
// sv.setOnQueryTextListener(this);
// item.setActionView(sv);
// }
@Override
public boolean onQueryTextChange(String newText) {
// TODO Auto-generated method stub
String newFilter = !TextUtils.isEmpty(newText) ? newText : null;
if (mCurFilter == null && newFilter == null) {
return true;
}
if (mCurFilter != null && mCurFilter.equals(newFilter)) {
return true;
}
mCurFilter = newFilter;
getLoaderManager().restartLoader(0, null, this);
return true;
}
@Override
public boolean onQueryTextSubmit(String query) {
// TODO Auto-generated method stub
return true;
}
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
// TODO Auto-generated method stub
super.onListItemClick(l, v, position, id);
Cursor c = (Cursor) mAdapter.getItem(position);
String name = c.getString(0);
Toast.makeText(getActivity(), "name:" + name, Toast.LENGTH_SHORT)
.show();
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
// TODO Auto-generated method stub
Uri baseUri;
if (mCurFilter != null) {
baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI,
Uri.encode(mCurFilter));
} else {
baseUri = Contacts.CONTENT_URI;
}
String select = "((" + Contacts.DISPLAY_NAME + " NOTNULL) AND ("
+ Contacts.HAS_PHONE_NUMBER + "=1) AND ("
+ Contacts.DISPLAY_NAME + " != '' ))";
return new CursorLoader(getActivity(), baseUri,
CONTACTS_SUMMARY_PROJECTION, select, null,
Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC");
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
// TODO Auto-generated method stub
mAdapter.swapCursor(data);
if (isResumed()) {
setListShown(true);
} else {
setListShownNoAnimation(true);
}
}
@Override
public void onLoaderReset(Loader<Cursor> arg0) {
// TODO Auto-generated method stub
mAdapter.swapCursor(null);
}
}
public static class ContextMenuFragment extends Fragment{
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
View root = inflater.inflate(R.layout.fragment_context_menu, container, false);
registerForContextMenu(root.findViewById(R.id.long_press));
return root;
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
// TODO Auto-generated method stub
super.onCreateContextMenu(menu, v, menuInfo);
menu.add(Menu.NONE, R.id.a_item, Menu.NONE, "Menu A");
menu.add(Menu.NONE, R.id.b_item, Menu.NONE, "Menu B");
}
@Override
public boolean onContextItemSelected(MenuItem item) {
// TODO Auto-generated method stub
switch (item.getItemId()) {
case R.id.a_item:
Toast.makeText(getActivity(), "a_item...", Toast.LENGTH_SHORT).show();
break;
case R.id.b_item:
Toast.makeText(getActivity(), "b_item...", Toast.LENGTH_SHORT).show();
break;
default:
break;
}
return super.onContextItemSelected(item);
}
}
}