Created
November 17, 2016 17:22
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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