com.github.saiff35.livingtabs.LivingTabsLayout.java Source code

Java tutorial

Introduction

Here is the source code for com.github.saiff35.livingtabs.LivingTabsLayout.java

Source

/*
 * Copyright (c) 2015 Saif Chaouachi
 *
 * 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.
 */

package com.github.saiff35.livingtabs;

import android.animation.Animator;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.support.annotation.DrawableRes;
import android.support.annotation.NonNull;
import android.support.design.widget.TabLayout;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

import java.lang.ref.WeakReference;
import java.util.ArrayList;

/**
 * Created by Saif on 8/26/2015.
 */
public class LivingTabsLayout extends TabLayout {
    protected static final int SCALE_HIDDEN = 0;
    private ArrayList<LivingTab> tabs;
    private boolean animationRunning = false;
    private final Animator.AnimatorListener startListener = new Animator.AnimatorListener() {
        @Override
        public void onAnimationStart(Animator animation) {
            animationRunning = true;
        }

        @Override
        public void onAnimationEnd(Animator animation) {

        }

        @Override
        public void onAnimationCancel(Animator animation) {

        }

        @Override
        public void onAnimationRepeat(Animator animation) {

        }
    };
    private final Animator.AnimatorListener stopListener = new Animator.AnimatorListener() {
        @Override
        public void onAnimationStart(Animator animation) {

        }

        @Override
        public void onAnimationEnd(Animator animation) {
            animationRunning = false;
        }

        @Override
        public void onAnimationCancel(Animator animation) {

        }

        @Override
        public void onAnimationRepeat(Animator animation) {

        }
    };

    public LivingTabsLayout(Context context) {
        this(context, null);
    }

    public LivingTabsLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);

    }

    public LivingTabsLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {

    }

    //TODO // FIXME: 8/27/2015 going swipping the leftest page then clicking the rightest doesn't work

    @Override
    public void setupWithViewPager(@NonNull ViewPager viewPager) {

        final PagerAdapter adapter = viewPager.getAdapter();
        DrawableResIconAdapter drawableResIconAdapter = null;
        DrawableIconAdapter drawableIconAdapter = null;
        boolean isDrawableResAdapter;
        if ((isDrawableResAdapter = adapter instanceof DrawableResIconAdapter)) {
            drawableResIconAdapter = (DrawableResIconAdapter) adapter;
        } else if (adapter instanceof DrawableIconAdapter) {
            drawableIconAdapter = (DrawableIconAdapter) adapter;
        } else {
            throw new IllegalArgumentException(
                    "ViewPager's adapter must implement either DrawableIconAdapter or DrawableResIconAdapter");
        }
        super.setupWithViewPager(viewPager);

        final int selectedTabPosition = getSelectedTabPosition();
        final int count = adapter.getCount();
        if (tabs == null)
            tabs = new ArrayList<>(count);
        else {
            tabs.clear();
        }
        for (int i = 0; i < count; ++i) {
            Tab t = super.getTabAt(i);
            if (isDrawableResAdapter)
                t.setIcon(drawableResIconAdapter.getIcon(i));
            else
                t.setIcon(drawableIconAdapter.getIcon(i));
            final LivingTab tab = newLivingTab(t);
            //  .setText(adapter.getPageTitle(i))
            //.setIcon(icons.get(i));
            addTab(tab);

            if (i != selectedTabPosition) {
                final TextView textView = tab.textView;
                textView.setScaleY(SCALE_HIDDEN);
                textView.setScaleX(SCALE_HIDDEN);
            } else {
                final ImageView iconView = tab.iconView;
                iconView.setScaleY(SCALE_HIDDEN);
                iconView.setScaleX(SCALE_HIDDEN);
            }
        }

        viewPager.addOnPageChangeListener(new LivingTabsOnPageChangeListener(this));
    }

    private void addTab(LivingTab tab) {
        tabs.add(tab);
    }

    private LivingTab newLivingTab(Tab tab) {
        return new LivingTab(tab);

    }

    public static class LivingTabsOnPageChangeListener implements ViewPager.OnPageChangeListener {

        private final WeakReference<LivingTabsLayout> tabLayoutRef;
        private int oldPosition = -1;
        private int state = ViewPager.SCROLL_STATE_IDLE;

        private int pendingPosition = -1;

        public LivingTabsOnPageChangeListener(LivingTabsLayout tabLayout) {
            tabLayoutRef = new WeakReference(tabLayout);
            oldPosition = tabLayout.getSelectedTabPosition();
        }

        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            LivingTabsLayout tabLayout = this.tabLayoutRef.get();
            if (tabLayout != null) {
                if (positionOffset == 0.0f || positionOffsetPixels == 0)
                    return;

                if (state == ViewPager.SCROLL_STATE_DRAGGING || state == ViewPager.SCROLL_STATE_SETTLING) {

                    tabLayout.setScalePosition(position, positionOffset, oldPosition, pendingPosition);

                }
                if (state == ViewPager.SCROLL_STATE_SETTLING && pendingPosition != -1) {
                    tabLayout.animateToPendingTab(pendingPosition, oldPosition);
                }
                if (pendingPosition != -1) {
                    oldPosition = pendingPosition;
                    pendingPosition = -1;
                }
            }
        }

        @Override
        public void onPageSelected(int position) {

            pendingPosition = position;
        }

        @Override
        public void onPageScrollStateChanged(int state) {

            this.state = state;
        }

    }

    private void animateToPendingTab(final int position, final int oldPosition) {
        {
            final LivingTab newTab = tabs.get(position);
            final View newTv = newTab.textView;

            newTv.animate().setDuration(300).scaleY(1).scaleX(1).setListener(startListener).start();

            final View newIv = newTab.iconView;

            newIv.animate().setDuration(300).scaleY(0).scaleX(0).start();

            final LivingTab oldTab = tabs.get(oldPosition);
            final View oldTv = oldTab.textView;

            oldTv.animate().setDuration(300).scaleY(0).scaleX(0).start();

            final View oldIv = oldTab.iconView;

            oldIv.animate().setDuration(300).scaleY(1).scaleX(1).setListener(stopListener).start();

        }
    }

    private void setScalePosition(final int position, final float positionOffset, final int oldPosition,
            final int pendingPosition) {
        if (!animationRunning) {
            int newPosition = position;

            float scale = positionOffset;
            if (position == oldPosition) {
                //TODO solve out of bound
                newPosition = position + 1;

            } else {
                scale = 1 - scale;
            }
            if (pendingPosition != -1) {
                newPosition = pendingPosition;

            }
            final LivingTab newTab = tabs.get(newPosition);
            TextView newTv = newTab.textView;

            newTv.setScaleY(scale);
            newTv.setScaleX(scale);
            ImageView newIv = newTab.iconView;
            float inversedScale = 1 - scale;
            newIv.setScaleY(inversedScale);
            newIv.setScaleX(inversedScale);

            final LivingTab oldTab = tabs.get(oldPosition);
            TextView oldTv = oldTab.textView;
            oldTv.setScaleY(inversedScale);
            oldTv.setScaleX(inversedScale);
            ImageView oldIv = oldTab.iconView;
            oldIv.setScaleY(scale);
            oldIv.setScaleX(scale);
        }
    }

    private static final class LivingTab {
        private TextView textView;
        private ImageView iconView;

        LivingTab(final Tab tab) {
            tab.setCustomView(R.layout.living_tabs);
            View v = tab.getCustomView();
            textView = (TextView) v.findViewById(android.R.id.text1);
            iconView = (ImageView) v.findViewById(android.R.id.icon);

        }

    }

    public interface DrawableIconAdapter {
        @NonNull
        Drawable getIcon(int position);
    }

    public interface DrawableResIconAdapter {
        @DrawableRes
        int getIcon(int position);
    }
}