29

編輯TabLayout與viewpager不平滑滾動

我按照這些教程來解決這個問題。

http://www.truiton.com/2015/06/android-tabs-example-fragments-viewpager/ https://guides.codepath.com/android/google-play-style-tabs-using-tablayout http://www.voidynullness.net/blog/2015/08/16/android-tablayout-design-support-library-tutorial/

但嘗試了多種解決方案後的煩人問題仍然存在。這裏是我面臨的問題的演示。自從我陷入這個問題後,我已經過了幾個星期。

Link演示。

設備我使用的測試是的Nexus 4和Nexus 5.

TabLayoutViewPager不滾動順暢。我需要刷兩次才能在下次點擊時轉移。我瀏覽過網頁,但找不到任何解決方案。 我正在使用最新的支持設計庫。 這裏是文件的gradle

apply plugin: 'com.android.application' 

android { 
compileSdkVersion 23 
buildToolsVersion "23.0.3" 

defaultConfig { 
    applicationId "com.softoven.ultron" 
    minSdkVersion 15 
    targetSdkVersion 23 
    versionCode 1 
    versionName "1.0" 
} 
buildTypes { 
    release { 
     minifyEnabled false 
     proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 
    } 
} 
} 

dependencies { 
compile fileTree(dir: 'libs', include: ['*.jar']) 
testCompile 'junit:junit:4.12' 
compile 'com.android.support:appcompat-v7:23.3.0' 
compile 'com.android.support:design:23.3.0' 
compile 'org.jsoup:jsoup:1.6.1' 
compile 'com.mikhaellopez:circularimageview:3.0.0' 
compile 'com.android.support:recyclerview-v7:23.3.0' 
compile 'com.mcxiaoke.volley:library:1.0.19' 
compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.5' 
compile 'com.google.code.gson:gson:2.5' 
} 

這裏是活動的代碼。

private DrawerLayout drawerLayout; 
private ViewPager viewPager; 
private TabLayout tabLayout; 
private NavigationView navigationView; 
private CategoriesDTO categoriesDTO; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    initToolbar(); 
    initUi(); 
    loadCategories(); 
} 

private void initToolbar() { 
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 
    setSupportActionBar(toolbar); 
    getSupportActionBar().setDisplayHomeAsUpEnabled(true); 
    getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_action_menu); 
} 

private void initUi() { 
    drawerLayout = (DrawerLayout) findViewById(R.id.drawer); 
    navigationView = (NavigationView) findViewById(R.id.navigation); 
    viewPager = (ViewPager) findViewById(R.id.viewPager); 
    tabLayout = (TabLayout) findViewById(R.id.tab); 

} 

private void loadCategories() { 
    StringRequest request = new StringRequest(Constants.URL_GET_CATEGORIES, new Response.Listener<String>() { 
     @Override 
     public void onResponse(String response) { 
      categoriesDTO = Constants.gson.fromJson(response, CategoriesDTO.class); 
      ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager()); 
      viewPager.setOffscreenPageLimit(1); 
      viewPager.setAdapter(adapter); 
      setTabLayout(); 
     } 
    }, new Response.ErrorListener() { 
     @Override 
     public void onErrorResponse(VolleyError error) { 

     } 
    }); 

    ApplicationController.getmInstance().addToRequestQueue(request); 
} 

private void setTabLayout() { 

    tabLayout.setupWithViewPager(viewPager); 

} 


@Override 
public boolean onCreateOptionsMenu(Menu menu) { 
    MenuInflater menuInflater = getMenuInflater(); 
    menuInflater.inflate(R.menu.home_side_menu, menu); 
    return true; 
} 

@Override 
public boolean onOptionsItemSelected(MenuItem item) { 
    int id = item.getItemId(); 
    switch (id) { 
     case android.R.id.home: 
      drawerLayout.openDrawer(GravityCompat.START); 
      return true; 
    } 
    return super.onOptionsItemSelected(item); 
} 

private class ViewPagerAdapter extends FragmentPagerAdapter { 

    public ViewPagerAdapter(FragmentManager fm) { 
     super(fm); 
    } 

    @Override 
    public Fragment getItem(int position) { 
     return new ContentFragment(); 
    } 

    @Override 
    public int getCount() { 
     return 10; 
    } 

    @Override 
    public CharSequence getPageTitle(int position) { 
     String title = categoriesDTO.getCategories().get(position).getTitle(); 
     return (CharSequence) title; 
    } 
} 

和XML文件

<?xml version="1.0" encoding="utf-8"?> 

<android.support.design.widget.CoordinatorLayout 
    android:layout_width="match_parent" 
    android:layout_height="match_parent"> 


    <android.support.design.widget.AppBarLayout 
     android:id="@+id/app_bar" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content"> 

     <include 
      android:id="@+id/toolbar" 
      layout="@layout/toolbar" 
      app:layout_scrollFlags="scroll|enterAlways" 
      app:popupTheme="@style/ThemeOverlay.AppCompat.Light" /> 

     <android.support.design.widget.TabLayout 
      android:id="@+id/tab" 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      app:tabTextColor="#fff" 
      app:tabGravity="fill" 
      app:tabMode="scrollable" 
      > 

     </android.support.design.widget.TabLayout> 
    </android.support.design.widget.AppBarLayout> 

    <android.support.v4.view.ViewPager 
     android:id="@+id/viewPager" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     app:layout_behavior="@string/appbar_scrolling_view_behavior"> 

    </android.support.v4.view.ViewPager> 
</android.support.design.widget.CoordinatorLayout> 

<android.support.design.widget.NavigationView 
    android:id="@+id/navigation" 
    android:layout_width="wrap_content" 
    android:layout_height="match_parent" 
    android:layout_gravity="start" 
    app:menu="@menu/home_drawer_menu"> 

</android.support.design.widget.NavigationView> 

這裏是你可以看到指示燈被部分分割的屏幕截圖。

enter image description here

任何解決方案?

+0

你在改變標籤頁時是否在主線程上做了很多工作? – Ritesh

+0

不,我現在只有一個靜態的片段。 –

+0

@ZeeshanShabbir可能是因爲你有抽空服務器請求而導致它。 –

回答

20

我剛剛通過你的代碼。問題在於您沒有提供任何佈局來在ContentFragment.java內膨脹。

我改變你的方法

@Nullable 
    @Override 
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 
     //return super.onCreateView(inflater, container, savedInstanceState); 
     return inflater.inflate(R.layout.feed_item, container, false); 

    } 

做了這些改變你的標籤被順利滾動之後。我不知道這種行爲背後的原因,但這個東西使它工作

+0

在我的情況下,我沒有覆蓋從我的片段(嘗試一些示例應用程序)onCreateView,所以我面臨着滾動問題。從Fragment的onCreateView返回視圖後,問題得到解決。 – Prashant

0

在你Android清單文件<Application>標籤中加入這一行

android:largeHeap="true" 
+0

這個標籤會做什麼? –

+0

它增加了堆大小。並可能是你viewpager滾動更快... – Krupa

+0

不,它不工作 –

1

啓用你的所有StrictMode政策的應用程序檢測到您可能是在主線程上無意中執行任何冗長的操作,造成的滯後,以便您可以採取進一步的必要糾正措施。

StrictMode是一款開發人員工具,它可以檢測出您可能會意外執行的操作,並將其引起您的注意,以便您修復它們。 StrictMode最常用於捕獲應用程序主線程上的意外磁盤或網絡訪問,其中接收UI操作併發生動畫。

詳情請參閱https://developer.android.com/reference/android/os/StrictMode.html

// Enable all thread strict mode policies 
    StrictMode.ThreadPolicy.Builder threadPolicyBuilder = new StrictMode.ThreadPolicy.Builder(); 

    // Detect everything that's potentially suspect 
    threadPolicyBuilder.detectAll(); 

    // Crash the whole process on violation 
    threadPolicyBuilder.penaltyDeath(); 

    // Log detected violations to the system log 
    threadPolicyBuilder.penaltyLog(); 

    // Crash the whole process on any network usage. 
    threadPolicyBuilder.penaltyDeathOnNetwork(); 


    StrictMode.ThreadPolicy threadPolicy = threadPolicyBuilder.build(); 
    StrictMode.setThreadPolicy(threadPolicy); 

    // Enable all VM strict mode policies 
    StrictMode.VmPolicy.Builder vmPolicyBuilder = new StrictMode.VmPolicy.Builder(); 

    // Detect everything that's potentially suspect 
    vmPolicyBuilder.detectAll(); 

    // Log detected violations to the system log 
    vmPolicyBuilder.penaltyLog(); 

    StrictMode.VmPolicy vmPolicy = vmPolicyBuilder.build(); 
    StrictMode.setVmPolicy(vmPolicy); 
+0

請添加一些解釋此代碼將做什麼? –

+0

添加了進一步的解釋。已經爲每行代碼提供了評論。 – Chebyr

2

我認爲你需要使用override方法setUserVisibleHint

您需要在Fragment中添加此項。

@Override 
public void setUserVisibleHint(boolean isVisibleToUser) { 
    super.setUserVisibleHint(isVisibleToUser); 
    if (isVisibleToUser) { 
     // load data here 
    }else{ 
     // fragment is no longer visible 
    } 
} 

讓您offScreenPageLimit到標籤數你有。

查看更多about setUserVisibleHinthere

+0

這怎麼修復滾動? –

+0

你看過鏈接嗎? –

+0

將offScreenPageLimit設置爲多個TABS。 –

1

這對android的座標佈局和appBar佈局並不新鮮;無論你做什麼,我相信你都無法使它更順暢。 但是

https://github.com/henrytao-me/smooth-app-bar-layout 

這可以滿足您的要求; 但是首先從

https://play.google.com/store/apps/details?id=me.henrytao.smoothappbarlayout 

下載示例應用程序,看它是否適合你的需要。(只是要確定)

+0

實際上,使用示例應用程序不能解決問題,它的替代方案和Ankit Aggarwal的解決方案完美無瑕。 – Prashant

0

首先,讓所有光滑不上主線程做繁重的作業,使用異步任務(不碰在異步任務視圖),一切都將在反正:)

光滑嘗試我的方式做到這一點:

SlidingTabLayout:

public class SlidingTabLayout extends HorizontalScrollView { 
    /** 
    * Allows complete control over the colors drawn in the tab layout. Set with 
    * {@link #setCustomTabColorizer(TabColorizer)}. 
    */ 
    View oldSelection = null; 

    public interface TabColorizer { 

     /** 
     * @return return the color of the indicator used when {@code position} is selected. 
     */ 
     int getIndicatorColor(int position); 

    } 

    private static final int TITLE_OFFSET_DIPS = 24; 
    private static final int TAB_VIEW_PADDING_DIPS = 8; 
    private static final int TAB_VIEW_TEXT_SIZE_SP = 12; 

    private int mTitleOffset; 

    private int mTabViewLayoutId; 
    private int mTabViewTextViewId; 
    private boolean mDistributeEvenly; 

    private ViewPager mViewPager; 
    private SparseArray<String> mContentDescriptions = new SparseArray<String>(); 
    private ViewPager.OnPageChangeListener mViewPagerPageChangeListener; 

    private final SlidingTabStrip mTabStrip; 

    public SlidingTabLayout(Context context) { 
     this(context, null); 
    } 

    public SlidingTabLayout(Context context, AttributeSet attrs) { 
     this(context, attrs, 0); 
    } 

    public SlidingTabLayout(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 

     // Disable the Scroll Bar 
     setHorizontalScrollBarEnabled(false); 
     // Make sure that the Tab Strips fills this View 
     setFillViewport(true); 

     mTitleOffset = (int) (TITLE_OFFSET_DIPS * getResources().getDisplayMetrics().density); 

     mTabStrip = new SlidingTabStrip(context); 
     addView(mTabStrip, LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); 
    } 


    public void hideTab(int tabIndex){ 
     for (int i = 0; i < mTabStrip.getChildCount(); i++) { 
      if(i == tabIndex){ 
       ((TextView)mTabStrip.getChildAt(i)).setVisibility(GONE); 
      } 
     } 


    } 

    /** 
    * Set the custom {@link TabColorizer} to be used. 
    * 
    * If you only require simple custmisation then you can use 
    * {@link #setSelectedIndicatorColors(int...)} to achieve 
    * similar effects. 
    */ 
    public void setCustomTabColorizer(TabColorizer tabColorizer) { 
     mTabStrip.setCustomTabColorizer(tabColorizer); 
    } 

    public void setDistributeEvenly(boolean distributeEvenly) { 
     mDistributeEvenly = distributeEvenly; 
    } 

    /** 
    * Sets the colors to be used for indicating the selected tab. These colors are treated as a 
    * circular array. Providing one color will mean that all tabs are indicated with the same color. 
    */ 
    public void setSelectedIndicatorColors(int... colors) { 
     mTabStrip.setSelectedIndicatorColors(colors); 
    } 

    /** 
    * Set the {@link ViewPager.OnPageChangeListener}. When using {@link SlidingTabLayout} you are 
    * required to set any {@link ViewPager.OnPageChangeListener} through this method. This is so 
    * that the layout can update it's scroll position correctly. 
    * 
    * @see ViewPager#setOnPageChangeListener(ViewPager.OnPageChangeListener) 
    */ 
    public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) { 
     mViewPagerPageChangeListener = listener; 
    } 

    /** 
    * Set the custom layout to be inflated for the tab views. 
    * 
    * @param layoutResId Layout id to be inflated 
    * @param textViewId id of the {@link TextView} in the inflated view 
    */ 
    public void setCustomTabView(int layoutResId, int textViewId) { 
     mTabViewLayoutId = layoutResId; 
     mTabViewTextViewId = textViewId; 
    } 

    /** 
    * Sets the associated view pager. Note that the assumption here is that the pager content 
    * (number of tabs and tab titles) does not change after this call has been made. 
    */ 
    public void setViewPager(ViewPager viewPager) { 
     mTabStrip.removeAllViews(); 

     mViewPager = viewPager; 
     if (viewPager != null) { 
      viewPager.setOnPageChangeListener(new InternalViewPagerListener()); 
      populateTabStrip(); 
     } 
    } 

    /** 
    * Create a default view to be used for tabs. This is called if a custom tab view is not set via 
    * {@link #setCustomTabView(int, int)}. 
    */ 
    protected TextView createDefaultTabView(Context context) { 
     TextView textView = new TextView(context); 
     textView.setGravity(Gravity.CENTER); 
     textView.setTextSize(16); 
     textView.setTypeface(Constants.TYPE_FACE_FONT_MEDIUM); 
     textView.setLayoutParams(new LinearLayout.LayoutParams(
       ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); 

     TypedValue outValue = new TypedValue(); 
     getContext().getTheme().resolveAttribute(android.R.attr.selectableItemBackground, 
       outValue, true); 
     textView.setBackgroundResource(outValue.resourceId); 
     if(Constants.PRODUCT_DETAILS_TAB_BAR_STYLE == 2) { 
      textView.setBackgroundColor(getResources().getColor(R.color.tab_bar_color)); 
      mTabStrip.setBackgroundColor(getResources().getColor(R.color.tab_bar_color)); 
     } 

     textView.setAllCaps(true); 

     int padding = (int) (TAB_VIEW_PADDING_DIPS * getResources().getDisplayMetrics().density); 
     textView.setPadding(padding, padding, padding, padding); 

     return textView; 
    } 

    private void populateTabStrip() { 
     removeOldSelection(); 
     oldSelection = null; 
     final PagerAdapter adapter = mViewPager.getAdapter(); 
     final View.OnClickListener tabClickListener = new TabClickListener(); 

     for (int i = 0; i < adapter.getCount(); i++) { 
      View tabView = null; 
      TextView tabTitleView = null; 

      if (mTabViewLayoutId != 0) { 
       // If there is a custom tab view layout id set, try and inflate it 
       tabView = LayoutInflater.from(getContext()).inflate(mTabViewLayoutId, mTabStrip, 
         false); 
       tabTitleView = (TextView) tabView.findViewById(mTabViewTextViewId); 
      } 

      if (tabView == null) { 
       tabView = createDefaultTabView(getContext()); 
      } 

      if (tabTitleView == null && TextView.class.isInstance(tabView)) { 
       tabTitleView = (TextView) tabView; 
      } 

      if (mDistributeEvenly) { 
       LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) tabView.getLayoutParams(); 
       lp.width = 0; 
       lp.weight = 1; 
      } 

      tabTitleView.setText(adapter.getPageTitle(i)); 

      tabView.setOnClickListener(tabClickListener); 
      String desc = mContentDescriptions.get(i, null); 
      if (desc != null) { 
       tabView.setContentDescription(desc); 
      } 

      mTabStrip.addView(tabView); 
      if(Constants.PRODUCT_DETAILS_TAB_BAR_STYLE == 1) 
       tabTitleView.setTextColor(getResources().getColorStateList(R.color.primary_ultralight)); 
      else 
       tabTitleView.setTextColor(getResources().getColor(R.color.primary_text)); 
      if (i == mViewPager.getCurrentItem()) { 
       tabView.setSelected(true); 
       tabTitleView.setTextColor(getResources().getColorStateList(R.color.primary_ultralight)); 
      } 

     } 

    } 

    public void setContentDescription(int i, String desc) { 
     mContentDescriptions.put(i, desc); 
    } 

    @Override 
    protected void onAttachedToWindow() { 
     super.onAttachedToWindow(); 

     if (mViewPager != null) { 
      scrollToTab(mViewPager.getCurrentItem(), 0); 
     } 
    } 

    private void scrollToTab(int tabIndex, int positionOffset) { 
     final int tabStripChildCount = mTabStrip.getChildCount(); 
     if (tabStripChildCount == 0 || tabIndex < 0 || tabIndex >= tabStripChildCount) { 
      return; 
     } 

     View selectedChild = mTabStrip.getChildAt(tabIndex); 
     if (selectedChild != null) { 

      if(positionOffset == 0 && selectedChild != oldSelection) { // added part 
       selectedChild.setSelected(true); 
       removeOldSelection(); 
       oldSelection = selectedChild; 
      } 

      int targetScrollX = selectedChild.getLeft() + positionOffset; 

      if (tabIndex > 0 || positionOffset > 0) { 
       // If we're not at the first child and are mid-scroll, make sure we obey the offset 
       targetScrollX -= mTitleOffset; 
      } 

      scrollTo(targetScrollX, 0); 
     } 
    } 

    private class InternalViewPagerListener implements ViewPager.OnPageChangeListener { 
     private int mScrollState; 

     @Override 
     public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 
      int tabStripChildCount = mTabStrip.getChildCount(); 
      if ((tabStripChildCount == 0) || (position < 0) || (position >= tabStripChildCount)) { 
       return; 
      } 

      mTabStrip.onViewPagerPageChanged(position, positionOffset); 

      View selectedTitle = mTabStrip.getChildAt(position); 
      int extraOffset = (selectedTitle != null) 
        ? (int) (positionOffset * selectedTitle.getWidth()) 
        : 0; 
      scrollToTab(position, extraOffset); 

      if (mViewPagerPageChangeListener != null) { 
       mViewPagerPageChangeListener.onPageScrolled(position, positionOffset, 
         positionOffsetPixels); 
      } 
     } 

     @Override 
     public void onPageScrollStateChanged(int state) { 
      mScrollState = state; 

      if (mViewPagerPageChangeListener != null) { 
       mViewPagerPageChangeListener.onPageScrollStateChanged(state); 
      } 
     } 

     @Override 
     public void onPageSelected(int position) { 
      if (mScrollState == ViewPager.SCROLL_STATE_IDLE) { 
       mTabStrip.onViewPagerPageChanged(position, 0f); 
       scrollToTab(position, 0); 
      } 
      for (int i = 0; i < mTabStrip.getChildCount(); i++) { 
       mTabStrip.getChildAt(i).setSelected(position == i); 

       if(Constants.PRODUCT_DETAILS_TAB_BAR_STYLE == 2){ 
        if(position == i) 
         ((TextView)mTabStrip.getChildAt(i)).setTextColor(getResources().getColorStateList(R.color.primary_ultralight)); 
        else 
         ((TextView)mTabStrip.getChildAt(i)).setTextColor(getResources().getColor(R.color.primary_text)); 
       } 




      } 
      if (mViewPagerPageChangeListener != null) { 
       mViewPagerPageChangeListener.onPageSelected(position); 
      } 
     } 

    } 
    private void removeOldSelection() { 
     if(oldSelection != null) { 
      oldSelection.setSelected(false); 
     } 
    } 
    private class TabClickListener implements View.OnClickListener { 
     @Override 
     public void onClick(View v) { 
      for (int i = 0; i < mTabStrip.getChildCount(); i++) { 
       if (v == mTabStrip.getChildAt(i)) { 
        mViewPager.setCurrentItem(i); 
        return; 
       } 
      } 
     } 
    } 

} 

SlidingTabStrip:

class SlidingTabStrip extends LinearLayout { 

    private static final int DEFAULT_BOTTOM_BORDER_THICKNESS_DIPS = 0; 
    private static final byte DEFAULT_BOTTOM_BORDER_COLOR_ALPHA = 0x26; 
    private static final int SELECTED_INDICATOR_THICKNESS_DIPS = 3; 
    private static final int DEFAULT_SELECTED_INDICATOR_COLOR = 0xFF33B5E5; 

    private final int mBottomBorderThickness; 
    private final Paint mBottomBorderPaint; 

    private final int mSelectedIndicatorThickness; 
    private final Paint mSelectedIndicatorPaint; 

    private final int mDefaultBottomBorderColor; 

    private int mSelectedPosition; 
    private float mSelectionOffset; 

    private SlidingTabLayout.TabColorizer mCustomTabColorizer; 
    private final SimpleTabColorizer mDefaultTabColorizer; 

    SlidingTabStrip(Context context) { 
     this(context, null); 
    } 

    SlidingTabStrip(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     setWillNotDraw(false); 

     final float density = getResources().getDisplayMetrics().density; 

     TypedValue outValue = new TypedValue(); 
     context.getTheme().resolveAttribute(android.R.attr.colorForeground, outValue, true); 
     final int themeForegroundColor = outValue.data; 

     mDefaultBottomBorderColor = setColorAlpha(themeForegroundColor, 
       DEFAULT_BOTTOM_BORDER_COLOR_ALPHA); 

     mDefaultTabColorizer = new SimpleTabColorizer(); 
     mDefaultTabColorizer.setIndicatorColors(DEFAULT_SELECTED_INDICATOR_COLOR); 

     mBottomBorderThickness = (int) (DEFAULT_BOTTOM_BORDER_THICKNESS_DIPS * density); 
     mBottomBorderPaint = new Paint(); 
     mBottomBorderPaint.setColor(mDefaultBottomBorderColor); 

     mSelectedIndicatorThickness = (int) (SELECTED_INDICATOR_THICKNESS_DIPS * density); 
     mSelectedIndicatorPaint = new Paint(); 
    } 

    void setCustomTabColorizer(SlidingTabLayout.TabColorizer customTabColorizer) { 
     mCustomTabColorizer = customTabColorizer; 
     invalidate(); 
    } 

    void setSelectedIndicatorColors(int... colors) { 
     // Make sure that the custom colorizer is removed 
     mCustomTabColorizer = null; 
     mDefaultTabColorizer.setIndicatorColors(colors); 
     invalidate(); 
    } 

    void onViewPagerPageChanged(int position, float positionOffset) { 
     mSelectedPosition = position; 
     mSelectionOffset = positionOffset; 
     invalidate(); 
    } 

    @Override 
    protected void onDraw(Canvas canvas) { 
     final int height = getHeight(); 
     final int childCount = getChildCount(); 
     final SlidingTabLayout.TabColorizer tabColorizer = mCustomTabColorizer != null 
       ? mCustomTabColorizer 
       : mDefaultTabColorizer; 

     // Thick colored underline below the current selection 
     if (childCount > 0) { 
      View selectedTitle = getChildAt(mSelectedPosition); 
      int left = selectedTitle.getLeft(); 
      int right = selectedTitle.getRight(); 
      int color = tabColorizer.getIndicatorColor(mSelectedPosition); 

      if (mSelectionOffset > 0f && mSelectedPosition < (getChildCount() - 1)) { 
       int nextColor = tabColorizer.getIndicatorColor(mSelectedPosition + 1); 
       if (color != nextColor) { 
        color = blendColors(nextColor, color, mSelectionOffset); 
       } 

       // Draw the selection partway between the tabs 
       View nextTitle = getChildAt(mSelectedPosition + 1); 
       left = (int) (mSelectionOffset * nextTitle.getLeft() + 
         (1.0f - mSelectionOffset) * left); 
       right = (int) (mSelectionOffset * nextTitle.getRight() + 
         (1.0f - mSelectionOffset) * right); 
      } 

      mSelectedIndicatorPaint.setColor(color); 

      canvas.drawRect(left, height - mSelectedIndicatorThickness, right, 
        height, mSelectedIndicatorPaint); 
     } 

     // Thin underline along the entire bottom edge 
     canvas.drawRect(0, height - mBottomBorderThickness, getWidth(), height, mBottomBorderPaint); 
    } 

    /** 
    * Set the alpha value of the {@code color} to be the given {@code alpha} value. 
    */ 
    private static int setColorAlpha(int color, byte alpha) { 
     return Color.argb(alpha, Color.red(color), Color.green(color), Color.blue(color)); 
    } 

    /** 
    * Blend {@code color1} and {@code color2} using the given ratio. 
    * 
    * @param ratio of which to blend. 1.0 will return {@code color1}, 0.5 will give an even blend, 
    *    0.0 will return {@code color2}. 
    */ 
    private static int blendColors(int color1, int color2, float ratio) { 
     final float inverseRation = 1f - ratio; 
     float r = (Color.red(color1) * ratio) + (Color.red(color2) * inverseRation); 
     float g = (Color.green(color1) * ratio) + (Color.green(color2) * inverseRation); 
     float b = (Color.blue(color1) * ratio) + (Color.blue(color2) * inverseRation); 
     return Color.rgb((int) r, (int) g, (int) b); 
    } 

    private static class SimpleTabColorizer implements SlidingTabLayout.TabColorizer { 
     private int[] mIndicatorColors; 

     @Override 
     public final int getIndicatorColor(int position) { 
      return mIndicatorColors[position % mIndicatorColors.length]; 
     } 

     void setIndicatorColors(int... colors) { 
      mIndicatorColors = colors; 
     } 
    } 
} 

以及如何使用:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:background="@color/layouts_background" 
    android:layout_height="match_parent"> 

     <LinearLayout 
      android:layout_width="match_parent" 
      android:layout_height="match_parent" 
      android:orientation="vertical"> 
      <RelativeLayout 
       android:id="@+id/page_root_container" 
       android:layout_width="match_parent" 
       android:layout_height="match_parent" 
       android:orientation="vertical"> 
       <include 
        android:id="@+id/app_bar" 
        layout="@layout/app_bar"/> 
       <LinearLayout 
        android:layout_width="match_parent" 
        android:layout_height="match_parent" 
        android:layout_below="@+id/app_bar" 
        android:orientation="vertical"> 
        <com.app.myapp.tab.SlidingTabLayout 
         android:id="@+id/detailsTabs" 
         android:layout_width="match_parent" 
         android:layout_height="wrap_content"> 

        </com.app.myapp.tab.SlidingTabLayout> 
        <android.support.v4.view.ViewPager 
         android:id="@+id/detailsPager" 
         android:layout_width="match_parent" 
         android:layout_height="0dp" 
         android:layout_weight="1"> 
        </android.support.v4.view.ViewPager> 
       </LinearLayout> 
      </RelativeLayout> 
     </LinearLayout> 
</RelativeLayout> 

工具欄爲appbar:

<?xml version="1.0" encoding="utf-8"?> 
<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:app="http://schemas.android.com/apk/res-auto" 
    android:layout_width="match_parent" 
    android:layout_height="?android:attr/actionBarSize" 
    android:background="@color/primary" 
    app:theme="@style/CustomToolbarTheme"> 


</android.support.v7.widget.Toolbar> 

在活動時間:

class DetailsTabsAdaptor extends FragmentPagerAdapter { 
     String [] tabsTitlesPrepare = {getString(R.string.details),getString(R.string.features), getString(R.string.spects), getString(R.string.downloads)}; 
     List<String> tabsTitles = new ArrayList<>(); 
     int tabsCount = 0; 
     boolean featuresExist = false; 
     boolean specificationsExist = false; 
     boolean downloadsExist = false; 

     public DetailsTabsAdaptor(FragmentManager fm) { 
      super(fm); 
      tabsTitles.add(tabsTitlesPrepare[0]); 
      tabsCount++; 
      if ((mProductDetails.ProductStructure.Features != null && mProductDetails.ProductStructure.Features.size()>0)) { 
       tabsTitles.add(tabsTitlesPrepare[1]); 
       featuresExist = true; 
       tabsCount++; 
      } 
      if ((mProductDetails.ProductStructure.SpecificationBlocks != null && mProductDetails.ProductStructure.SpecificationBlocks.size()>0)) { 
       tabsTitles.add(tabsTitlesPrepare[2]); 
       specificationsExist = true; 
       tabsCount++; 
      } 
      if ((mProductDetails.ProductStructure.SupportFiles != null && mProductDetails.ProductStructure.SupportFiles.size()>0)) { 
       tabsTitles.add(tabsTitlesPrepare[3]); 
       downloadsExist = true; 
       tabsCount++; 
      } 

     } 

     @Override 
     public CharSequence getPageTitle(int position) { 
      return tabsTitles.get(position); 
     } 

     @Override 
     public Fragment getItem(int position) { 
      if(position == 0){ 
       ProductDetailsFragment fragment = new ProductDetailsFragment(); 
       return fragment; 
      } 
      if(position == 1 && featuresExist){ 
       ProductFeaturesFragment fragment = new ProductFeaturesFragment(); 
       return fragment; 
      } 
      if((position == 2 && specificationsExist) || (position == 1 && (!featuresExist) && specificationsExist)){ 
       ProductSpectsFragment fragment = new ProductSpectsFragment(); 
       return fragment; 
      } 
      if((position == 3 && downloadsExist) || (position == 1 && (!featuresExist) && (!specificationsExist) && downloadsExist) || 
        (position == 2 && (!specificationsExist) && downloadsExist)){ 
       ProductDownloadsFragment fragment = new ProductDownloadsFragment(); 
       return fragment; 
      } 

      return null; 
     } 

     @Override 
     public int getCount() { 
      return tabsCount; 
     } 
    } 

而設置選項卡

public void setupTabs() { 
     mDetailsPager.setAdapter(new DetailsTabsAdaptor(getSupportFragmentManager())); 
     mDetailsTabs.setViewPager(mDetailsPager); 
     mDetailsTabs.setBackgroundResource(R.color.primary); 
     mDetailsTabs.setCustomTabView(R.layout.custom_details_view_tab_layout, R.id.tabText); 
     mDetailsTabs.setCustomTabColorizer(new SlidingTabLayout.TabColorizer() { 
      @Override 
      public int getIndicatorColor(int position) { 
       return getResources().getColor(R.color.primary_light); 
      } 
     }); 


     mDetailsTabs.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { 
      @Override 
      public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 
      } 

      @Override 
      public void onPageSelected(int position) { 

       for (int i = 0; i < mDetailsTabs.getChildCount(); i++) 
        mDetailsTabs.getChildAt(i).setSelected(i == position); 
       if (position == DESCRIPTION_PAGE_ID) 
        mFavoritesButton.setVisibility(View.VISIBLE); 
       else 
        mFavoritesButton.setVisibility(View.GONE); 

      } 

      @Override 
      public void onPageScrollStateChanged(int state) { 
      } 
     }); 

    } 

custom_details_view_tab_layout:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="vertical" 
    android:layout_width="match_parent" 
    android:background="@color/primary" 
    android:layout_height="match_parent"> 
    <com.avad.avaddroid.customModels.TextViewMedium 
     android:id="@+id/tabText" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:textColor="@color/primary_light" 
     android:layout_gravity="center"/> 

</LinearLayout> 

最後說明:這裏沒有貼初始化所有變量的,不要偷懶去嘗試學習一項位;)

1

請設置viewPager.setOffscreenPageLimit(1); to viewPager.setOffscreenPageLimit(5);

5

更改這條線在你的活動:

ViewPagerAdapter adapter = new ViewPagerAdapter(getChildFragmentManager()); 
2

如果您打算在片段中創建TabLayout然後用getChildFragmentManager()代替getSupportFragmentManager()作爲參數。

ViewPagerAdapter adapter = new ViewPagerAdapter(getChildFragmentManager());