TabLayout con viewpager desplazamiento no suave


Editar

He seguido estos tutoriales para solucionar este problema.

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/

Pero es molesto que el problema aún persiste después de probar varias soluciones. Aquí está la demostración para el problema i estoy mirando.Han pasado semanas desde que estoy atascado en este problema.

Link para demo.

Los dispositivos que estoy usando para las pruebas son Nexus 4 y Nexus 5.

TabLayout con ViewPager no se desplaza suavemente. Necesito deslizar dos veces para cambiar en el siguiente toque. He mirado alrededor de la tela pero no pude encontrar ninguna solución. Estoy utilizando la última biblioteca de diseño de soporte. Aquí está gradle file

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'
}

Aquí está el código de actividad.

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;
    }
}

Y xml file

<?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>

Aquí está la captura de pantalla que puede ver que el indicador está parcialmente dividido.

introduzca la descripción de la imagen aquí

Alguna solución?

Author: Zeeshan Shabbir, 2016-05-16

9 answers

Acabo de revisar tu código. El problema es que no está proporcionando ningún diseño para inflar dentro de ContentFragment.Java.

Cambié tu método a

    @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);

    }

Después de hacer estos cambios, sus pestañas se desplazaban sin problemas. No conozco la razón detrás de este comportamiento, pero esta cosa lo hizo funcionar

 27
Author: Ankit Aggarwal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-30 09:26:52

Cambie esta línea en su Actividad:

ViewPagerAdapter adapter = new ViewPagerAdapter(getChildFragmentManager());
 7
Author: Hamed Nabizadeh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-02 01:59:07

Creo que necesitas usar el método override setUserVisibleHint.

Necesitas agregar esto en tu Fragment.

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

Haga su offScreenPageLimit al NÚMERO DE PESTAÑAS que tiene.

Leer más sobre setUserVisibleHint aquí .

 2
Author: Jay Rathod RJ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-18 12:40:53

Si va a crear TabLayout dentro de a fragments, use getChildFragmentManager() en lugar de getSupportFragmentManager() como parámetro.

ViewPagerAdapter adapter = new ViewPagerAdapter(getChildFragmentManager());
 2
Author: Arihant Jain,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-01 10:49:56

Habilite todas las políticas StrictMode en su aplicación para detectar cualquier operación larga que pueda estar realizando inadvertidamente en el subproceso principal, causando el retraso, para que pueda tomar las medidas correctivas necesarias.

StrictMode es una herramienta de desarrollo que detecta cosas que podría estar haciendo por accidente y las llama la atención para que pueda solucionarlas. StrictMode se usa más comúnmente para capturar el acceso accidental al disco o a la red en el subproceso principal de la aplicación, donde la interfaz de usuario se reciben operaciones y se realizan animaciones.

Véase https://developer.android.com/reference/android/os/StrictMode.html para más detalles.

    // 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);
 1
Author: Chebyr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-18 12:25:26

Esto no es nada nuevo con el diseño de coordenadas de Android y el diseño de AppBar; estoy seguro de que no podrás hacerlo más suave sin importar lo que hagas. Sin embargo

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

Esto podría cumplir con sus requisitos; Sin embargo, en primer lugar descargar la aplicación de ejemplo de

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

Para ver si se ajusta a su necesidad.(solo para estar seguro)

 1
Author: DEEPANKUR SADANA,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-18 19:36:13

Por Favor, Establezca ViewPager.setOffscreenPageLimit (1); para ViewPager.setOffscreenPageLimit (5);

 1
Author: Aditay Kaushal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-25 10:39:37

En tu archivo de manifiesto de Android agrega esta línea en <Application> etiqueta

 android:largeHeap="true" 
 0
Author: Krupa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-18 14:20:13

En primer lugar, para hacer que todo sea suave, no hagas operaciones pesadas en el hilo principal, usa tareas asíncronas (no toques las vistas en la tarea asíncrona), y todo será suave de todos modos:)

Prueba mi manera de hacer esto:

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;
        }
    }
}

Y cómo usarlo:

<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>

Barra de herramientas como 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>

En Actividad:

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;
        }
    }

Y Pestañas De Configuración

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>

Notas Finales: no publicado aquí init de todas las variables, no seas perezoso tratar de aprender un poco;)

 0
Author: Stepan Maksymov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-25 01:26:21