Skip to content

Instantly share code, notes, and snippets.

@Shyri
Created November 17, 2016 17:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Shyri/be70ceb101c98b3d457f7ff43b7f1c40 to your computer and use it in GitHub Desktop.
Save Shyri/be70ceb101c98b3d457f7ff43b7f1c40 to your computer and use it in GitHub Desktop.
This class aims to solve a known issue with TabLayout when setting RTL layout direction, the scroll animation goes the opposite direction than it should
/*
* Copyright 2016 Shyri Villar
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
/**
* This class aims to solve a known issue with TabLayout when setting RTL layout direction.
* This workaround overrides {@link TabLayout#scrollTo(int, int)} in order to undo
* what {@link TabLayout#calculateScrollXForTab} does to x coordinates and do same calculations but for the
* opposite direction before performing the scroll.
*
* You can use this in conjunction with RTL supported ViewPager modified by Konstantin Loginov
* https://github.com/ksloginov/RtlViewPager
*/
public class TabLayoutRTLSupported extends TabLayout {
int selectedPosition;
public TabLayoutRTLSupported(Context context) {
super(context);
}
public TabLayoutRTLSupported(Context context, AttributeSet attrs) {
super(context, attrs);
}
public TabLayoutRTLSupported(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public void scrollTo(int x, int y) {
final boolean isRtl = ViewCompat.getLayoutDirection(this) == ViewCompat.LAYOUT_DIRECTION_RTL;
if (isRtl) {
x = recalculateX(x);
}
super.scrollTo(x, y);
}
public void setupWithViewPager(@Nullable final ViewPager viewPager, boolean autoRefresh) {
// We need to add our own page change listener before parent does so we are notified of selected position when
// page is scrolled before him.
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
selectedPosition = position;
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
super.setupWithViewPager(viewPager, autoRefresh);
}
/**
* This method reverts the calculation done by {@link TabLayout#calculateScrollXForTab} before applying scrollTo
*
* @param x
*
* @return
*/
private int recalculateX(int x) {
try {
ViewGroup mTabStrip = null;
for (int i = 0; i < getChildCount(); i++) {
// We have to get SlidingTabStrip like this because class is not public and we have to make sure this is
// the one we get
if ("android.support.design.widget.TabLayout.SlidingTabStrip".equals(getChildAt(i).getClass()
.getCanonicalName())) {
mTabStrip = (ViewGroup) getChildAt(i);
}
}
// First we have to undo the conversion done by parent before reaching this point
View selectedChild = mTabStrip.getChildAt(selectedPosition);
View nextChild =
selectedPosition + 1 < mTabStrip.getChildCount() ? mTabStrip.getChildAt(selectedPosition + 1) : null;
int selectedWidth = selectedChild != null ? selectedChild.getWidth() : 0;
int nextWidth = nextChild != null ? nextChild.getWidth() : 0;
// Original value will hold value of (positionOffset * 0.5f) which we need in order do the new calculation
float originalValue = x;
originalValue = originalValue - selectedChild.getLeft();
originalValue = originalValue - selectedChild.getWidth() / 2;
originalValue = originalValue + getWidth() / 2;
originalValue = originalValue / (selectedWidth + nextWidth);
nextChild = selectedPosition - 1 < mTabStrip.getChildCount() ? mTabStrip.getChildAt(selectedPosition - 1) : null;
selectedWidth = selectedChild != null ? selectedChild.getWidth() : 0;
nextWidth = nextChild != null ? nextChild.getWidth() : 0;
return selectedChild.getRight() - (int) (originalValue * (selectedWidth + nextWidth)) -
(selectedChild.getWidth() / 2) - (getWidth() / 2);
} catch (Exception e) {
// Somthing went wrong, better to keep things as they were
}
return x;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment