• 炫酷tab栏--第三方开源--NavigationTabStrip


    github下载地址:https://github.com/DevLight-Mobile-Agency/NavigationTabStrip

    这个开源项目很强大,只是一个自定义的控件,只有一个类

    /*
     * Copyright (C) 2015 Basil Miller
     *
     * 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 testnavigationtabstrip.zzw.com.tablib;
    
    import android.animation.Animator;
    import android.animation.ArgbEvaluator;
    import android.animation.ValueAnimator;
    import android.content.Context;
    import android.content.res.Configuration;
    import android.content.res.TypedArray;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.Rect;
    import android.graphics.RectF;
    import android.graphics.Typeface;
    import android.os.Parcel;
    import android.os.Parcelable;
    import android.support.v4.view.ViewPager;
    import android.text.TextPaint;
    import android.util.AttributeSet;
    import android.view.MotionEvent;
    import android.view.View;
    import android.view.animation.AccelerateDecelerateInterpolator;
    import android.view.animation.Interpolator;
    import android.view.animation.LinearInterpolator;
    import android.widget.Scroller;
    
    import java.lang.reflect.Field;
    import java.util.Arrays;
    import java.util.Random;
    
    /**
     * Created by GIGAMOLE on 24.03.2016.
     */
    public class NavigationTabStrip extends View implements ViewPager.OnPageChangeListener {
    
        // NTS constants
        private final static String PREVIEW_TITLE = "Title";
        private final static int INVALID_INDEX = -1;
    
        // Default variables
        private final static int DEFAULT_ANIMATION_DURATION = 350;
        private final static float DEFAULT_STRIP_FACTOR = 2.5F;
        private final static float DEFAULT_STRIP_WEIGHT = 10.0F;
        private final static float DEFAULT_CORNER_RADIUS = 5.0F;
        private final static int DEFAULT_INACTIVE_COLOR = Color.GRAY;
        private final static int DEFAULT_ACTIVE_COLOR = Color.WHITE;
        private final static int DEFAULT_STRIP_COLOR = Color.RED;
        private final static int DEFAULT_TITLE_SIZE = 0;
    
        // Title size offer to view height
        private final static float TITLE_SIZE_FRACTION = 0.35F;
    
        // Max and min fraction
        private final static float MIN_FRACTION = 0.0F;
        private final static float MAX_FRACTION = 1.0F;
    
        // NTS and strip bounds
        private final RectF mBounds = new RectF();
        private final RectF mStripBounds = new RectF();
        private final Rect mTitleBounds = new Rect();
    
        // Main paint
        private final Paint mStripPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG) {
            {
                setStyle(Style.FILL);
            }
        };
    
        // Paint for tav title
        private final Paint mTitlePaint = new TextPaint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG) {
            {
                setTextAlign(Align.CENTER);
            }
        };
    
        // Variables for animator
        private final ValueAnimator mAnimator = new ValueAnimator();
        private final ArgbEvaluator mColorEvaluator = new ArgbEvaluator();
        private final ResizeInterpolator mResizeInterpolator = new ResizeInterpolator();
        private int mAnimationDuration;
    
        // NTS titles
        private String[] mTitles;
    
        // Variables for ViewPager
        private ViewPager mViewPager;
        private ViewPager.OnPageChangeListener mOnPageChangeListener;
        private int mScrollState;
    
        // Tab listener
        private OnTabStripSelectedIndexListener mOnTabStripSelectedIndexListener;
        private ValueAnimator.AnimatorListener mAnimatorListener;
    
        // Variables for sizes
        private float mTabSize;
        // Tab title size and margin
        private float mTitleSize;
        // Strip type and gravity
        private StripType mStripType;
        private StripGravity mStripGravity;
        // Corners radius for rect mode
        private float mStripWeight;
        private float mCornersRadius;
    
        // Indexes
        private int mLastIndex = INVALID_INDEX;
        private int mIndex = INVALID_INDEX;
        // General fraction value
        private float mFraction;
    
        // Coordinates of strip
        private float mStartStripX;
        private float mEndStripX;
        private float mStripLeft;
        private float mStripRight;
    
        // Detect if is bar mode or indicator pager mode
        private boolean mIsViewPagerMode;
        // Detect if we move from left to right
        private boolean mIsResizeIn;
        // Detect if we get action down event
        private boolean mIsActionDown;
        // Detect if we get action down event on strip
        private boolean mIsTabActionDown;
        // Detect when we set index from tab bar nor from ViewPager
        private boolean mIsSetIndexFromTabBar;
    
        // Color variables
        private int mInactiveColor;
        private int mActiveColor;
    
        // Custom typeface
        private Typeface mTypeface;
    
        public NavigationTabStrip(final Context context) {
            this(context, null);
        }
    
        public NavigationTabStrip(final Context context, final AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public NavigationTabStrip(final Context context, final AttributeSet attrs, final int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            //Init NTS
    
            // Always draw
            setWillNotDraw(false);
            // More speed!
            setLayerType(LAYER_TYPE_HARDWARE, null);
    
            final TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.NavigationTabStrip);
            try {
                setStripColor(
                        typedArray.getColor(R.styleable.NavigationTabStrip_nts_color, DEFAULT_STRIP_COLOR)
                );
                setTitleSize(
                        typedArray.getDimension(R.styleable.NavigationTabStrip_nts_size, DEFAULT_TITLE_SIZE)
                );
                setStripWeight(
                        typedArray.getDimension(R.styleable.NavigationTabStrip_nts_weight, DEFAULT_STRIP_WEIGHT)
                );
                setStripFactor(
                        typedArray.getFloat(R.styleable.NavigationTabStrip_nts_factor, DEFAULT_STRIP_FACTOR)
                );
                setStripType(
                        typedArray.getInt(R.styleable.NavigationTabStrip_nts_type, StripType.LINE_INDEX)
                );
                setStripGravity(
                        typedArray.getInt(R.styleable.NavigationTabStrip_nts_gravity, StripGravity.BOTTOM_INDEX)
                );
    
                setTypeface(typedArray.getString(R.styleable.NavigationTabStrip_nts_typeface));
                setInactiveColor(
                        typedArray.getColor(
                                R.styleable.NavigationTabStrip_nts_inactive_color, DEFAULT_INACTIVE_COLOR
                        )
                );
                setActiveColor(
                        typedArray.getColor(
                                R.styleable.NavigationTabStrip_nts_active_color, DEFAULT_ACTIVE_COLOR
                        )
                );
                setAnimationDuration(
                        typedArray.getInteger(
                                R.styleable.NavigationTabStrip_nts_animation_duration, DEFAULT_ANIMATION_DURATION
                        )
                );
                setCornersRadius(
                        typedArray.getDimension(
                                R.styleable.NavigationTabStrip_nts_corners_radius, DEFAULT_CORNER_RADIUS
                        )
                );
    
                // Get titles
                String[] titles = null;
                try {
                    final int titlesResId = typedArray.getResourceId(
                            R.styleable.NavigationTabStrip_nts_titles, 0
                    );
                    titles = titlesResId == 0 ? null :
                            typedArray.getResources().getStringArray(titlesResId);
                } catch (Exception exception) {
                    titles = null;
                    exception.printStackTrace();
                } finally {
                    if (titles == null) {
                        if (isInEditMode()) {
                            titles = new String[new Random().nextInt(5) + 1];
                            Arrays.fill(titles, PREVIEW_TITLE);
                        } else titles = new String[0];
                    }
    
                    setTitles(titles);
                }
    
                // Init animator
                mAnimator.setFloatValues(MIN_FRACTION, MAX_FRACTION);
                mAnimator.setInterpolator(new LinearInterpolator());
                mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    @Override
                    public void onAnimationUpdate(final ValueAnimator animation) {
                        updateIndicatorPosition((Float) animation.getAnimatedValue());
                    }
                });
            } finally {
                typedArray.recycle();
            }
        }
    
        public int getAnimationDuration() {
            return mAnimationDuration;
        }
    
        public void setAnimationDuration(final int animationDuration) {
            mAnimationDuration = animationDuration;
            mAnimator.setDuration(mAnimationDuration);
            resetScroller();
        }
    
        public String[] getTitles() {
            return mTitles;
        }
    
        public void setTitles(final int... titleResIds) {
            final String[] titles = new String[titleResIds.length];
            for (int i = 0; i < titleResIds.length; i++)
                titles[i] = getResources().getString(titleResIds[i]);
            setTitles(titles);
        }
    
        public void setTitles(final String... titles) {
            for (int i = 0; i < titles.length; i++) titles[i] = titles[i].toUpperCase();
            mTitles = titles;
            requestLayout();
        }
    
        public int getStripColor() {
            return mStripPaint.getColor();
        }
    
        public void setStripColor(final int color) {
            mStripPaint.setColor(color);
            postInvalidate();
        }
    
        public void setStripWeight(final float stripWeight) {
            mStripWeight = stripWeight;
            requestLayout();
        }
    
        public StripGravity getStripGravity() {
            return mStripGravity;
        }
    
        private void setStripGravity(final int index) {
            switch (index) {
                case StripGravity.TOP_INDEX:
                    setStripGravity(StripGravity.TOP);
                    break;
                case StripGravity.BOTTOM_INDEX:
                default:
                    setStripGravity(StripGravity.BOTTOM);
            }
        }
    
        public void setStripGravity(final StripGravity stripGravity) {
            mStripGravity = stripGravity;
            requestLayout();
        }
    
        public StripType getStripType() {
            return mStripType;
        }
    
        private void setStripType(final int index) {
            switch (index) {
                case StripType.POINT_INDEX:
                    setStripType(StripType.POINT);
                    break;
                case StripType.LINE_INDEX:
                default:
                    setStripType(StripType.LINE);
            }
        }
    
        public void setStripType(final StripType stripType) {
            mStripType = stripType;
            requestLayout();
        }
    
        public float getStripFactor() {
            return mResizeInterpolator.getFactor();
        }
    
        public void setStripFactor(final float factor) {
            mResizeInterpolator.setFactor(factor);
        }
    
        public Typeface getTypeface() {
            return mTypeface;
        }
    
        public void setTypeface(final String typeface) {
            Typeface tempTypeface;
            try {
                tempTypeface = Typeface.createFromAsset(getContext().getAssets(), typeface);
            } catch (Exception e) {
                tempTypeface = Typeface.create(Typeface.DEFAULT, Typeface.NORMAL);
                e.printStackTrace();
            }
    
            setTypeface(tempTypeface);
        }
    
        public void setTypeface(final Typeface typeface) {
            mTypeface = typeface;
            mTitlePaint.setTypeface(typeface);
            postInvalidate();
        }
    
        public int getActiveColor() {
            return mActiveColor;
        }
    
        public void setActiveColor(final int activeColor) {
            mActiveColor = activeColor;
            postInvalidate();
        }
    
        public int getInactiveColor() {
            return mInactiveColor;
        }
    
        public void setInactiveColor(final int inactiveColor) {
            mInactiveColor = inactiveColor;
            postInvalidate();
        }
    
        public float getCornersRadius() {
            return mCornersRadius;
        }
    
        public void setCornersRadius(final float cornersRadius) {
            mCornersRadius = cornersRadius;
            postInvalidate();
        }
    
        public float getTitleSize() {
            return mTitleSize;
        }
    
        public void setTitleSize(final float titleSize) {
            mTitleSize = titleSize;
            mTitlePaint.setTextSize(titleSize);
            postInvalidate();
        }
    
        public OnTabStripSelectedIndexListener getOnTabStripSelectedIndexListener() {
            return mOnTabStripSelectedIndexListener;
        }
    
        // Set on tab bar selected index listener where you can trigger action onStart or onEnd
        public void setOnTabStripSelectedIndexListener(final OnTabStripSelectedIndexListener onTabStripSelectedIndexListener) {
            mOnTabStripSelectedIndexListener = onTabStripSelectedIndexListener;
    
            if (mAnimatorListener == null)
                mAnimatorListener = new Animator.AnimatorListener() {
                    @Override
                    public void onAnimationStart(final Animator animation) {
                        if (mOnTabStripSelectedIndexListener != null)
                            mOnTabStripSelectedIndexListener.onStartTabSelected(mTitles[mIndex], mIndex);
    
                        animation.removeListener(this);
                        animation.addListener(this);
                    }
    
                    @Override
                    public void onAnimationEnd(final Animator animation) {
                        if (mIsViewPagerMode) return;
    
                        animation.removeListener(this);
                        animation.addListener(this);
    
                        if (mOnTabStripSelectedIndexListener != null)
                            mOnTabStripSelectedIndexListener.onEndTabSelected(mTitles[mIndex], mIndex);
                    }
    
                    @Override
                    public void onAnimationCancel(final Animator animation) {
    
                    }
    
                    @Override
                    public void onAnimationRepeat(final Animator animation) {
    
                    }
                };
            mAnimator.removeListener(mAnimatorListener);
            mAnimator.addListener(mAnimatorListener);
        }
    
        public void setViewPager(final ViewPager viewPager) {
            // Detect whether ViewPager mode
            if (viewPager == null) {
                mIsViewPagerMode = false;
                return;
            }
    
            if (mViewPager == viewPager) return;
            if (mViewPager != null) mViewPager.setOnPageChangeListener(null);
            if (viewPager.getAdapter() == null)
                throw new IllegalStateException("ViewPager does not provide adapter instance.");
    
            mIsViewPagerMode = true;
            mViewPager = viewPager;
            mViewPager.addOnPageChangeListener(this);
    
            resetScroller();
            postInvalidate();
        }
    
        public void setViewPager(final ViewPager viewPager, int index) {
            setViewPager(viewPager);
    
            mIndex = index;
            if (mIsViewPagerMode) mViewPager.setCurrentItem(index, true);
            postInvalidate();
        }
    
        // Reset scroller and reset scroll duration equals to animation duration
        private void resetScroller() {
            if (mViewPager == null) return;
            try {
                final Field scrollerField = ViewPager.class.getDeclaredField("mScroller");
                scrollerField.setAccessible(true);
                final ResizeViewPagerScroller scroller = new ResizeViewPagerScroller(getContext());
                scrollerField.set(mViewPager, scroller);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        public void setOnPageChangeListener(final ViewPager.OnPageChangeListener listener) {
            mOnPageChangeListener = listener;
        }
    
        public int getTabIndex() {
            return mIndex;
        }
    
        public void setTabIndex(int index) {
            setTabIndex(index, false);
        }
    
        // Set tab index from touch or programmatically
        public void setTabIndex(int index, boolean force) {
            if (mAnimator.isRunning()) return;
            if (mTitles.length == 0) return;
    
            // This check gives us opportunity to have an non selected tab
            if (mIndex == INVALID_INDEX) force = true;
    
            // Detect if last is the same
            if (index == mIndex) return;
    
            // Snap index to tabs size
            index = Math.max(0, Math.min(index, mTitles.length - 1));
    
            mIsResizeIn = index < mIndex;
            mLastIndex = mIndex;
            mIndex = index;
    
            mIsSetIndexFromTabBar = true;
            if (mIsViewPagerMode) {
                if (mViewPager == null) throw new IllegalStateException("ViewPager is null.");
                mViewPager.setCurrentItem(index, true);
            }
    
            // Set startX and endX for animation, where we animate two sides of rect with different interpolation
            mStartStripX = mStripLeft;
            mEndStripX = (mIndex * mTabSize) + (mStripType == StripType.POINT ? mTabSize * 0.5F : 0.0F);
    
            // If it force, so update immediately, else animate
            // This happens if we set index onCreate or something like this
            // You can use force param or call this method in some post()
            if (force) updateIndicatorPosition(MAX_FRACTION);
            else mAnimator.start();
        }
    
        private void updateIndicatorPosition(final float fraction) {
            // Update general fraction
            mFraction = fraction;
    
            // Set the strip left side coordinate
            mStripLeft =
                    mStartStripX + (mResizeInterpolator.getResizeInterpolation(fraction, mIsResizeIn) *
                            (mEndStripX - mStartStripX));
            // Set the strip right side coordinate
            mStripRight =
                    (mStartStripX + (mStripType == StripType.LINE ? mTabSize : mStripWeight)) +
                            (mResizeInterpolator.getResizeInterpolation(fraction, !mIsResizeIn) *
                                    (mEndStripX - mStartStripX));
    
            // Update NTS
            postInvalidate();
        }
    
        // Update NTS
        private void notifyDataSetChanged() {
            postInvalidate();
        }
    
        @Override
        public boolean onTouchEvent(final MotionEvent event) {
            // Return if animation is running
            if (mAnimator.isRunning()) return true;
            // If is not idle state, return
            if (mScrollState != ViewPager.SCROLL_STATE_IDLE) return true;
    
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    // Action down touch
                    mIsActionDown = true;
                    if (!mIsViewPagerMode) break;
                    // Detect if we touch down on tab, later to move
                    mIsTabActionDown = (int) (event.getX() / mTabSize) == mIndex;
                    break;
                case MotionEvent.ACTION_MOVE:
                    // If tab touched, so move
                    if (mIsTabActionDown) {
                        mViewPager.setCurrentItem((int) (event.getX() / mTabSize), true);
                        break;
                    }
                    if (mIsActionDown) break;
                case MotionEvent.ACTION_UP:
                    // Press up and set tab index relative to current coordinate
                    if (mIsActionDown) setTabIndex((int) (event.getX() / mTabSize));
                case MotionEvent.ACTION_CANCEL:
                case MotionEvent.ACTION_OUTSIDE:
                default:
                    // Reset action touch variables
                    mIsTabActionDown = false;
                    mIsActionDown = false;
                    break;
            }
    
            return true;
        }
    
        @Override
        protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    
            // Get measure size
            final float width = MeasureSpec.getSize(widthMeasureSpec);
            final float height = MeasureSpec.getSize(heightMeasureSpec);
    
            // Set bounds for NTS
            mBounds.set(0.0F, 0.0F, width, height);
    
            if (mTitles.length == 0 || width == 0 || height == 0) return;
    
            // Get smaller side
            mTabSize = width / (float) mTitles.length;
            if ((int) mTitleSize == DEFAULT_TITLE_SIZE)
                setTitleSize((height - mStripWeight) * TITLE_SIZE_FRACTION);
    
            // Set start position of strip for preview or on start
            if (isInEditMode() || !mIsViewPagerMode) {
                mIsSetIndexFromTabBar = true;
    
                // Set random in preview mode
                if (isInEditMode()) mIndex = new Random().nextInt(mTitles.length);
    
                mStartStripX =
                        (mIndex * mTabSize) + (mStripType == StripType.POINT ? mTabSize * 0.5F : 0.0F);
                mEndStripX = mStartStripX;
                updateIndicatorPosition(MAX_FRACTION);
            }
        }
    
        @Override
        protected void onDraw(final Canvas canvas) {
            // Set bound of strip
            mStripBounds.set(
                    mStripLeft - (mStripType == StripType.POINT ? mStripWeight * 0.5F : 0.0F),
                    mStripGravity == StripGravity.BOTTOM ? mBounds.height() - mStripWeight : 0.0F,
                    mStripRight - (mStripType == StripType.POINT ? mStripWeight * 0.5F : 0.0F),
                    mStripGravity == StripGravity.BOTTOM ? mBounds.height() : mStripWeight
            );
    
            // Draw strip
            if (mCornersRadius == 0) canvas.drawRect(mStripBounds, mStripPaint);
            else canvas.drawRoundRect(mStripBounds, mCornersRadius, mCornersRadius, mStripPaint);
    
            // Draw tab titles
            for (int i = 0; i < mTitles.length; i++) {
                final String title = mTitles[i];
    
                final float leftTitleOffset = (mTabSize * i) + (mTabSize * 0.5F);
    
                mTitlePaint.getTextBounds(title, 0, title.length(), mTitleBounds);
                final float topTitleOffset = (mBounds.height() - mStripWeight) * 0.5F +
                        mTitleBounds.height() * 0.5F - mTitleBounds.bottom;
    
                // Get interpolated fraction for left last and current tab
                final float interpolation = mResizeInterpolator.getResizeInterpolation(mFraction, true);
                final float lastInterpolation = mResizeInterpolator.getResizeInterpolation(mFraction, false);
    
                // Check if we handle tab from touch on NTS or from ViewPager
                // There is a strange logic of ViewPager onPageScrolled method, so it is
                if (mIsSetIndexFromTabBar) {
                    if (mIndex == i) updateCurrentTitle(interpolation);
                    else if (mLastIndex == i) updateLastTitle(lastInterpolation);
                    else updateInactiveTitle();
                } else {
                    if (i != mIndex && i != mIndex + 1) updateInactiveTitle();
                    else if (i == mIndex + 1) updateCurrentTitle(interpolation);
                    else if (i == mIndex) updateLastTitle(lastInterpolation);
                }
    
                canvas.drawText(
                        title, leftTitleOffset,
                        topTitleOffset + (mStripGravity == StripGravity.TOP ? mStripWeight : 0.0F),
                        mTitlePaint
                );
            }
        }
    
        // Method to transform current fraction of NTS and position
        private void updateCurrentTitle(final float interpolation) {
            mTitlePaint.setColor(
                    (int) mColorEvaluator.evaluate(interpolation, mInactiveColor, mActiveColor)
            );
        }
    
        // Method to transform last fraction of NTS and position
        private void updateLastTitle(final float lastInterpolation) {
            mTitlePaint.setColor(
                    (int) mColorEvaluator.evaluate(lastInterpolation, mActiveColor, mInactiveColor)
            );
        }
    
        // Method to transform others fraction of NTS and position
        private void updateInactiveTitle() {
            mTitlePaint.setColor(mInactiveColor);
        }
    
        @Override
        public void onPageScrolled(int position, float positionOffset, final int positionOffsetPixels) {
            // If we animate, don`t call this
            if (!mIsSetIndexFromTabBar) {
                mIsResizeIn = position < mIndex;
                mLastIndex = mIndex;
                mIndex = position;
    
                mStartStripX =
                        (position * mTabSize) + (mStripType == StripType.POINT ? mTabSize * 0.5F : 0.0F);
                mEndStripX = mStartStripX + mTabSize;
                updateIndicatorPosition(positionOffset);
            }
    
            if (mOnPageChangeListener != null)
                mOnPageChangeListener.onPageScrolled(position, positionOffset, positionOffsetPixels);
        }
    
        @Override
        public void onPageSelected(final int position) {
            // If VP idle, so update
            if (mScrollState == ViewPager.SCROLL_STATE_IDLE) {
                mIsResizeIn = position < mIndex;
                mLastIndex = mIndex;
                mIndex = position;
                postInvalidate();
            }
        }
    
        @Override
        public void onPageScrollStateChanged(final int state) {
            // If VP idle, reset to MIN_FRACTION
            if (state == ViewPager.SCROLL_STATE_IDLE) {
                mFraction = MIN_FRACTION;
                mIsSetIndexFromTabBar = false;
    
                if (mOnPageChangeListener != null) mOnPageChangeListener.onPageSelected(mIndex);
                else {
                    if (mOnTabStripSelectedIndexListener != null)
                        mOnTabStripSelectedIndexListener.onEndTabSelected(mTitles[mIndex], mIndex);
                }
            }
            mScrollState = state;
    
            if (mOnPageChangeListener != null) mOnPageChangeListener.onPageScrollStateChanged(state);
        }
    
        @Override
        public void onRestoreInstanceState(Parcelable state) {
            final SavedState savedState = (SavedState) state;
            super.onRestoreInstanceState(savedState.getSuperState());
            mIndex = savedState.index;
            requestLayout();
        }
    
        @Override
        public Parcelable onSaveInstanceState() {
            final Parcelable superState = super.onSaveInstanceState();
            final SavedState savedState = new SavedState(superState);
            savedState.index = mIndex;
            return savedState;
        }
    
        // Save current index instance
        private static class SavedState extends BaseSavedState {
            int index;
    
            public SavedState(Parcelable superState) {
                super(superState);
            }
    
            private SavedState(Parcel in) {
                super(in);
                index = in.readInt();
            }
    
            @Override
            public void writeToParcel(Parcel dest, int flags) {
                super.writeToParcel(dest, flags);
                dest.writeInt(index);
            }
    
            @SuppressWarnings("UnusedDeclaration")
            public static final Creator<SavedState> CREATOR = new Creator<SavedState>() {
                @Override
                public SavedState createFromParcel(Parcel in) {
                    return new SavedState(in);
                }
    
                @Override
                public SavedState[] newArray(int size) {
                    return new SavedState[size];
                }
            };
        }
    
        @Override
        protected void onConfigurationChanged(final Configuration newConfig) {
            // Config view on rotate etc.
            super.onConfigurationChanged(newConfig);
            requestLayout();
    
            // Refresh strip and state after config changed to current
            final int tempIndex = mIndex;
            setTabIndex(INVALID_INDEX, true);
            post(new Runnable() {
                @Override
                public void run() {
                    setTabIndex(tempIndex, true);
                }
            });
        }
    
        // Custom scroller with custom scroll duration
        private class ResizeViewPagerScroller extends Scroller {
    
            public ResizeViewPagerScroller(Context context) {
                super(context, new AccelerateDecelerateInterpolator());
            }
    
            @Override
            public void startScroll(int startX, int startY, int dx, int dy, int duration) {
                super.startScroll(startX, startY, dx, dy, mAnimationDuration);
            }
    
            @Override
            public void startScroll(int startX, int startY, int dx, int dy) {
                super.startScroll(startX, startY, dx, dy, mAnimationDuration);
            }
        }
    
        // Resize interpolator to create smooth effect on strip according to inspiration design
        // This is like improved accelerated and decelerated interpolator
        private static class ResizeInterpolator implements Interpolator {
    
            // Spring factor
            private float mFactor;
            // Check whether side we move
            private boolean mResizeIn;
    
            public float getFactor() {
                return mFactor;
            }
    
            public void setFactor(final float factor) {
                mFactor = factor;
            }
    
            @Override
            public float getInterpolation(final float input) {
                if (mResizeIn) return (float) (1.0F - Math.pow((1.0F - input), 2.0F * mFactor));
                else return (float) (Math.pow(input, 2.0F * mFactor));
            }
    
            public float getResizeInterpolation(final float input, final boolean resizeIn) {
                mResizeIn = resizeIn;
                return getInterpolation(input);
            }
        }
    
        // NTS strip type
        public enum StripType {
            LINE, POINT;
    
            private final static int LINE_INDEX = 0;
            private final static int POINT_INDEX = 1;
        }
    
        // NTS strip gravity
        public enum StripGravity {
            BOTTOM, TOP;
    
            private final static int BOTTOM_INDEX = 0;
            private final static int TOP_INDEX = 1;
        }
    
        // Out listener for selected index
        public interface OnTabStripSelectedIndexListener {
            void onStartTabSelected(final String title, final int index);
    
            void onEndTabSelected(final String title, final int index);
        }
    }
    NavigationTabStrip

    相关的资源文件:

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
    
        <declare-styleable name="NavigationTabStrip">
            <attr name="nts_color" format="color"/>
            <attr name="nts_size" format="dimension"/>
            <attr name="nts_weight" format="dimension"/>
            <attr name="nts_factor" format="float"/>
            <attr name="nts_titles" format="reference"/>
    
            <attr name="nts_type" format="enum">
                <enum name="line" value="0"/>
                <enum name="point" value="1"/>
            </attr>
            <attr name="nts_gravity" format="enum">
                <enum name="bottom" value="0"/>
                <enum name="top" value="1"/>
            </attr>
    
            <attr name="nts_typeface" format="string"/>
            <attr name="nts_corners_radius" format="dimension"/>
            <attr name="nts_animation_duration" format="integer"/>
    
            <attr name="nts_inactive_color" format="color"/>
            <attr name="nts_active_color" format="color"/>
        </declare-styleable>
    
    </resources>
    attrs.xml

    Demo代码:

    xml:

    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <android.support.v4.view.ViewPager
            android:id="@+id/vp"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            android:weightSum="3">
    
            <FrameLayout
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="1"
                android:background="#ffffffff"
                android:paddingEnd="30dp"
                android:paddingLeft="30dp"
                android:paddingRight="30dp"
                android:paddingStart="30dp">
    
                <testnavigationtabstrip.zzw.com.tablib.NavigationTabStrip
                    android:id="@+id/nts_top"
                    android:layout_width="match_parent"
                    android:layout_height="56dp"
                    android:layout_gravity="center"
                    app:nts_active_color="#42a4d1"
                    app:nts_color="#42a4d1"
                    app:nts_corners_radius="1dp"
                    app:nts_inactive_color="#ff1a1e23"
                    app:nts_size="15sp"
                    app:nts_titles="@array/titles"
                    app:nts_weight="3dp" />
    
            </FrameLayout>
    
            <FrameLayout
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="1"
                android:background="#ff252e39">
    
                <View
                    android:layout_width="match_parent"
                    android:layout_height="4dp"
                    android:layout_gravity="center"
                    android:layout_marginTop="18dp"
                    android:background="#182128" />
    
                <testnavigationtabstrip.zzw.com.tablib.NavigationTabStrip
                    android:id="@+id/nts_center"
                    android:layout_width="match_parent"
                    android:layout_height="42dp"
                    android:layout_gravity="center"
                    android:layout_marginEnd="30dp"
                    android:layout_marginLeft="30dp"
                    android:layout_marginRight="30dp"
                    android:layout_marginStart="30dp"
                    app:nts_active_color="#fff"
                    app:nts_color="#3cdedd"
                    app:nts_corners_radius="3.5dp"
                    app:nts_factor="0.8"
                    app:nts_gravity="bottom"
                    app:nts_inactive_color="#81ffffff"
                    app:nts_titles="@array/titles"
                    app:nts_type="point"
                    app:nts_typeface="fonts/moon.otf"
                    app:nts_weight="7dp" />
    
            </FrameLayout>
    
            <FrameLayout
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="1"
                android:background="#ff1a1e23"
                android:paddingEnd="30dp"
                android:paddingLeft="30dp"
                android:paddingRight="30dp"
                android:paddingStart="30dp">
    
                <testnavigationtabstrip.zzw.com.tablib.NavigationTabStrip
                    android:id="@+id/nts_bottom"
                    android:layout_width="match_parent"
                    android:layout_height="50dp"
                    android:layout_gravity="center"
                    app:nts_active_color="#fff"
                    app:nts_color="#ff1748"
                    app:nts_corners_radius="1.5dp"
                    app:nts_factor="2.8"
                    app:nts_inactive_color="#81ffffff"
                    app:nts_titles="@array/titles"
                    app:nts_typeface="fonts/drugs.otf"
                    app:nts_weight="3dp" />
    
            </FrameLayout>
    
        </LinearLayout>
    
    </FrameLayout>

    相关资源文件:

    arrays.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
    
        <string-array name="titles">
            <item>Nav</item>
            <item>Tab</item>
            <item>Strip</item>
        </string-array>
    
    </resources>

    java代码:

    package com.zzw.TestNavigationTabStrip;
    
    import android.support.v4.view.PagerAdapter;
    import android.support.v4.view.ViewPager;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.view.View;
    import android.view.ViewGroup;
    
    import testnavigationtabstrip.zzw.com.tablib.NavigationTabStrip;
    
    public class MainActivity extends AppCompatActivity {
        private ViewPager mViewPager;
    
        private NavigationTabStrip mTopNavigationTabStrip;
        private NavigationTabStrip mCenterNavigationTabStrip;
        private NavigationTabStrip mBottomNavigationTabStrip;
    
        @Override
        protected void onCreate(final Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            initUI();
            setUI();
        }
    
        private void initUI() {
            mViewPager = (ViewPager) findViewById(R.id.vp);
            mTopNavigationTabStrip = (NavigationTabStrip) findViewById(R.id.nts_top);
            mCenterNavigationTabStrip = (NavigationTabStrip) findViewById(R.id.nts_center);
            mBottomNavigationTabStrip = (NavigationTabStrip) findViewById(R.id.nts_bottom);
        }
    
        private void setUI() {
            mViewPager.setAdapter(new PagerAdapter() {
                @Override
                public int getCount() {
                    return 3;
                }
    
                @Override
                public boolean isViewFromObject(final View view, final Object object) {
                    return view.equals(object);
                }
    
                @Override
                public void destroyItem(final View container, final int position, final Object object) {
                    ((ViewPager) container).removeView((View) object);
                }
    
                @Override
                public Object instantiateItem(final ViewGroup container, final int position) {
                    final View view = new View(getBaseContext());
                    container.addView(view);
                    return view;
                }
            });
    
            mTopNavigationTabStrip.setTabIndex(1, true);
            mBottomNavigationTabStrip.setViewPager(mViewPager, 1);
            mCenterNavigationTabStrip.setTabIndex(1, true);
    
    //        final NavigationTabStrip navigationTabStrip = (NavigationTabStrip) findViewById(R.id.nts);
    //        navigationTabStrip.setTitles("Nav", "Tab", "Strip");
    //        navigationTabStrip.setTabIndex(0, true);
    //        navigationTabStrip.setTitleSize(15);
    //        navigationTabStrip.setStripColor(Color.RED);
    //        navigationTabStrip.setStripWeight(6);
    //        navigationTabStrip.setStripFactor(2);
    //        navigationTabStrip.setStripType(NavigationTabStrip.StripType.LINE);
    //        navigationTabStrip.setStripGravity(NavigationTabStrip.StripGravity.BOTTOM);
    //        navigationTabStrip.setTypeface("fonts/typeface.ttf");
    //        navigationTabStrip.setCornersRadius(3);
    //        navigationTabStrip.setAnimationDuration(300);
    //        navigationTabStrip.setInactiveColor(Color.GRAY);
    //        navigationTabStrip.setActiveColor(Color.WHITE);
    //        navigationTabStrip.setOnPageChangeListener(...);
    //        navigationTabStrip.setOnTabStripSelectedIndexListener(...);
        }
    }
  • 相关阅读:
    时间相关概念
    如何查询Oracle EBS接口表
    生成随机数
    web.config/app.config敏感数据加/解密的二种方法
    浅谈.NET下的多线程和并行计算
    禁用浏览中的Tab键
    主从表关联,判断子表全部符合条件后主有才有效
    windows xp 中的administrator帐户不在用户登录内怎么解决?
    WebResourceCompression压缩模块以及.Net 程序脱离.net framework框架运行
    使用架构(XSD)验证XML文件
  • 原文地址:https://www.cnblogs.com/zzw1994/p/5553609.html
Copyright © 2020-2023  润新知