<?xml version="1.0" encoding="utf-8"?> <TabHost xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/tabhost" android:layout_width="match_parent" android:layout_height="match_parent" > <LinearLayout android:id="@+id/setting" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/maintab_toolbar_bg" > <ListView android:id="@+id/list" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/transparent" android:cacheColorHint="@android:color/transparent" android:dividerHeight="1dp"/> </LinearLayout> <LinearLayout android:id="@+id/main" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <RelativeLayout android:layout_width="match_parent" android:layout_height="45dp" android:background="@drawable/app_title_bar" android:gravity="center_vertical" android:orientation="horizontal" > <TextView android:layout_width="wrap_content" android:layout_height="fill_parent" android:layout_marginLeft="24dp" android:gravity="center_vertical" android:text="@string/app_name" android:textColor="@android:color/white" android:textSize="22dp" /> <ImageButton android:id="@+id/btn_settings" android:layout_width="48dip" android:layout_height="match_parent" android:layout_alignParentRight="true" android:background="@android:color/transparent" android:src="@drawable/action_settings" /> <ImageView android:layout_width="1dp" android:layout_height="match_parent" android:layout_toLeftOf="@id/btn_settings" android:background="@drawable/app_title_bar_line" /> </RelativeLayout> <FrameLayout android:id="@android:id/tabcontent" android:layout_width="0dp" android:layout_height="0dp" android:layout_weight="0" > </FrameLayout> <FrameLayout android:id="@+id/containertabcontent" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" > </FrameLayout> <TabWidget android:id="@android:id/tabs" android:layout_width="match_parent" android:layout_height="55dip" android:layout_weight="0" android:orientation="horizontal" > </TabWidget> </LinearLayout> </TabHost>
private final static int TRANSLATE_ANIMATION_WIDTH = 150; private final static int ANIMATION_DURATION_FAST = 450; private final static int ANIMATION_DURATION_SLOW = 350; private final static int MOVE_DISTANCE = 50; private TabHost mTabHost; private TabManager mTabManager; private LinearLayout mSettingLinearLayout; private LinearLayout mMainLinearLayout; // 屏幕宽度 private int mWidth; private float mPositionX; // 滑动状态 private boolean mSlided = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ActivityUtils.requestNotTitleBar(this); setContentView(R.layout.fragment_tabs); mWidth = getResources().getDisplayMetrics().widthPixels; // 继承tabactivity.getTabHost()不需要setup() mTabHost = (TabHost) findViewById(android.R.id.tabhost); mTabHost.setup(); mTabManager = new TabManager(this, mTabHost, R.id.containertabcontent); RelativeLayout app = (RelativeLayout) getLayoutInflater().inflate( R.layout.app_tab_layout, null); mTabManager.addTab(mTabHost.newTabSpec("Apps").setIndicator(app), AppsFragment.class, null); RelativeLayout contacts = (RelativeLayout) getLayoutInflater().inflate( R.layout.contacts_tab_layout, null); mTabManager.addTab(mTabHost.newTabSpec("Contact") .setIndicator(contacts), ContactsFragment.class, null); RelativeLayout message = (RelativeLayout) getLayoutInflater().inflate( R.layout.message_tab_layout, null); mTabManager.addTab( mTabHost.newTabSpec("Message").setIndicator(message), MessageFragment.class, null); mSettingLinearLayout = (LinearLayout) findViewById(R.id.setting); mMainLinearLayout = (LinearLayout) findViewById(R.id.main); mMainLinearLayout.setOnTouchListener(mOnTouchListener); slideIn(); ListView listView = (ListView) findViewById(R.id.list); listView.setOnTouchListener(mOnTouchListener); findViewById(R.id.btn_settings).setOnClickListener(mOnClickListener); if (savedInstanceState != null) { mTabHost.setCurrentTabByTag(savedInstanceState.getString("tag")); } // 初始化listview final Resources res = getResources(); String[] mTitles = res.getStringArray(R.array.setting_items); ArrayAdapter<String> mAdapter = new ArrayAdapter<String>(this, R.layout.fragment_setting_item, R.id.item, mTitles); listView.setAdapter(mAdapter); } // 点击按钮 private OnClickListener mOnClickListener = new OnClickListener() { @Override public void onClick(View v) { switch (v.getId()) { case R.id.btn_settings : if (mSlided) { slideIn(); } else { slideOut(); } break; } } }; // 滑动 private OnTouchListener mOnTouchListener = new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (v.getId() == R.id.main) { int action = event.getAction(); switch (action) { case MotionEvent.ACTION_DOWN : mPositionX = event.getX(); break; case MotionEvent.ACTION_MOVE : final float currentX = event.getX(); // 向左边滑动 if (currentX - mPositionX <= -MOVE_DISTANCE && !mSlided) { slideOut(); } else if (currentX - mPositionX >= MOVE_DISTANCE && mSlided) { slideIn(); } break; } return true; } return false; } }; /** * 滑出侧边栏 */ private void slideOut() { TranslateAnimation translate = new TranslateAnimation(mWidth, TRANSLATE_ANIMATION_WIDTH, 0, 0); translate.setDuration(ANIMATION_DURATION_SLOW); translate.setFillAfter(true); mSettingLinearLayout.startAnimation(translate); mSettingLinearLayout.getAnimation().setAnimationListener( new Animation.AnimationListener() { @Override public void onAnimationStart(Animation anim) { } @Override public void onAnimationRepeat(Animation animation) { } @Override public void onAnimationEnd(Animation anima) { TranslateAnimation animation = new TranslateAnimation( 0, TRANSLATE_ANIMATION_WIDTH - mWidth, 0, 0); animation.setDuration(ANIMATION_DURATION_FAST); animation.setFillAfter(true); mMainLinearLayout.startAnimation(animation); mSlided = true; } }); } /** * 滑进侧边栏 */ private void slideIn() { TranslateAnimation translate = new TranslateAnimation(TRANSLATE_ANIMATION_WIDTH, mWidth, 0, 0); translate.setDuration(ANIMATION_DURATION_FAST); // 动画完成时停在结束位置 translate.setFillAfter(true); mSettingLinearLayout.startAnimation(translate); mSettingLinearLayout.getAnimation().setAnimationListener( new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { TranslateAnimation mainAnimation = new TranslateAnimation( -mWidth + TRANSLATE_ANIMATION_WIDTH, 0, 0, 0); mainAnimation.setDuration(ANIMATION_DURATION_SLOW); mainAnimation.setFillAfter(true); mMainLinearLayout.startAnimation(mainAnimation); } @Override public void onAnimationRepeat(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { mSlided = false; } }); } @Override public boolean onContextItemSelected(MenuItem item) { if (mSlided) { slideIn(); } else { slideOut(); } return true; } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK && mSlided) { slideIn(); return true; } return super.onKeyDown(keyCode, event); } /** * 销毁之前 */ @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putString("tag", mTabHost.getCurrentTabTag()); } public static class TabManager implements TabHost.OnTabChangeListener { private final FragmentTabActivity mActivity; // 保存tab private final Map<String, TabInfo> mTabs = new HashMap<String, FragmentTabActivity.TabManager.TabInfo>(); private final TabHost mTabHost; private final int mContainerID; private TabInfo mLastTab; public TabManager(FragmentTabActivity activity, TabHost tabHost, int containerID) { mActivity = activity; mTabHost = tabHost; mContainerID = containerID; mTabHost.setOnTabChangedListener(this); } static final class TabInfo { private final String tag; private final Class<?> clss; private final Bundle args; private Fragment fragment; TabInfo(String _tag, Class<?> _clss, Bundle _args) { tag = _tag; clss = _clss; args = _args; } } static class TabFactory implements TabHost.TabContentFactory { private Context mContext; TabFactory(Context context) { mContext = context; } @Override public View createTabContent(String tag) { View v = new View(mContext); v.setMinimumHeight(0); v.setMinimumWidth(0); return v; } } // 加入tab public void addTab(TabHost.TabSpec tabSpec, Class<?> clss, Bundle args) { tabSpec.setContent(new TabFactory(mActivity)); String tag = tabSpec.getTag(); TabInfo info = new TabInfo(tag, clss, args); final FragmentManager fm = mActivity.getSupportFragmentManager(); info.fragment = fm.findFragmentByTag(tag); // isDetached分离状态 if (info.fragment != null && !info.fragment.isDetached()) { FragmentTransaction ft = fm.beginTransaction(); ft.detach(info.fragment); ft.commit(); } mTabs.put(tag, info); mTabHost.addTab(tabSpec); } @Override public void onTabChanged(String tabId) { TabInfo newTab = mTabs.get(tabId); if (mLastTab != newTab) { FragmentManager fragmentManager = mActivity .getSupportFragmentManager(); FragmentTransaction fragmentTransaction = fragmentManager .beginTransaction(); // 脱离之前的tab if (mLastTab != null && mLastTab.fragment != null) { fragmentTransaction.detach(mLastTab.fragment); } if (newTab != null) { if (newTab.fragment == null) { newTab.fragment = Fragment.instantiate(mActivity, newTab.clss.getName(), newTab.args); fragmentTransaction.add(mContainerID, newTab.fragment, newTab.tag); } else { // 激活 fragmentTransaction.attach(newTab.fragment); } } mLastTab = newTab; fragmentTransaction.commit(); // 会在进程的主线程中,用异步的方式来执行,如果想要立即执行这个等待中的操作,就要调用这个方法 // 所有的回调和相关的行为都会在这个调用中被执行完成,因此要仔细确认这个方法的调用位置。 fragmentManager.executePendingTransactions(); } } }
先看看内部类TabManager,封装了TabHost的addTab动作,其中addTabaddTab(TabHost.TabSpec tabSpec, Class<?> clss, Bundle args)方法第一个参数是tabhost.tabspec,第二个参数是fragment,第三个是你要从FragmentTabActivity里传递到相关fragment的参数。
// isDetached分离状态 if (info.fragment != null && !info.fragment.isDetached()) { FragmentTransaction ft = fm.beginTransaction(); ft.detach(info.fragment); ft.commit(); }
@Override public void onTabChanged(String tabId) { TabInfo newTab = mTabs.get(tabId); if (mLastTab != newTab) { FragmentManager fragmentManager = mActivity .getSupportFragmentManager(); FragmentTransaction fragmentTransaction = fragmentManager .beginTransaction(); // 脱离之前的tab if (mLastTab != null && mLastTab.fragment != null) { fragmentTransaction.detach(mLastTab.fragment); } if (newTab != null) { if (newTab.fragment == null) { newTab.fragment = Fragment.instantiate(mActivity, newTab.clss.getName(), newTab.args); fragmentTransaction.add(mContainerID, newTab.fragment, newTab.tag); } else { // 激活 fragmentTransaction.attach(newTab.fragment); } } mLastTab = newTab; fragmentTransaction.commit(); // 会在进程的主线程中,用异步的方式来执行,如果想要立即执行这个等待中的操作,就要调用这个方法 // 所有的回调和相关的行为都会在这个调用中被执行完成,因此要仔细确认这个方法的调用位置。 fragmentManager.executePendingTransactions(); } }
mTabManager = new TabManager(this, mTabHost, R.id.containertabcontent); RelativeLayout app = (RelativeLayout) getLayoutInflater().inflate( R.layout.app_tab_layout, null); mTabManager.addTab(mTabHost.newTabSpec("Apps").setIndicator(app), AppsFragment.class, null); RelativeLayout contacts = (RelativeLayout) getLayoutInflater().inflate( R.layout.contacts_tab_layout, null); mTabManager.addTab(mTabHost.newTabSpec("Contact") .setIndicator(contacts), ContactsFragment.class, null); RelativeLayout message = (RelativeLayout) getLayoutInflater().inflate( R.layout.message_tab_layout, null); mTabManager.addTab( mTabHost.newTabSpec("Message").setIndicator(message), MessageFragment.class, null);
/** * 滑出侧边栏 */ private void slideOut() { TranslateAnimation translate = new TranslateAnimation(mWidth, TRANSLATE_ANIMATION_WIDTH, 0, 0); translate.setDuration(ANIMATION_DURATION_SLOW); translate.setFillAfter(true); mSettingLinearLayout.startAnimation(translate); mSettingLinearLayout.getAnimation().setAnimationListener( new Animation.AnimationListener() { @Override public void onAnimationStart(Animation anim) { } @Override public void onAnimationRepeat(Animation animation) { } @Override public void onAnimationEnd(Animation anima) { TranslateAnimation animation = new TranslateAnimation( 0, TRANSLATE_ANIMATION_WIDTH - mWidth, 0, 0); animation.setDuration(ANIMATION_DURATION_FAST); animation.setFillAfter(true); mMainLinearLayout.startAnimation(animation); mSlided = true; } }); }
/** * 滑进侧边栏 */ private void slideIn() { TranslateAnimation translate = new TranslateAnimation(TRANSLATE_ANIMATION_WIDTH, mWidth, 0, 0); translate.setDuration(ANIMATION_DURATION_FAST); // 动画完成时停在结束位置 translate.setFillAfter(true); mSettingLinearLayout.startAnimation(translate); mSettingLinearLayout.getAnimation().setAnimationListener( new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { TranslateAnimation mainAnimation = new TranslateAnimation( -mWidth + TRANSLATE_ANIMATION_WIDTH, 0, 0, 0); mainAnimation.setDuration(ANIMATION_DURATION_SLOW); mainAnimation.setFillAfter(true); mMainLinearLayout.startAnimation(mainAnimation); } @Override public void onAnimationRepeat(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { mSlided = false; } }); }
代码均在:https://huangsm.googlecode.com/svn/trunk/UiDemo
或:https://github.com/huangsanm/uidemo.git