/*
* Copyright (C) 2017 Stichting Akvo (Akvo Foundation)
*
* This file is part of Akvo Flow.
*
* Akvo Flow is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Akvo Flow is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Akvo Flow. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.akvo.flow.ui.view;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.TabLayout;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import org.akvo.flow.util.ViewUtil;
import java.lang.reflect.Field;
import timber.log.Timber;
/**
* a TabLayout which adapts its tabs sizes to the number of items in the pager adapter.
* For 1 tab -> use all the screen width for tab width
* For 2 tabs -> stretch both tabs to occupy both half of screen
* For 3 tabs or more -> tabs will be scrollable and each tab will have the size of about 1/3 of the
* screen size
*/
public class AdaptableTabLayout extends TabLayout {
private static final String REQUESTED_TAB_MIN_WIDTH = "mRequestedTabMinWidth";
private static final String REQUESTED_TAB_MAX_WIDTH = "mRequestedTabMaxWidth";
private static final int DIVIDER_MINIMUM = 1;
private static final int DIVIDER_MAXIMUM = 3;
public static final int UNSET = -1;
private AdapterChangeListener mAdapterChangeListener;
private int numberOfTabs = UNSET;
public AdaptableTabLayout(Context context) {
super(context);
}
public AdaptableTabLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public AdaptableTabLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public void setupWithViewPager(@Nullable ViewPager viewPager) {
setUpTabSizesUsingViewPagerContent(viewPager);
setUpAdapterChangeListener(viewPager);
super.setupWithViewPager(viewPager);
}
private void setUpAdapterChangeListener(ViewPager viewPager) {
if (mAdapterChangeListener == null) {
mAdapterChangeListener = new AdapterChangeListener();
}
viewPager.addOnAdapterChangeListener(mAdapterChangeListener);
}
private void setUpTabSizesUsingViewPagerContent(ViewPager viewPager) {
if (viewPager != null) {
final PagerAdapter adapter = viewPager.getAdapter();
if (adapter != null && adapter.getCount() > 0) {
setTabWidth(adapter.getCount());
}
}
}
private void setTabWidth(int numberOfTabs) {
if (this.numberOfTabs != numberOfTabs) {
this.numberOfTabs = numberOfTabs;
int width = ViewUtil.getScreenWidth(getContext());
int divider = Math.min(Math.max(numberOfTabs, DIVIDER_MINIMUM), DIVIDER_MAXIMUM);
int tabMinWidth = width / divider;
setMinimumTabWidth(tabMinWidth);
setMaximumTabWidth(tabMinWidth);
}
}
private void setMinimumTabWidth(int tabMinWidth) {
initReflectedValue(tabMinWidth, REQUESTED_TAB_MIN_WIDTH);
}
private void setMaximumTabWidth(int tabMaxWidth) {
initReflectedValue(tabMaxWidth, REQUESTED_TAB_MAX_WIDTH);
}
private void initReflectedValue(int value, String reflectedFieldName) {
Field field;
try {
field = TabLayout.class.getDeclaredField(reflectedFieldName);
field.setAccessible(true);
field.set(this, value);
} catch (NoSuchFieldException e) {
Timber.e(e, "Field not found : %s", reflectedFieldName);
} catch (IllegalAccessException e) {
Timber.e(e, "Illegal access : %s", reflectedFieldName);
}
}
private class AdapterChangeListener implements ViewPager.OnAdapterChangeListener {
@Override
public void onAdapterChanged(@NonNull ViewPager viewPager,
@Nullable PagerAdapter oldAdapter, @Nullable PagerAdapter newAdapter) {
int count = newAdapter == null ? 0 : newAdapter.getCount();
setTabWidth(count);
}
}
}