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.
Alguna solución?
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
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());
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í .
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());
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);
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)
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);
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"
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;)
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