转载,原博地址:http://blog.csdn.net/xiangxue336/article/details/22804971
今天介绍现在比较流行的一种app布局方式:内外层嵌套Tab,子Tab可以实现滑动切换。
实现原理:FragmentTabHost+Fragment实现第一层Tab。
在Fragment里利用ViewPaper,实现第二层Tab,也就是子Tab。
从原理可以看出,这两层Tab是完全解耦的,没有任何事件和数据联系,那么先介绍第一层怎么实现,由于google对FragmentTabHost+Fragment封装的比较好,实现过程无非是FragmentTabHost+Fragment的使用过程。
可以用一句话来说明过程:就是给FragmentTabHost设置一定数量的按钮背景。
- public static Context context;
-
-
-
- private Fragment frg_content;
-
-
-
-
- private FragmentTabHost frg_tabHost;
-
-
-
-
- private int intImageViewArray[] = {
- R.drawable.selector_bt_bookstore_featured, R.drawable.selector_bt_bookstore_top,
- R.drawable.selector_bt_bookstore_category, R.drawable.selector_bt_bookstore_search
- };
-
-
-
-
- private Class fragmentArray[] = {
- BookstoreFeaturedFragment.class, BookstoreTopFragment.class,
- BookstoreCategoryFragment.class, BookstoreSearchFragment.class
- };
-
-
-
-
- private String txt_Array[] = {
- "精选", "排行", "分类", "搜索"
- };
-
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- overridePendingTransition(R.anim.slide_right_in, R.anim.slide_mid_left_out);
-
- setContentView(R.layout.ac_bookstore_main);
-
-
-
- int count = intImageViewArray.length;
-
-
- frg_tabHost = (FragmentTabHost) findViewById(android.R.id.tabhost);
- frg_tabHost.setup(this, getSupportFragmentManager(), R.id.realtabcontent);
-
- for (int i = 0; i < count; i++) {
-
- ImageView imageView = new ImageView(this);
-
- imageView.setImageDrawable(skinContext.getResources().getDrawable(intImageViewArray[i]));
- imageView.setScaleType(ScaleType.CENTER_CROP);
- TabSpec tabSpec = frg_tabHost.newTabSpec(txt_Array[i]).setIndicator(imageView);
-
- frg_tabHost.addTab(tabSpec, fragmentArray[i], null);
- }
-
- frg_tabHost.setCurrentTab(0);
- getSlidingMenu().setSlidingEnabled(false);
-
- }
这样就实现了点击哪个按钮,就显示哪个fragment。
这样就存在一个问题,就是tab布局问题,显示在上面还是下面:
tab显示在底部的布局:
- <LinearLayout
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical" >
-
- <FrameLayout
- android:id="@+id/realtabcontent"
- android:layout_width="fill_parent"
- android:layout_height="0dip"
- android:layout_weight="1" />
-
- <android.support.v4.app.FragmentTabHost
- android:id="@android:id/tabhost"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content" >
-
- <FrameLayout
- android:id="@android:id/tabcontent"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:layout_weight="0" />
- </android.support.v4.app.FragmentTabHost>
-
-
- </LinearLayout>
tab显示在顶部的布局:
- <LinearLayout
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical" >
-
- <android.support.v4.app.FragmentTabHost
- android:id="@android:id/tabhost"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content" >
-
- <FrameLayout
- android:id="@android:id/tabcontent"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:layout_weight="0" />
- </android.support.v4.app.FragmentTabHost>
-
- <FrameLayout
- android:id="@+id/realtabcontent"
- android:layout_width="fill_parent"
- android:layout_height="0dip"
- android:layout_weight="1" />
- </LinearLayout>
对比可以看出:realtabcontent是fragment显示的位置,一般是竖向填充:layout_weight="1"
tabhost是tab按钮放置位置,一般是横向填充,高度根据背景自适应。
tabcontent是干什么用的呢?看下代码:
- public void switchContent(Fragment fragment) {
-
- getSupportFragmentManager().beginTransaction().replace(android.R.id.tabcontent, fragment)
- .commit();
-
- }
这行代码的作用是 显示frament页,所以我认为tabcontent指的是当前frament页面,可以用于页面的刷新。
这样第一层tab就实现了。
我们在实现第二层tab,其实即使ViewPaper的使用方法:
ViewPager的使用比较简单,完全可以当做一个listview使用:
- viewpager_featured.setAdapter(viewPagerAdapter);
- viewpager_featured.setCurrentItem(0);
还可以设置缓存页面个数:viewpager_featured.setOffscreenPageLimit(2);用来防止页面刷新,这个数值越大会占用越多内存。所以放置数据刷新的方法是设置绑定数据的状态,根据数据状态觉得是否要刷新。
主要讲解下ViewPager和tab结合的时候的使用,特别是有动画效果的时候的使用。
这里介绍一种tab实现方式:1.tab 个数可删减。2、焦点tab显示在可见位置
这里tab按钮用textview来实现,先动态的初始化tab个数,以及根据显示字数多少设置宽度:
根据屏幕大小动态计算了,textview按钮的属性。并且设置了点击监听,根据tab的数量给adapter绑定数据。
设置适配器:
- setSlideMenu();
- TextView mTextView = (TextView) linearLayout_menu.getChildAt(0);
- mTextView.setSelected(true);
-
- viewpager_featured.setAdapter(viewPagerAdapter);
- viewpager_featured.setCurrentItem(0);
这样点击tab,ViewPaper可以自动切换了,那滑动ViewPapert,tab调整显示位置实现:
- viewpager_featured.setOnPageChangeListener(new OnPageChangeListener() {
-
- @SuppressLint("NewApi")
- @Override
- public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
-
- getMenuXPosition();
- }
-
- @Override
- public void onPageSelected(int position) {
-
- if (listMenuPosition == null || listMenuPosition.size() <= 0) {
- getMenuXPosition();
- }
-
- int moveLeft = (int) listMenuPosition.get(position) - (int) listMenuPosition.get(1);
- hScroll_menu.smoothScrollTo(moveLeft, 0);
-
- setSelectedState(position);
-
- }
-
- @Override
- public void onPageScrollStateChanged(int state) {
-
- }
- });
-
-
-
- private List<Integer> listMenuPosition;
- private void getMenuXPosition() {
-
- for (int i = 0; i < linearLayout_menu.getChildCount(); i++) {
- TextView textView = (TextView) linearLayout_menu.getChildAt(i);
- listMenuPosition.add(textView.getLeft());
- }
-
- }
是通过记录每个textview的左侧位置,每次滑动的时候都都让scrollview滑动一定位置,保证焦点textview 的tab可见。最后给出布局文件:
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="@dimen/bookstore_featured_menu_height"
- android:orientation="horizontal" >
-
- <HorizontalScrollView
- android:id="@+id/scrollview_menu"
- android:layout_width="0dip"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:scrollbars="none" >
-
- <LinearLayout
- android:id="@+id/linearLayout_menu"
- android:layout_width="0dip"
- android:layout_height="match_parent"
- android:background="@drawable/bookstore_featured_navigation_bg"
- android:gravity="center_vertical"
- android:orientation="horizontal" >
- </LinearLayout>
- </HorizontalScrollView>
-
- </LinearLayout>
-
- <RelativeLayout
- android:id="@+id/relativelayout_viewpager"
- android:layout_width="match_parent"
- android:layout_height="match_parent" >
-
- <android.support.v4.view.ViewPager
- android:id="@+id/viewpager_featured_pager"
- android:layout_width="match_parent"
- android:layout_height="match_parent" >
- </android.support.v4.view.ViewPager>
-
- <ProgressBar
- android:id="@+id/progressBar_loading"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_centerInParent="true" />
- </RelativeLayout>
和ViewPaper配合实现tab的方式有很多,关键根据需求不同来选择实现方式,textview、button、radiobutton、iamgeview都可以用来实现tab。