mirror of https://github.com/TeamNewPipe/NewPipe
135 lines
3.8 KiB
Java
135 lines
3.8 KiB
Java
package org.schabi.newpipe.views;
|
|
|
|
import android.content.Context;
|
|
import android.util.AttributeSet;
|
|
import android.view.View;
|
|
|
|
import androidx.annotation.NonNull;
|
|
|
|
import com.google.android.material.tabs.TabLayout;
|
|
|
|
/**
|
|
* A TabLayout that is scrollable when tabs exceed its width.
|
|
* Hides when there are less than 2 tabs.
|
|
*/
|
|
public class ScrollableTabLayout extends TabLayout {
|
|
private static final String TAG = ScrollableTabLayout.class.getSimpleName();
|
|
|
|
private int layoutWidth = 0;
|
|
private int prevVisibility = View.GONE;
|
|
|
|
public ScrollableTabLayout(final Context context) {
|
|
super(context);
|
|
}
|
|
|
|
public ScrollableTabLayout(final Context context, final AttributeSet attrs) {
|
|
super(context, attrs);
|
|
}
|
|
|
|
public ScrollableTabLayout(final Context context, final AttributeSet attrs,
|
|
final int defStyleAttr) {
|
|
super(context, attrs, defStyleAttr);
|
|
}
|
|
|
|
@Override
|
|
protected void onLayout(final boolean changed, final int l, final int t, final int r,
|
|
final int b) {
|
|
super.onLayout(changed, l, t, r, b);
|
|
|
|
remeasureTabs();
|
|
}
|
|
|
|
@Override
|
|
protected void onSizeChanged(final int w, final int h, final int oldw, final int oldh) {
|
|
super.onSizeChanged(w, h, oldw, oldh);
|
|
|
|
layoutWidth = w;
|
|
}
|
|
|
|
@Override
|
|
public void addTab(@NonNull final Tab tab, final int position, final boolean setSelected) {
|
|
super.addTab(tab, position, setSelected);
|
|
|
|
hasMultipleTabs();
|
|
|
|
// Adding a tab won't decrease total tabs' width so tabMode won't have to change to FIXED
|
|
if (getTabMode() != MODE_SCROLLABLE) {
|
|
remeasureTabs();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void removeTabAt(final int position) {
|
|
super.removeTabAt(position);
|
|
|
|
hasMultipleTabs();
|
|
|
|
// Removing a tab won't increase total tabs' width
|
|
// so tabMode won't have to change to SCROLLABLE
|
|
if (getTabMode() != MODE_FIXED) {
|
|
remeasureTabs();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void onVisibilityChanged(final View changedView, final int visibility) {
|
|
super.onVisibilityChanged(changedView, visibility);
|
|
|
|
// Check width if some tabs have been added/removed while ScrollableTabLayout was invisible
|
|
// We don't have to check if it was GONE because then requestLayout() will be called
|
|
if (changedView == this) {
|
|
if (prevVisibility == View.INVISIBLE) {
|
|
remeasureTabs();
|
|
}
|
|
prevVisibility = visibility;
|
|
}
|
|
}
|
|
|
|
private void setMode(final int mode) {
|
|
if (mode == getTabMode()) {
|
|
return;
|
|
}
|
|
|
|
setTabMode(mode);
|
|
}
|
|
|
|
/**
|
|
* Make ScrollableTabLayout not visible if there are less than two tabs.
|
|
*/
|
|
private void hasMultipleTabs() {
|
|
if (getTabCount() > 1) {
|
|
setVisibility(View.VISIBLE);
|
|
} else {
|
|
setVisibility(View.GONE);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Calculate minimal width required by tabs and set tabMode accordingly.
|
|
*/
|
|
private void remeasureTabs() {
|
|
if (prevVisibility != View.VISIBLE) {
|
|
return;
|
|
}
|
|
if (layoutWidth == 0) {
|
|
return;
|
|
}
|
|
|
|
final int count = getTabCount();
|
|
int contentWidth = 0;
|
|
for (int i = 0; i < count; i++) {
|
|
final View child = getTabAt(i).view;
|
|
if (child.getVisibility() == View.VISIBLE) {
|
|
// Use tab's minimum requested width should actual content be too small
|
|
contentWidth += Math.max(child.getMinimumWidth(), child.getMeasuredWidth());
|
|
}
|
|
}
|
|
|
|
if (contentWidth > layoutWidth) {
|
|
setMode(TabLayout.MODE_SCROLLABLE);
|
|
} else {
|
|
setMode(TabLayout.MODE_FIXED);
|
|
}
|
|
}
|
|
}
|