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(...);
}
}

炫酷tab栏--第三方开源--NavigationTabStrip的更多相关文章

  1. ViewPage显示Fragment集合实现左右滑动并且出现tab栏--第三方开源--SlidingTabLayout和SlidingTabStrip实现

    注意:有关Fragment的方法和ViewPager的全部是android.support.v4包的,否则会报很多的错误 MainActivity: package com.zzw.fragmentt ...

  2. Android 常用炫酷控件(开源项目)git地址汇总

    第一部分 个性化控件(View) 主要介绍那些不错个性化的 View,包括 ListView.ActionBar.Menu.ViewPager.Gallery.GridView.ImageView.P ...

  3. css3制作炫酷导航栏效果

    今天主要利用hover选择器.鼠标滑过查看效果. 一.普通导航栏 Home Content Service Team Contact 对于这种普通的导航栏,只是鼠标滑过的时候颜色会变,所以思路变得很简 ...

  4. 炫酷:一句代码实现标题栏、导航栏滑动隐藏。ByeBurger库的使用和实现

    本文已授权微信公众号:鸿洋(hongyangAndroid)原创首发. 其实上周五的时候已经发过一篇文章.基本实现了底部导航栏隐藏的效果.但是使用起来可能不是很实用.因为之前我实现的方式是继承了系统的 ...

  5. Android绘图机制(四)——使用HelloCharts开源框架搭建一系列炫酷图表,柱形图,折线图,饼状图和动画特效,抽丝剥茧带你认识图表之美

    Android绘图机制(四)--使用HelloCharts开源框架搭建一系列炫酷图表,柱形图,折线图,饼状图和动画特效,抽丝剥茧带你认识图表之美 这里为什么不继续把自定义View写下去呢,因为最近项目 ...

  6. 开源分享三(炫酷的Android Loading动画)

    开源分享三(炫酷的Android Loading动画) 分享GitHub上的一些Loading,为了提升产品用户体验,一个好的Loading必然是不可缺少的,对于一些耗时需要用户等待的页面来说会转移用 ...

  7. 有了这个开源 Java 项目,开发出炫酷的小游戏好像不难?

    本文适合有 Java 基础知识的人群,跟着本文可学习和运行 Java 的游戏. 本文作者:HelloGitHub-秦人 HelloGitHub 推出的<讲解开源项目>系列,今天给大家带来一 ...

  8. [开源硬件DIY] 自制一款精致炫酷的蓝牙土壤温湿度传感器,用于做盆栽呵护类产品(API开放,开发者可自行DIY微信小程序\安卓IOS应用)

    目录 前言: 1. 成品展示 2. 原理图解析 3. pcb设计 4. 嵌入式对外提供接口 4.1 蓝牙广播 4.2 蓝牙服务和属性 4.3 数据包格式 4.4 数据通信模型 重要 . 前言: 本期给 ...

  9. Android一个炫酷的树状图组织架构图开源控件实现过程

    Android一个炫酷的树状图组织架构图开源控件 文章目录 [1 简介] [2 效果展示] [3 使用步骤] [4 实现基本布局流程] [5 实现自由放缩及拖动] [6 实现添加删除及节点动画] [7 ...

随机推荐

  1. java基础:父类与子类之间变量和方法的调用

    1)父类构造函数 java中当调用某个类的构造方法的时候,系统总会调用父类的非静态初始化块进行初始化,这个调用是隐式的,而且父类的静态初始化代码 块总是会被执行,接着调用父类的一个或者多个构造器执行初 ...

  2. [转]linux shell 流程控制(条件if,循环【for,while】,选择【case】语句实例

    原文链接:http://www.cnblogs.com/chengmo/archive/2010/10/14/1851434.html linux shell有一套自己的流程控制语句,其中包括条件语句 ...

  3. iOS 学习@autoreleasepool{}

    " ojc-c 是通过一种"referring counting"(引用计数)的方式来管理内存的, 对象在开始分配内存(alloc)的时候引用计数为一,以后每当碰到有al ...

  4. 生于MVP,死于PMF

    本文的主要内容会按照是什么.为什么以及如何做的逻辑展开,主要包括以下几部分: 什么是MVP与PMF: 为什么要有MVP与PMF: 如何创建MVP: 如何验证PMF. 什么是MVP与PMF MVP(Mi ...

  5. $Java正则表达式基础整理

    (一)正则表达式及语法简介 String类使用正则表达式的几个方法: 正则表达式支持的合法字符: 特殊字符: 预定义字符: 方括号表达式: 圆括号表达式:用于将多个表达式组成一个子表达式,可以使用或运 ...

  6. Mysql主从复制原理详解

    一.为什么要做主从同步 1.读写分离,降低对主数据库的IO消耗 2.避免数据丢失 3.提高业务系统性能 二.主从同步和集群的区别 1.主从同步 一般需要两台及以上数据库服务器即可(一台用于写入数据,一 ...

  7. C++使用命名空间中成员的三种方式

    通过简单的代码来介绍使用命名空间中成员的三种方式(我们最常用到的命名空间是是标准库std,下面的命名空间都以std为例): 使用作用域符:: #include<iostream> int ...

  8. Django 模板标签[转]

    Django 模板标签if/else 标签 基本语法格式如下: {% if condition %}     ... display{% endif %} 或者: {% if condition1 % ...

  9. jprofile查看hprof文件[转]

    用jprofile打开hprof文件,查看内存泄露情况,有几个常用的功能说明一下: 工具下载:到官网下载jprofile7.0.1 64位的.再申请一个注册号,注册号的申请好像是一个邮件只能用一次. ...

  10. js,java,ajax实现跨域访问及其原理

    http://blog.csdn.net/saytime/article/details/51540876 这篇文章对跨域访问做了较为细致得分析,我这里做下简单总结 1.实现跨域访问原理: 浏览器由于 ...