Skip to content

Commit

Permalink
[Tab] Fixed indicator not updating when a tab to the start/left of th…
Browse files Browse the repository at this point in the history
…e selected tab is removed.

PiperOrigin-RevId: 456322731
  • Loading branch information
pekingme authored and raajkumars committed Jun 23, 2022
1 parent cab45dd commit 2fc2e6a
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 41 deletions.
Expand Up @@ -18,6 +18,8 @@

import io.material.catalog.R;

import static java.lang.Math.max;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
Expand Down Expand Up @@ -87,14 +89,23 @@ public View onCreateDemoView(
numTabs++;
});

Button removeButton = view.findViewById(R.id.remove_tab_button);
removeButton.setOnClickListener(
Button removeFirstButton = view.findViewById(R.id.remove_first_tab_button);
removeFirstButton.setOnClickListener(
v -> {
if (scrollableTabLayout.getTabCount() > 0) {
scrollableTabLayout.removeTabAt(0);
}
numTabs = max(0, numTabs - 1);
});

Button removeLastButton = view.findViewById(R.id.remove_last_tab_button);
removeLastButton.setOnClickListener(
v -> {
Tab tab = scrollableTabLayout.getTabAt(scrollableTabLayout.getTabCount() - 1);
if (tab != null) {
scrollableTabLayout.removeTab(tab);
}
numTabs = Math.max(0, numTabs - 1);
numTabs = max(0, numTabs - 1);
});
return view;
}
Expand Down
Expand Up @@ -32,6 +32,14 @@
android:layout_marginBottom="@dimen/cat_tabs_standard_spacing"
android:orientation="vertical">

<Button
android:id="@+id/add_tab_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/cat_tabs_small_spacing"
android:layout_marginRight="@dimen/cat_tabs_small_spacing"
android:text="@string/cat_tabs_add_tab_button_label" />

<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
Expand All @@ -40,17 +48,17 @@
android:orientation="horizontal"
tools:ignore="ButtonStyle">
<Button
android:id="@+id/add_tab_button"
android:id="@+id/remove_first_tab_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/cat_tabs_small_spacing"
android:layout_marginRight="@dimen/cat_tabs_small_spacing"
android:text="@string/cat_tabs_add_tab_button_label" />
android:text="@string/cat_tabs_remove_first_tab_button_label" />
<Button
android:id="@+id/remove_tab_button"
android:id="@+id/remove_last_tab_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/cat_tabs_remove_tab_button_label" />
android:text="@string/cat_tabs_remove_last_tab_button_label" />
</LinearLayout>


Expand Down
2 changes: 2 additions & 0 deletions catalog/java/io/material/catalog/tabs/res/values/strings.xml
Expand Up @@ -45,6 +45,8 @@
<string name="cat_tabs_secondary_tabs_label">Material Tabs (Secondary)</string>
<string name="cat_tabs_add_tab_button_label">Add Tab</string>
<string name="cat_tabs_remove_tab_button_label">Remove Tab</string>
<string name="cat_tabs_remove_first_tab_button_label">Remove First Tab</string>
<string name="cat_tabs_remove_last_tab_button_label">Remove Last Tab</string>
<string name="cat_tabs_controllable_demo_title">Controllable Tabs Demo</string>
<string name="cat_tabs_scrollable_demo_title">Scrollable Tabs Demo</string>
<string name="cat_tabs_auto_demo_title">Auto Tabs Demo</string>
Expand Down
45 changes: 11 additions & 34 deletions lib/java/com/google/android/material/tabs/TabLayout.java
Expand Up @@ -25,8 +25,6 @@
import static com.google.android.material.animation.AnimationUtils.FAST_OUT_SLOW_IN_INTERPOLATOR;
import static com.google.android.material.theme.overlay.MaterialThemeOverlay.wrap;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.content.Context;
Expand Down Expand Up @@ -3007,10 +3005,6 @@ private float approximateLineWidth(@NonNull Layout layout, int line, float textS

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

private int layoutDirection = -1;

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

selectedPosition = position;
selectionOffset = positionOffset;
// The title view refers to the one indicated when offset is 0.
final View firstTitle = getChildAt(position);
// The title view refers to the one indicated when offset is 1.
final View nextTitle = getChildAt(position + 1);

final View selectedTitle = getChildAt(selectedPosition);
final View nextTitle = getChildAt(selectedPosition + 1);

tweenIndicatorPosition(selectedTitle, nextTitle, selectionOffset);
}

float getIndicatorPosition() {
return selectedPosition + selectionOffset;
tweenIndicatorPosition(firstTitle, nextTitle, positionOffset);
}

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

/** Immediately update the indicator position to the currently selected position. */
private void jumpIndicatorToSelectedPosition() {
final View currentView = getChildAt(selectedPosition);
final View currentView = getChildAt(getSelectedTabPosition());
tabIndicatorInterpolator.setIndicatorBoundsForTab(
TabLayout.this, currentView, tabSelectedIndicator);
}
Expand Down Expand Up @@ -3214,7 +3203,7 @@ void animateIndicatorToPosition(final int position, int duration) {
*/
private void updateOrRecreateIndicatorAnimation(
boolean recreateAnimation, final int position, int duration) {
final View currentView = getChildAt(selectedPosition);
final View currentView = getChildAt(getSelectedTabPosition());
final View targetView = getChildAt(position);
if (targetView == null) {
// If we don't have a view, just update the position now and return
Expand All @@ -3239,18 +3228,6 @@ public void onAnimationUpdate(@NonNull ValueAnimator valueAnimator) {
animator.setDuration(duration);
animator.setFloatValues(0F, 1F);
animator.addUpdateListener(updateListener);
animator.addListener(
new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animator) {
selectedPosition = position;
}

@Override
public void onAnimationEnd(Animator animator) {
selectedPosition = position;
}
});
animator.start();
} else {
// Reuse the existing animator. Updating the listener only modifies the target positions.
Expand Down

0 comments on commit 2fc2e6a

Please sign in to comment.