Skip to content

Commit 2fc2e6a

Browse files
pekingmeraajkumars
authored andcommittedJun 23, 2022
[Tab] Fixed indicator not updating when a tab to the start/left of the selected tab is removed.
PiperOrigin-RevId: 456322731
1 parent cab45dd commit 2fc2e6a

File tree

4 files changed

+39
-41
lines changed

4 files changed

+39
-41
lines changed
 

‎catalog/java/io/material/catalog/tabs/TabsScrollableDemoFragment.java

+14-3
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
import io.material.catalog.R;
2020

21+
import static java.lang.Math.max;
22+
2123
import android.os.Bundle;
2224
import android.view.LayoutInflater;
2325
import android.view.View;
@@ -87,14 +89,23 @@ public View onCreateDemoView(
8789
numTabs++;
8890
});
8991

90-
Button removeButton = view.findViewById(R.id.remove_tab_button);
91-
removeButton.setOnClickListener(
92+
Button removeFirstButton = view.findViewById(R.id.remove_first_tab_button);
93+
removeFirstButton.setOnClickListener(
94+
v -> {
95+
if (scrollableTabLayout.getTabCount() > 0) {
96+
scrollableTabLayout.removeTabAt(0);
97+
}
98+
numTabs = max(0, numTabs - 1);
99+
});
100+
101+
Button removeLastButton = view.findViewById(R.id.remove_last_tab_button);
102+
removeLastButton.setOnClickListener(
92103
v -> {
93104
Tab tab = scrollableTabLayout.getTabAt(scrollableTabLayout.getTabCount() - 1);
94105
if (tab != null) {
95106
scrollableTabLayout.removeTab(tab);
96107
}
97-
numTabs = Math.max(0, numTabs - 1);
108+
numTabs = max(0, numTabs - 1);
98109
});
99110
return view;
100111
}

‎catalog/java/io/material/catalog/tabs/res/layout/cat_tabs_scrollable_fragment.xml

+12-4
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,14 @@
3232
android:layout_marginBottom="@dimen/cat_tabs_standard_spacing"
3333
android:orientation="vertical">
3434

35+
<Button
36+
android:id="@+id/add_tab_button"
37+
android:layout_width="wrap_content"
38+
android:layout_height="wrap_content"
39+
android:layout_marginEnd="@dimen/cat_tabs_small_spacing"
40+
android:layout_marginRight="@dimen/cat_tabs_small_spacing"
41+
android:text="@string/cat_tabs_add_tab_button_label" />
42+
3543
<LinearLayout
3644
android:layout_width="wrap_content"
3745
android:layout_height="wrap_content"
@@ -40,17 +48,17 @@
4048
android:orientation="horizontal"
4149
tools:ignore="ButtonStyle">
4250
<Button
43-
android:id="@+id/add_tab_button"
51+
android:id="@+id/remove_first_tab_button"
4452
android:layout_width="wrap_content"
4553
android:layout_height="wrap_content"
4654
android:layout_marginEnd="@dimen/cat_tabs_small_spacing"
4755
android:layout_marginRight="@dimen/cat_tabs_small_spacing"
48-
android:text="@string/cat_tabs_add_tab_button_label" />
56+
android:text="@string/cat_tabs_remove_first_tab_button_label" />
4957
<Button
50-
android:id="@+id/remove_tab_button"
58+
android:id="@+id/remove_last_tab_button"
5159
android:layout_width="wrap_content"
5260
android:layout_height="wrap_content"
53-
android:text="@string/cat_tabs_remove_tab_button_label" />
61+
android:text="@string/cat_tabs_remove_last_tab_button_label" />
5462
</LinearLayout>
5563

5664

‎catalog/java/io/material/catalog/tabs/res/values/strings.xml

+2
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@
4545
<string name="cat_tabs_secondary_tabs_label">Material Tabs (Secondary)</string>
4646
<string name="cat_tabs_add_tab_button_label">Add Tab</string>
4747
<string name="cat_tabs_remove_tab_button_label">Remove Tab</string>
48+
<string name="cat_tabs_remove_first_tab_button_label">Remove First Tab</string>
49+
<string name="cat_tabs_remove_last_tab_button_label">Remove Last Tab</string>
4850
<string name="cat_tabs_controllable_demo_title">Controllable Tabs Demo</string>
4951
<string name="cat_tabs_scrollable_demo_title">Scrollable Tabs Demo</string>
5052
<string name="cat_tabs_auto_demo_title">Auto Tabs Demo</string>

‎lib/java/com/google/android/material/tabs/TabLayout.java

+11-34
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@
2525
import static com.google.android.material.animation.AnimationUtils.FAST_OUT_SLOW_IN_INTERPOLATOR;
2626
import static com.google.android.material.theme.overlay.MaterialThemeOverlay.wrap;
2727

28-
import android.animation.Animator;
29-
import android.animation.AnimatorListenerAdapter;
3028
import android.animation.ValueAnimator;
3129
import android.annotation.SuppressLint;
3230
import android.content.Context;
@@ -3007,10 +3005,6 @@ private float approximateLineWidth(@NonNull Layout layout, int line, float textS
30073005

30083006
class SlidingTabIndicator extends LinearLayout {
30093007
ValueAnimator indicatorAnimator;
3010-
int selectedPosition = -1;
3011-
// selectionOffset is only used when a tab is being slid due to a viewpager swipe.
3012-
// selectionOffset is always the offset to the right of selectedPosition.
3013-
float selectionOffset;
30143008

30153009
private int layoutDirection = -1;
30163010

@@ -3038,26 +3032,21 @@ boolean childrenNeedLayout() {
30383032
/**
30393033
* Set the indicator position based on an offset between two adjacent tabs.
30403034
*
3041-
* @param position The position from which the offset should be calculated.
3042-
* @param positionOffset The offset to the right of position where the indicator should be
3043-
* drawn. This must be a value between 0.0 and 1.0.
3035+
* @param position Position index of the first tab (with less index) currently being displayed.
3036+
* Tab position+1 will be visible if positionOffset is nonzero.
3037+
* @param positionOffset Value from [0, 1) indicating the offset from the tab at position.
30443038
*/
30453039
void setIndicatorPositionFromTabPosition(int position, float positionOffset) {
30463040
if (indicatorAnimator != null && indicatorAnimator.isRunning()) {
30473041
indicatorAnimator.cancel();
30483042
}
30493043

3050-
selectedPosition = position;
3051-
selectionOffset = positionOffset;
3044+
// The title view refers to the one indicated when offset is 0.
3045+
final View firstTitle = getChildAt(position);
3046+
// The title view refers to the one indicated when offset is 1.
3047+
final View nextTitle = getChildAt(position + 1);
30523048

3053-
final View selectedTitle = getChildAt(selectedPosition);
3054-
final View nextTitle = getChildAt(selectedPosition + 1);
3055-
3056-
tweenIndicatorPosition(selectedTitle, nextTitle, selectionOffset);
3057-
}
3058-
3059-
float getIndicatorPosition() {
3060-
return selectedPosition + selectionOffset;
3049+
tweenIndicatorPosition(firstTitle, nextTitle, positionOffset);
30613050
}
30623051

30633052
@Override
@@ -3144,7 +3133,7 @@ protected void onLayout(boolean changed, int l, int t, int r, int b) {
31443133
// position of the indicator, since the tab widths are different. We need to modify the
31453134
// animation's updateListener to pick up the new target positions.
31463135
updateOrRecreateIndicatorAnimation(
3147-
/* recreateAnimation= */ false, selectedPosition, /* duration= */ -1);
3136+
/* recreateAnimation= */ false, getSelectedTabPosition(), /* duration= */ -1);
31483137
} else {
31493138
// If we've been laid out, update the indicator position
31503139
jumpIndicatorToSelectedPosition();
@@ -3153,7 +3142,7 @@ protected void onLayout(boolean changed, int l, int t, int r, int b) {
31533142

31543143
/** Immediately update the indicator position to the currently selected position. */
31553144
private void jumpIndicatorToSelectedPosition() {
3156-
final View currentView = getChildAt(selectedPosition);
3145+
final View currentView = getChildAt(getSelectedTabPosition());
31573146
tabIndicatorInterpolator.setIndicatorBoundsForTab(
31583147
TabLayout.this, currentView, tabSelectedIndicator);
31593148
}
@@ -3214,7 +3203,7 @@ void animateIndicatorToPosition(final int position, int duration) {
32143203
*/
32153204
private void updateOrRecreateIndicatorAnimation(
32163205
boolean recreateAnimation, final int position, int duration) {
3217-
final View currentView = getChildAt(selectedPosition);
3206+
final View currentView = getChildAt(getSelectedTabPosition());
32183207
final View targetView = getChildAt(position);
32193208
if (targetView == null) {
32203209
// If we don't have a view, just update the position now and return
@@ -3239,18 +3228,6 @@ public void onAnimationUpdate(@NonNull ValueAnimator valueAnimator) {
32393228
animator.setDuration(duration);
32403229
animator.setFloatValues(0F, 1F);
32413230
animator.addUpdateListener(updateListener);
3242-
animator.addListener(
3243-
new AnimatorListenerAdapter() {
3244-
@Override
3245-
public void onAnimationStart(Animator animator) {
3246-
selectedPosition = position;
3247-
}
3248-
3249-
@Override
3250-
public void onAnimationEnd(Animator animator) {
3251-
selectedPosition = position;
3252-
}
3253-
});
32543231
animator.start();
32553232
} else {
32563233
// Reuse the existing animator. Updating the listener only modifies the target positions.

0 commit comments

Comments
 (0)
Please sign in to comment.