采用PagerAdapter中的FragmentPagerAdapter来实现页面切换,适用于a handful of typically more static fragments to be paged through
1.Layout ViewPager
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <android.support.v4.view.ViewPager android:id="@+id/vpPager" android:layout_width="match_parent" android:layout_height="wrap_content"> <!-- PagerTabStrip automatically display the page indicator for your pager --> <android.support.v4.view.PagerTabStrip android:id="@+id/pager_header" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="top" android:paddingBottom="4dp" android:paddingTop="4dp" /> </android.support.v4.view.ViewPager> </LinearLayout>
2.Define Fragments
FirstFragment is like SecondFragment
1 package com.example.fragmentpagerdemo; 2 3 import android.os.Bundle; 4 import android.support.v4.app.Fragment; 5 import android.view.LayoutInflater; 6 import android.view.View; 7 import android.view.ViewGroup; 8 import android.widget.TextView; 9 10 public class FirstFragment extends Fragment{ 11 12 //Store instance variables 13 private String title; 14 private int page; 15 16 /** 17 * 每一个fragment实例都可以附带一个bundle对象: bundle-->(key-value) 18 * @param title 19 * @param page 20 * @return 21 */ 22 //newInstance constructor for creating fragment with arguments 23 public static FirstFragment newsInstance(String title, int page) 24 { 25 //首先创建fragment实例 26 FirstFragment fragment = new FirstFragment(); 27 //创建bundle对象 28 Bundle bundle = new Bundle(); 29 //向该bundle对象中添加参数 30 bundle.putInt("page", page); 31 bundle.putString("title", title); 32 //将bundle附加给fragment 33 fragment.setArguments(bundle); 34 return fragment; 35 } 36 // Store instance variables based on arguments passed 37 @Override 38 public void onCreate(Bundle savedInstanceState) { 39 // 40 super.onCreate(savedInstanceState); 41 page = getArguments().getInt("page", 0); 42 title = getArguments().getString("title", null); 43 } 44 45 @Override 46 public View onCreateView(LayoutInflater inflater, ViewGroup container, 47 Bundle savedInstanceState) { 48 // 49 View view = inflater.inflate(R.layout.first_fragment, container, false); 50 TextView text = (TextView) view.findViewById(R.id.textView); 51 text.setText(page + "--" + title); 52 return view; 53 } 54 55 56 57 58 }
3.MainActivity
1 package com.example.fragmentpagerdemo; 2 3 import android.annotation.SuppressLint; 4 import android.os.Bundle; 5 import android.support.v4.app.Fragment; 6 import android.support.v4.app.FragmentActivity; 7 import android.support.v4.app.FragmentManager; 8 import android.support.v4.app.FragmentPagerAdapter; 9 import android.support.v4.view.ViewPager; 10 import android.support.v4.view.ViewPager.OnPageChangeListener; 11 import android.widget.Toast; 12 13 public class MainActivity extends FragmentActivity{ 14 FragmentPagerAdapter adapterViewPager; 15 ViewPager vpPager; 16 @Override 17 protected void onCreate(Bundle savedInstanceState) { 18 super.onCreate(savedInstanceState); 19 setContentView(R.layout.activity_main); 20 21 vpPager = (ViewPager) findViewById(R.id.vpPager); 22 adapterViewPager = new MyPagerAdapter(getSupportFragmentManager()); 23 vpPager.setAdapter(adapterViewPager); 24 //setup OnPageChangeListener 25 vpPager.setOnPageChangeListener(new OnPageChangeListener() 26 { 27 28 // Called when the scroll state changes: 29 // SCROLL_STATE_IDLE, SCROLL_STATE_DRAGGING, SCROLL_STATE_SETTLING 30 @Override 31 public void onPageScrollStateChanged(int arg0) { 32 // 33 34 } 35 // This method will be invoked when the current page is scrolled 36 @Override 37 public void onPageScrolled(int arg0, float arg1, int arg2) { 38 // 39 40 } 41 // This method will be invoked when a new page becomes selected. 42 @SuppressLint("ShowToast") 43 @Override 44 public void onPageSelected(int arg0) { 45 // 46 System.out.println("The page is cahnged to:" + vpPager.getCurrentItem()); 47 // Toast.makeText(this, "The page is changed to:" + vpPager.getCurrentItem(), Toast.LENGTH_LONG); 48 } 49 }); 50 } 51 public static class MyPagerAdapter extends FragmentPagerAdapter 52 { 53 private static int NUM_ITEMS = 3; 54 public MyPagerAdapter(FragmentManager fm) { 55 super(fm); 56 } 57 @Override 58 public Fragment getItem(int position) { 59 // 60 switch(position) 61 { 62 case 0: 63 return FirstFragment.newsInstance("Page @ 1", 0); 64 case 1: 65 return FirstFragment.newsInstance("Page @ 2", 1); 66 case 2: 67 return SecondFragment.newsInstance("Page @ 3", 2); 68 default: 69 return null; 70 } 71 } 72 @Override 73 public int getCount() { 74 // 75 return NUM_ITEMS; 76 } 77 // Returns the page title for the top indicator 78 @Override 79 public CharSequence getPageTitle(int position) { 80 // 81 return "Page" + position; 82 } 83 } 84 }
Google recommended method to implement Tab: Google Play style sliding tabs
First need to copy the following two java source files into your application:
SlidingTabLayout.java

1 /* 2 * Copyright 2014 Google Inc. All rights reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.samples.apps.iosched.ui.widget; 18 19 import android.content.Context; 20 import android.graphics.Typeface; 21 import android.os.Build; 22 import android.support.v4.view.PagerAdapter; 23 import android.support.v4.view.ViewPager; 24 import android.util.AttributeSet; 25 import android.util.SparseArray; 26 import android.util.TypedValue; 27 import android.view.Gravity; 28 import android.view.LayoutInflater; 29 import android.view.View; 30 import android.view.ViewGroup; 31 import android.widget.HorizontalScrollView; 32 import android.widget.LinearLayout; 33 import android.widget.TextView; 34 35 /** 36 * To be used with ViewPager to provide a tab indicator component which give constant feedback as to 37 * the user's scroll progress. 38 * <p> 39 * To use the component, simply add it to your view hierarchy. Then in your 40 * {@link android.app.Activity} or {@link android.support.v4.app.Fragment} call 41 * {@link #setViewPager(ViewPager)} providing it the ViewPager this layout is being used for. 42 * <p> 43 * The colors can be customized in two ways. The first and simplest is to provide an array of colors 44 * via {@link #setSelectedIndicatorColors(int...)}. The 45 * alternative is via the {@link TabColorizer} interface which provides you complete control over 46 * which color is used for any individual position. 47 * <p> 48 * The views used as tabs can be customized by calling {@link #setCustomTabView(int, int)}, 49 * providing the layout ID of your custom layout. 50 */ 51 public class SlidingTabLayout extends HorizontalScrollView { 52 /** 53 * Allows complete control over the colors drawn in the tab layout. Set with 54 * {@link #setCustomTabColorizer(TabColorizer)}. 55 */ 56 public interface TabColorizer { 57 58 /** 59 * @return return the color of the indicator used when {@code position} is selected. 60 */ 61 int getIndicatorColor(int position); 62 63 } 64 65 private static final int TITLE_OFFSET_DIPS = 24; 66 private static final int TAB_VIEW_PADDING_DIPS = 16; 67 private static final int TAB_VIEW_TEXT_SIZE_SP = 12; 68 69 private int mTitleOffset; 70 71 private int mTabViewLayoutId; 72 private int mTabViewTextViewId; 73 private boolean mDistributeEvenly; 74 75 private ViewPager mViewPager; 76 private SparseArray<String> mContentDescriptions = new SparseArray<String>(); 77 private ViewPager.OnPageChangeListener mViewPagerPageChangeListener; 78 79 private final SlidingTabStrip mTabStrip; 80 81 public SlidingTabLayout(Context context) { 82 this(context, null); 83 } 84 85 public SlidingTabLayout(Context context, AttributeSet attrs) { 86 this(context, attrs, 0); 87 } 88 89 public SlidingTabLayout(Context context, AttributeSet attrs, int defStyle) { 90 super(context, attrs, defStyle); 91 92 // Disable the Scroll Bar 93 setHorizontalScrollBarEnabled(false); 94 // Make sure that the Tab Strips fills this View 95 setFillViewport(true); 96 97 mTitleOffset = (int) (TITLE_OFFSET_DIPS * getResources().getDisplayMetrics().density); 98 99 mTabStrip = new SlidingTabStrip(context); 100 addView(mTabStrip, LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); 101 } 102 103 /** 104 * Set the custom {@link TabColorizer} to be used. 105 * 106 * If you only require simple custmisation then you can use 107 * {@link #setSelectedIndicatorColors(int...)} to achieve 108 * similar effects. 109 */ 110 public void setCustomTabColorizer(TabColorizer tabColorizer) { 111 mTabStrip.setCustomTabColorizer(tabColorizer); 112 } 113 114 public void setDistributeEvenly(boolean distributeEvenly) { 115 mDistributeEvenly = distributeEvenly; 116 } 117 118 /** 119 * Sets the colors to be used for indicating the selected tab. These colors are treated as a 120 * circular array. Providing one color will mean that all tabs are indicated with the same color. 121 */ 122 public void setSelectedIndicatorColors(int... colors) { 123 mTabStrip.setSelectedIndicatorColors(colors); 124 } 125 126 /** 127 * Set the {@link ViewPager.OnPageChangeListener}. When using {@link SlidingTabLayout} you are 128 * required to set any {@link ViewPager.OnPageChangeListener} through this method. This is so 129 * that the layout can update it's scroll position correctly. 130 * 131 * @see ViewPager#setOnPageChangeListener(ViewPager.OnPageChangeListener) 132 */ 133 public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) { 134 mViewPagerPageChangeListener = listener; 135 } 136 137 /** 138 * Set the custom layout to be inflated for the tab views. 139 * 140 * @param layoutResId Layout id to be inflated 141 * @param textViewId id of the {@link TextView} in the inflated view 142 */ 143 public void setCustomTabView(int layoutResId, int textViewId) { 144 mTabViewLayoutId = layoutResId; 145 mTabViewTextViewId = textViewId; 146 } 147 148 /** 149 * Sets the associated view pager. Note that the assumption here is that the pager content 150 * (number of tabs and tab titles) does not change after this call has been made. 151 */ 152 public void setViewPager(ViewPager viewPager) { 153 mTabStrip.removeAllViews(); 154 155 mViewPager = viewPager; 156 if (viewPager != null) { 157 viewPager.setOnPageChangeListener(new InternalViewPagerListener()); 158 populateTabStrip(); 159 } 160 } 161 162 /** 163 * Create a default view to be used for tabs. This is called if a custom tab view is not set via 164 * {@link #setCustomTabView(int, int)}. 165 */ 166 protected TextView createDefaultTabView(Context context) { 167 TextView textView = new TextView(context); 168 textView.setGravity(Gravity.CENTER); 169 textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, TAB_VIEW_TEXT_SIZE_SP); 170 textView.setTypeface(Typeface.DEFAULT_BOLD); 171 textView.setLayoutParams(new LinearLayout.LayoutParams( 172 ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); 173 174 TypedValue outValue = new TypedValue(); 175 getContext().getTheme().resolveAttribute(android.R.attr.selectableItemBackground, 176 outValue, true); 177 textView.setBackgroundResource(outValue.resourceId); 178 textView.setAllCaps(true); 179 180 int padding = (int) (TAB_VIEW_PADDING_DIPS * getResources().getDisplayMetrics().density); 181 textView.setPadding(padding, padding, padding, padding); 182 183 return textView; 184 } 185 186 private void populateTabStrip() { 187 final PagerAdapter adapter = mViewPager.getAdapter(); 188 final View.OnClickListener tabClickListener = new TabClickListener(); 189 190 for (int i = 0; i < adapter.getCount(); i++) { 191 View tabView = null; 192 TextView tabTitleView = null; 193 194 if (mTabViewLayoutId != 0) { 195 // If there is a custom tab view layout id set, try and inflate it 196 tabView = LayoutInflater.from(getContext()).inflate(mTabViewLayoutId, mTabStrip, 197 false); 198 tabTitleView = (TextView) tabView.findViewById(mTabViewTextViewId); 199 } 200 201 if (tabView == null) { 202 tabView = createDefaultTabView(getContext()); 203 } 204 205 if (tabTitleView == null && TextView.class.isInstance(tabView)) { 206 tabTitleView = (TextView) tabView; 207 } 208 209 if (mDistributeEvenly) { 210 LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) tabView.getLayoutParams(); 211 lp.width = 0; 212 lp.weight = 1; 213 } 214 215 tabTitleView.setText(adapter.getPageTitle(i)); 216 tabView.setOnClickListener(tabClickListener); 217 String desc = mContentDescriptions.get(i, null); 218 if (desc != null) { 219 tabView.setContentDescription(desc); 220 } 221 222 mTabStrip.addView(tabView); 223 if (i == mViewPager.getCurrentItem()) { 224 tabView.setSelected(true); 225 } 226 } 227 } 228 229 public void setContentDescription(int i, String desc) { 230 mContentDescriptions.put(i, desc); 231 } 232 233 @Override 234 protected void onAttachedToWindow() { 235 super.onAttachedToWindow(); 236 237 if (mViewPager != null) { 238 scrollToTab(mViewPager.getCurrentItem(), 0); 239 } 240 } 241 242 private void scrollToTab(int tabIndex, int positionOffset) { 243 final int tabStripChildCount = mTabStrip.getChildCount(); 244 if (tabStripChildCount == 0 || tabIndex < 0 || tabIndex >= tabStripChildCount) { 245 return; 246 } 247 248 View selectedChild = mTabStrip.getChildAt(tabIndex); 249 if (selectedChild != null) { 250 int targetScrollX = selectedChild.getLeft() + positionOffset; 251 252 if (tabIndex > 0 || positionOffset > 0) { 253 // If we're not at the first child and are mid-scroll, make sure we obey the offset 254 targetScrollX -= mTitleOffset; 255 } 256 257 scrollTo(targetScrollX, 0); 258 } 259 } 260 261 private class InternalViewPagerListener implements ViewPager.OnPageChangeListener { 262 private int mScrollState; 263 264 @Override 265 public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 266 int tabStripChildCount = mTabStrip.getChildCount(); 267 if ((tabStripChildCount == 0) || (position < 0) || (position >= tabStripChildCount)) { 268 return; 269 } 270 271 mTabStrip.onViewPagerPageChanged(position, positionOffset); 272 273 View selectedTitle = mTabStrip.getChildAt(position); 274 int extraOffset = (selectedTitle != null) 275 ? (int) (positionOffset * selectedTitle.getWidth()) 276 : 0; 277 scrollToTab(position, extraOffset); 278 279 if (mViewPagerPageChangeListener != null) { 280 mViewPagerPageChangeListener.onPageScrolled(position, positionOffset, 281 positionOffsetPixels); 282 } 283 } 284 285 @Override 286 public void onPageScrollStateChanged(int state) { 287 mScrollState = state; 288 289 if (mViewPagerPageChangeListener != null) { 290 mViewPagerPageChangeListener.onPageScrollStateChanged(state); 291 } 292 } 293 294 @Override 295 public void onPageSelected(int position) { 296 if (mScrollState == ViewPager.SCROLL_STATE_IDLE) { 297 mTabStrip.onViewPagerPageChanged(position, 0f); 298 scrollToTab(position, 0); 299 } 300 for (int i = 0; i < mTabStrip.getChildCount(); i++) { 301 mTabStrip.getChildAt(i).setSelected(position == i); 302 } 303 if (mViewPagerPageChangeListener != null) { 304 mViewPagerPageChangeListener.onPageSelected(position); 305 } 306 } 307 308 } 309 310 private class TabClickListener implements View.OnClickListener { 311 @Override 312 public void onClick(View v) { 313 for (int i = 0; i < mTabStrip.getChildCount(); i++) { 314 if (v == mTabStrip.getChildAt(i)) { 315 mViewPager.setCurrentItem(i); 316 return; 317 } 318 } 319 } 320 } 321 322 }
SlidingTabStrip.java

1 /* 2 * Copyright 2014 Google Inc. All rights reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.samples.apps.iosched.ui.widget; 18 19 import android.R; 20 import android.content.Context; 21 import android.graphics.Canvas; 22 import android.graphics.Color; 23 import android.graphics.Paint; 24 import android.util.AttributeSet; 25 import android.util.TypedValue; 26 import android.view.View; 27 import android.widget.LinearLayout; 28 29 class SlidingTabStrip extends LinearLayout { 30 31 private static final int DEFAULT_BOTTOM_BORDER_THICKNESS_DIPS = 0; 32 private static final byte DEFAULT_BOTTOM_BORDER_COLOR_ALPHA = 0x26; 33 private static final int SELECTED_INDICATOR_THICKNESS_DIPS = 3; 34 private static final int DEFAULT_SELECTED_INDICATOR_COLOR = 0xFF33B5E5; 35 36 private final int mBottomBorderThickness; 37 private final Paint mBottomBorderPaint; 38 39 private final int mSelectedIndicatorThickness; 40 private final Paint mSelectedIndicatorPaint; 41 42 private final int mDefaultBottomBorderColor; 43 44 private int mSelectedPosition; 45 private float mSelectionOffset; 46 47 private SlidingTabLayout.TabColorizer mCustomTabColorizer; 48 private final SimpleTabColorizer mDefaultTabColorizer; 49 50 SlidingTabStrip(Context context) { 51 this(context, null); 52 } 53 54 SlidingTabStrip(Context context, AttributeSet attrs) { 55 super(context, attrs); 56 setWillNotDraw(false); 57 58 final float density = getResources().getDisplayMetrics().density; 59 60 TypedValue outValue = new TypedValue(); 61 context.getTheme().resolveAttribute(R.attr.colorForeground, outValue, true); 62 final int themeForegroundColor = outValue.data; 63 64 mDefaultBottomBorderColor = setColorAlpha(themeForegroundColor, 65 DEFAULT_BOTTOM_BORDER_COLOR_ALPHA); 66 67 mDefaultTabColorizer = new SimpleTabColorizer(); 68 mDefaultTabColorizer.setIndicatorColors(DEFAULT_SELECTED_INDICATOR_COLOR); 69 70 mBottomBorderThickness = (int) (DEFAULT_BOTTOM_BORDER_THICKNESS_DIPS * density); 71 mBottomBorderPaint = new Paint(); 72 mBottomBorderPaint.setColor(mDefaultBottomBorderColor); 73 74 mSelectedIndicatorThickness = (int) (SELECTED_INDICATOR_THICKNESS_DIPS * density); 75 mSelectedIndicatorPaint = new Paint(); 76 } 77 78 void setCustomTabColorizer(SlidingTabLayout.TabColorizer customTabColorizer) { 79 mCustomTabColorizer = customTabColorizer; 80 invalidate(); 81 } 82 83 void setSelectedIndicatorColors(int... colors) { 84 // Make sure that the custom colorizer is removed 85 mCustomTabColorizer = null; 86 mDefaultTabColorizer.setIndicatorColors(colors); 87 invalidate(); 88 } 89 90 void onViewPagerPageChanged(int position, float positionOffset) { 91 mSelectedPosition = position; 92 mSelectionOffset = positionOffset; 93 invalidate(); 94 } 95 96 @Override 97 protected void onDraw(Canvas canvas) { 98 final int height = getHeight(); 99 final int childCount = getChildCount(); 100 final SlidingTabLayout.TabColorizer tabColorizer = mCustomTabColorizer != null 101 ? mCustomTabColorizer 102 : mDefaultTabColorizer; 103 104 // Thick colored underline below the current selection 105 if (childCount > 0) { 106 View selectedTitle = getChildAt(mSelectedPosition); 107 int left = selectedTitle.getLeft(); 108 int right = selectedTitle.getRight(); 109 int color = tabColorizer.getIndicatorColor(mSelectedPosition); 110 111 if (mSelectionOffset > 0f && mSelectedPosition < (getChildCount() - 1)) { 112 int nextColor = tabColorizer.getIndicatorColor(mSelectedPosition + 1); 113 if (color != nextColor) { 114 color = blendColors(nextColor, color, mSelectionOffset); 115 } 116 117 // Draw the selection partway between the tabs 118 View nextTitle = getChildAt(mSelectedPosition + 1); 119 left = (int) (mSelectionOffset * nextTitle.getLeft() + 120 (1.0f - mSelectionOffset) * left); 121 right = (int) (mSelectionOffset * nextTitle.getRight() + 122 (1.0f - mSelectionOffset) * right); 123 } 124 125 mSelectedIndicatorPaint.setColor(color); 126 127 canvas.drawRect(left, height - mSelectedIndicatorThickness, right, 128 height, mSelectedIndicatorPaint); 129 } 130 131 // Thin underline along the entire bottom edge 132 canvas.drawRect(0, height - mBottomBorderThickness, getWidth(), height, mBottomBorderPaint); 133 } 134 135 /** 136 * Set the alpha value of the {@code color} to be the given {@code alpha} value. 137 */ 138 private static int setColorAlpha(int color, byte alpha) { 139 return Color.argb(alpha, Color.red(color), Color.green(color), Color.blue(color)); 140 } 141 142 /** 143 * Blend {@code color1} and {@code color2} using the given ratio. 144 * 145 * @param ratio of which to blend. 1.0 will return {@code color1}, 0.5 will give an even blend, 146 * 0.0 will return {@code color2}. 147 */ 148 private static int blendColors(int color1, int color2, float ratio) { 149 final float inverseRation = 1f - ratio; 150 float r = (Color.red(color1) * ratio) + (Color.red(color2) * inverseRation); 151 float g = (Color.green(color1) * ratio) + (Color.green(color2) * inverseRation); 152 float b = (Color.blue(color1) * ratio) + (Color.blue(color2) * inverseRation); 153 return Color.rgb((int) r, (int) g, (int) b); 154 } 155 156 private static class SimpleTabColorizer implements SlidingTabLayout.TabColorizer { 157 private int[] mIndicatorColors; 158 159 @Override 160 public final int getIndicatorColor(int position) { 161 return mIndicatorColors[position % mIndicatorColors.length]; 162 } 163 164 void setIndicatorColors(int... colors) { 165 mIndicatorColors = colors; 166 } 167 } 168 }
You may choose to move them to a suitable package in your project.Once you have included SlidingTabLayout.java
andSlidingTabStrip.java
files within your app, you can use the SlidingTabLayout
in your layout file to display tabs. Your layout file will have tabs on the top and a ViewPager
on the bottom as shown below:
https://github.com/codepath/android_guides/wiki/Google-Play-Style-Tabs-using-SlidingTabLayout