From 8dbb3ff36fe6f1e8d4b23985a5887c32286d3c2a Mon Sep 17 00:00:00 2001 From: keaideluren <513421345@qq.com> Date: Mon, 4 Dec 2017 17:00:07 +0800 Subject: [PATCH 1/5] set SegmentTabLayout indicator draggable --- .../flyco/tablayout/PullSegmentTabLayout.java | 846 ++++++++++++++++++ .../com/flyco/tablayout/SegmentTabLayout.java | 193 +++- .../src/main/res/values/attrs.xml | 3 + app/build.gradle | 11 +- .../ui/SegmentTabActivity.java | 2 + .../main/res/layout/activity_segment_tab.xml | 17 + 6 files changed, 1039 insertions(+), 33 deletions(-) create mode 100644 FlycoTabLayout_Lib/src/main/java/com/flyco/tablayout/PullSegmentTabLayout.java diff --git a/FlycoTabLayout_Lib/src/main/java/com/flyco/tablayout/PullSegmentTabLayout.java b/FlycoTabLayout_Lib/src/main/java/com/flyco/tablayout/PullSegmentTabLayout.java new file mode 100644 index 00000000..eda6d240 --- /dev/null +++ b/FlycoTabLayout_Lib/src/main/java/com/flyco/tablayout/PullSegmentTabLayout.java @@ -0,0 +1,846 @@ +package com.flyco.tablayout; + +import android.animation.TypeEvaluator; +import android.animation.ValueAnimator; +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.drawable.GradientDrawable; +import android.os.Bundle; +import android.os.Parcelable; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentActivity; +import android.util.AttributeSet; +import android.util.Log; +import android.util.SparseArray; +import android.util.TypedValue; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.view.animation.OvershootInterpolator; +import android.widget.FrameLayout; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.flyco.tablayout.listener.OnTabSelectListener; +import com.flyco.tablayout.utils.FragmentChangeManager; +import com.flyco.tablayout.utils.UnreadMsgUtils; +import com.flyco.tablayout.widget.MsgView; + +import java.util.ArrayList; + +public class PullSegmentTabLayout extends FrameLayout implements ValueAnimator.AnimatorUpdateListener { + private Context mContext; + private String[] mTitles; + private ViewGroup mTabsContainer; + private int mCurrentTab; + private int mLastTab; + private int mTabCount; + /** + * 用于绘制显示器 + */ + private Rect mIndicatorRect = new Rect(); + private GradientDrawable mIndicatorDrawable = new GradientDrawable(); + private GradientDrawable mRectDrawable = new GradientDrawable(); + + private Paint mDividerPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + + private float mTabPadding; + private boolean mTabSpaceEqual; + private float mTabWidth; + + /** + * indicator + */ + private int mIndicatorColor; + private float mIndicatorHeight; + private float mIndicatorCornerRadius; + private float mIndicatorMarginLeft; + private float mIndicatorMarginTop; + private float mIndicatorMarginRight; + private float mIndicatorMarginBottom; + private long mIndicatorAnimDuration; + private boolean mIndicatorAnimEnable; + private boolean mIndicatorBounceEnable; + + /** + * divider + */ + private int mDividerColor; + private float mDividerWidth; + private float mDividerPadding; + + /** + * title + */ + private static final int TEXT_BOLD_NONE = 0; + private static final int TEXT_BOLD_WHEN_SELECT = 1; + private static final int TEXT_BOLD_BOTH = 2; + private float mTextsize; + private int mTextSelectColor; + private int mTextUnselectColor; + private int mTextBold; + private boolean mTextAllCaps; + + private int mBarColor; + private int mBarStrokeColor; + private float mBarStrokeWidth; + + private int mHeight; + + /** + * anim + */ + private ValueAnimator mValueAnimator; + private OvershootInterpolator mInterpolator = new OvershootInterpolator(0.8f); + + private FragmentChangeManager mFragmentChangeManager; + private float[] mRadiusArr = new float[8]; + + public PullSegmentTabLayout(Context context) { + this(context, null, 0); + } + + public PullSegmentTabLayout(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public PullSegmentTabLayout(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + setWillNotDraw(false);//重写onDraw方法,需要调用这个方法来清除flag + setClipChildren(false); + setClipToPadding(false); + + this.mContext = context; + mTabsContainer = new LinearLayout(context); + setContainerTouchListener(); + addView(mTabsContainer); + + obtainAttributes(context, attrs); + + //get layout_height + String height = attrs.getAttributeValue("http://schemas.android.com/apk/res/android", "layout_height"); + + //create ViewPager + if (height.equals(ViewGroup.LayoutParams.MATCH_PARENT + "")) { + } else if (height.equals(ViewGroup.LayoutParams.WRAP_CONTENT + "")) { + } else { + int[] systemAttrs = {android.R.attr.layout_height}; + TypedArray a = context.obtainStyledAttributes(attrs, systemAttrs); + mHeight = a.getDimensionPixelSize(0, ViewGroup.LayoutParams.WRAP_CONTENT); + a.recycle(); + } + + mValueAnimator = ValueAnimator.ofObject(new PointEvaluator(), mLastP, mCurrentP); + mValueAnimator.addUpdateListener(this); + } + + /** + * 拖动效果需要设置外层窗口的touch事件 + */ + private void setContainerTouchListener() { + mTabsContainer.setOnTouchListener(new OnTouchListener() { + float xDown; + int rectLeftDown, rectRightDown, downPosition; + + @Override + public boolean onTouch(View view, MotionEvent motionEvent) { + switch (motionEvent.getAction()) { + case MotionEvent.ACTION_DOWN: + xDown = motionEvent.getX(); + rectLeftDown = mIndicatorRect.left; + rectRightDown = mIndicatorRect.right; + for (int i = 0; i < mTabsContainer.getChildCount(); i++) { + View child = mTabsContainer.getChildAt(i); + if (child.getLeft() <= motionEvent.getX() && child.getRight() > motionEvent.getX()) { + downPosition = (int) child.getTag(); + break; + } + } + Log.e("AAAAA", "按下:"); + break; + case MotionEvent.ACTION_MOVE: + if (downPosition == getCurrentTab()) { + mIndicatorRect.left = (int) (motionEvent.getX() - xDown + rectLeftDown); + mIndicatorRect.right = (int) (motionEvent.getX() - xDown + rectRightDown); + invalidate(); + } + Log.e("AAAAA", "滑动:"); + break; + case MotionEvent.ACTION_UP: + int position = 0; + if (motionEvent.getX() >= mTabsContainer.getRight()) { + position = getTabCount() - 1; + } else { + for (int i = 0; i < mTabsContainer.getChildCount(); i++) { + View child = mTabsContainer.getChildAt(i); + if (child.getLeft() <= motionEvent.getX() && child.getRight() > motionEvent.getX()) { + position = (int) child.getTag(); + break; + } + } + } + if (position != downPosition && downPosition != getCurrentTab()) { + //抬起和按下的不是同一个 + return true; + } + if (mCurrentTab != position) { + setCurrentTab(position); + if (mListener != null) { + mListener.onTabSelect(position); + } + } else { + if (mIndicatorAnimEnable) { + calcOffset(); + } else { + invalidate(); + } + if (mListener != null) { + mListener.onTabReselect(position); + } + } + Log.e("AAAAA", "抬起:"); + break; + } + return true; + } + }); + } + + private void obtainAttributes(Context context, AttributeSet attrs) { + TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SegmentTabLayout); + + mIndicatorColor = ta.getColor(R.styleable.SegmentTabLayout_tl_indicator_color, Color.parseColor("#222831")); + mIndicatorHeight = ta.getDimension(R.styleable.SegmentTabLayout_tl_indicator_height, -1); + mIndicatorCornerRadius = ta.getDimension(R.styleable.SegmentTabLayout_tl_indicator_corner_radius, -1); + mIndicatorMarginLeft = ta.getDimension(R.styleable.SegmentTabLayout_tl_indicator_margin_left, dp2px(0)); + mIndicatorMarginTop = ta.getDimension(R.styleable.SegmentTabLayout_tl_indicator_margin_top, 0); + mIndicatorMarginRight = ta.getDimension(R.styleable.SegmentTabLayout_tl_indicator_margin_right, dp2px(0)); + mIndicatorMarginBottom = ta.getDimension(R.styleable.SegmentTabLayout_tl_indicator_margin_bottom, 0); + mIndicatorAnimEnable = ta.getBoolean(R.styleable.SegmentTabLayout_tl_indicator_anim_enable, false); + mIndicatorBounceEnable = ta.getBoolean(R.styleable.SegmentTabLayout_tl_indicator_bounce_enable, true); + mIndicatorAnimDuration = ta.getInt(R.styleable.SegmentTabLayout_tl_indicator_anim_duration, -1); + + mDividerColor = ta.getColor(R.styleable.SegmentTabLayout_tl_divider_color, mIndicatorColor); + mDividerWidth = ta.getDimension(R.styleable.SegmentTabLayout_tl_divider_width, dp2px(1)); + mDividerPadding = ta.getDimension(R.styleable.SegmentTabLayout_tl_divider_padding, 0); + + mTextsize = ta.getDimension(R.styleable.SegmentTabLayout_tl_textsize, sp2px(13f)); + mTextSelectColor = ta.getColor(R.styleable.SegmentTabLayout_tl_textSelectColor, Color.parseColor("#ffffff")); + mTextUnselectColor = ta.getColor(R.styleable.SegmentTabLayout_tl_textUnselectColor, mIndicatorColor); + mTextBold = ta.getInt(R.styleable.SegmentTabLayout_tl_textBold, TEXT_BOLD_NONE); + mTextAllCaps = ta.getBoolean(R.styleable.SegmentTabLayout_tl_textAllCaps, false); + + mTabSpaceEqual = ta.getBoolean(R.styleable.SegmentTabLayout_tl_tab_space_equal, true); + mTabWidth = ta.getDimension(R.styleable.SegmentTabLayout_tl_tab_width, dp2px(-1)); + mTabPadding = ta.getDimension(R.styleable.SegmentTabLayout_tl_tab_padding, mTabSpaceEqual || mTabWidth > 0 ? dp2px(0) : dp2px(10)); + + mBarColor = ta.getColor(R.styleable.SegmentTabLayout_tl_bar_color, Color.TRANSPARENT); + mBarStrokeColor = ta.getColor(R.styleable.SegmentTabLayout_tl_bar_stroke_color, mIndicatorColor); + mBarStrokeWidth = ta.getDimension(R.styleable.SegmentTabLayout_tl_bar_stroke_width, dp2px(1)); + + ta.recycle(); + } + + public void setTabData(String[] titles) { + if (titles == null || titles.length == 0) { + throw new IllegalStateException("Titles can not be NULL or EMPTY !"); + } + + this.mTitles = titles; + + notifyDataSetChanged(); + } + + /** + * 关联数据支持同时切换fragments + */ + public void setTabData(String[] titles, FragmentActivity fa, int containerViewId, ArrayList fragments) { + mFragmentChangeManager = new FragmentChangeManager(fa.getSupportFragmentManager(), containerViewId, fragments); + setTabData(titles); + } + + /** + * 更新数据 + */ + public void notifyDataSetChanged() { + mTabsContainer.removeAllViews(); + this.mTabCount = mTitles.length; + View tabView; + for (int i = 0; i < mTabCount; i++) { + tabView = View.inflate(mContext, R.layout.layout_tab_segment, null); + tabView.setTag(i); + addTab(i, tabView); + } + + updateTabStyles(); + } + + /** + * 创建并添加tab + */ + private void addTab(final int position, View tabView) { + TextView tv_tab_title = (TextView) tabView.findViewById(R.id.tv_tab_title); + tv_tab_title.setText(mTitles[position]); + +// tabView.setOnClickListener(new OnClickListener() { +// @Override +// public void onClick(View v) { +// int position = (Integer) v.getTag(); +// if (mCurrentTab != position) { +// setCurrentTab(position); +// if (mListener != null) { +// mListener.onTabSelect(position); +// } +// } else { +// if (mListener != null) { +// mListener.onTabReselect(position); +// } +// } +// } +// }); + + /** 每一个Tab的布局参数 */ + LinearLayout.LayoutParams lp_tab = mTabSpaceEqual ? + new LinearLayout.LayoutParams(0, LayoutParams.MATCH_PARENT, 1.0f) : + new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT); + if (mTabWidth > 0) { + lp_tab = new LinearLayout.LayoutParams((int) mTabWidth, LayoutParams.MATCH_PARENT); + } + mTabsContainer.addView(tabView, position, lp_tab); + } + + private void updateTabStyles() { + for (int i = 0; i < mTabCount; i++) { + View tabView = mTabsContainer.getChildAt(i); + tabView.setPadding((int) mTabPadding, 0, (int) mTabPadding, 0); + TextView tv_tab_title = (TextView) tabView.findViewById(R.id.tv_tab_title); + tv_tab_title.setTextColor(i == mCurrentTab ? mTextSelectColor : mTextUnselectColor); + tv_tab_title.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTextsize); +// tv_tab_title.setPadding((int) mTabPadding, 0, (int) mTabPadding, 0); + if (mTextAllCaps) { + tv_tab_title.setText(tv_tab_title.getText().toString().toUpperCase()); + } + + if (mTextBold == TEXT_BOLD_BOTH) { + tv_tab_title.getPaint().setFakeBoldText(true); + } else if (mTextBold == TEXT_BOLD_NONE) { + tv_tab_title.getPaint().setFakeBoldText(false); + } + } + } + + private void updateTabSelection(int position) { + for (int i = 0; i < mTabCount; ++i) { + View tabView = mTabsContainer.getChildAt(i); + final boolean isSelect = i == position; + TextView tab_title = (TextView) tabView.findViewById(R.id.tv_tab_title); + tab_title.setTextColor(isSelect ? mTextSelectColor : mTextUnselectColor); + if (mTextBold == TEXT_BOLD_WHEN_SELECT) { + tab_title.getPaint().setFakeBoldText(isSelect); + } + } + } + + private void calcOffset() { + final View currentTabView = mTabsContainer.getChildAt(this.mCurrentTab); + mCurrentP.left = currentTabView.getLeft(); + mCurrentP.right = currentTabView.getRight(); + + +// final View lastTabView = mTabsContainer.getChildAt(this.mLastTab); + mLastP.left = mIndicatorRect.left; + mLastP.right = mIndicatorRect.right; +// Log.d("AAA", "mLastP--->" + mLastP.left + "&" + mLastP.right); +// Log.d("AAA", "mCurrentP--->" + mCurrentP.left + "&" + mCurrentP.right); + if (mLastP.left == mCurrentP.left && mLastP.right == mCurrentP.right) { + invalidate(); + } else { + mValueAnimator.setObjectValues(mLastP, mCurrentP); + if (mIndicatorBounceEnable) { + mValueAnimator.setInterpolator(mInterpolator); + } + + if (mIndicatorAnimDuration < 0) { + mIndicatorAnimDuration = mIndicatorBounceEnable ? 500 : 250; + } + mValueAnimator.setDuration(mIndicatorAnimDuration); + mValueAnimator.start(); + } + } + + private void calcIndicatorRect() { + View currentTabView = mTabsContainer.getChildAt(this.mCurrentTab); + float left = currentTabView.getLeft(); + float right = currentTabView.getRight(); + + mIndicatorRect.left = (int) left; + mIndicatorRect.right = (int) right; + + if (!mIndicatorAnimEnable) { + if (mCurrentTab == 0) { + /**The corners are ordered top-left, top-right, bottom-right, bottom-left*/ + mRadiusArr[0] = mIndicatorCornerRadius; + mRadiusArr[1] = mIndicatorCornerRadius; + mRadiusArr[2] = 0; + mRadiusArr[3] = 0; + mRadiusArr[4] = 0; + mRadiusArr[5] = 0; + mRadiusArr[6] = mIndicatorCornerRadius; + mRadiusArr[7] = mIndicatorCornerRadius; + } else if (mCurrentTab == mTabCount - 1) { + /**The corners are ordered top-left, top-right, bottom-right, bottom-left*/ + mRadiusArr[0] = 0; + mRadiusArr[1] = 0; + mRadiusArr[2] = mIndicatorCornerRadius; + mRadiusArr[3] = mIndicatorCornerRadius; + mRadiusArr[4] = mIndicatorCornerRadius; + mRadiusArr[5] = mIndicatorCornerRadius; + mRadiusArr[6] = 0; + mRadiusArr[7] = 0; + } else { + /**The corners are ordered top-left, top-right, bottom-right, bottom-left*/ + mRadiusArr[0] = 0; + mRadiusArr[1] = 0; + mRadiusArr[2] = 0; + mRadiusArr[3] = 0; + mRadiusArr[4] = 0; + mRadiusArr[5] = 0; + mRadiusArr[6] = 0; + mRadiusArr[7] = 0; + } + } else { + /**The corners are ordered top-left, top-right, bottom-right, bottom-left*/ + mRadiusArr[0] = mIndicatorCornerRadius; + mRadiusArr[1] = mIndicatorCornerRadius; + mRadiusArr[2] = mIndicatorCornerRadius; + mRadiusArr[3] = mIndicatorCornerRadius; + mRadiusArr[4] = mIndicatorCornerRadius; + mRadiusArr[5] = mIndicatorCornerRadius; + mRadiusArr[6] = mIndicatorCornerRadius; + mRadiusArr[7] = mIndicatorCornerRadius; + } + } + + @Override + public void onAnimationUpdate(ValueAnimator animation) { + IndicatorPoint p = (IndicatorPoint) animation.getAnimatedValue(); + mIndicatorRect.left = (int) p.left; + mIndicatorRect.right = (int) p.right; + invalidate(); + } + + private boolean mIsFirstDraw = true; + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + if (isInEditMode() || mTabCount <= 0) { + return; + } + + int height = getHeight(); + int paddingLeft = getPaddingLeft(); + + if (mIndicatorHeight < 0) { + mIndicatorHeight = height - mIndicatorMarginTop - mIndicatorMarginBottom; + } + + if (mIndicatorCornerRadius < 0 || mIndicatorCornerRadius > mIndicatorHeight / 2) { + mIndicatorCornerRadius = mIndicatorHeight / 2; + } + + //draw rect + mRectDrawable.setColor(mBarColor); + mRectDrawable.setStroke((int) mBarStrokeWidth, mBarStrokeColor); + mRectDrawable.setCornerRadius(mIndicatorCornerRadius); + mRectDrawable.setBounds(getPaddingLeft(), getPaddingTop(), getWidth() - getPaddingRight(), getHeight() - getPaddingBottom()); + mRectDrawable.draw(canvas); + + // draw divider + if (!mIndicatorAnimEnable && mDividerWidth > 0) { + mDividerPaint.setStrokeWidth(mDividerWidth); + mDividerPaint.setColor(mDividerColor); + for (int i = 0; i < mTabCount - 1; i++) { + View tab = mTabsContainer.getChildAt(i); + canvas.drawLine(paddingLeft + tab.getRight(), mDividerPadding, paddingLeft + tab.getRight(), height - mDividerPadding, mDividerPaint); + } + } + + + //draw indicator line + if (mIndicatorAnimEnable) { + if (mIsFirstDraw) { + mIsFirstDraw = false; + calcIndicatorRect(); + } + } else { + calcIndicatorRect(); + } + + mIndicatorDrawable.setColor(mIndicatorColor); + mIndicatorDrawable.setBounds(paddingLeft + (int) mIndicatorMarginLeft + mIndicatorRect.left, + (int) mIndicatorMarginTop, (int) (paddingLeft + mIndicatorRect.right - mIndicatorMarginRight), + (int) (mIndicatorMarginTop + mIndicatorHeight)); + mIndicatorDrawable.setCornerRadii(mRadiusArr); + mIndicatorDrawable.draw(canvas); + + } + + //setter and getter + public void setCurrentTab(int currentTab) { + mLastTab = this.mCurrentTab; + this.mCurrentTab = currentTab; + updateTabSelection(currentTab); + if (mFragmentChangeManager != null) { + mFragmentChangeManager.setFragments(currentTab); + } + if (mIndicatorAnimEnable) { + calcOffset(); + } else { + invalidate(); + } + } + + public void setTabPadding(float tabPadding) { + this.mTabPadding = dp2px(tabPadding); + updateTabStyles(); + } + + public void setTabSpaceEqual(boolean tabSpaceEqual) { + this.mTabSpaceEqual = tabSpaceEqual; + updateTabStyles(); + } + + public void setTabWidth(float tabWidth) { + this.mTabWidth = dp2px(tabWidth); + updateTabStyles(); + } + + public void setIndicatorColor(int indicatorColor) { + this.mIndicatorColor = indicatorColor; + invalidate(); + } + + public void setIndicatorHeight(float indicatorHeight) { + this.mIndicatorHeight = dp2px(indicatorHeight); + invalidate(); + } + + public void setIndicatorCornerRadius(float indicatorCornerRadius) { + this.mIndicatorCornerRadius = dp2px(indicatorCornerRadius); + invalidate(); + } + + public void setIndicatorMargin(float indicatorMarginLeft, float indicatorMarginTop, + float indicatorMarginRight, float indicatorMarginBottom) { + this.mIndicatorMarginLeft = dp2px(indicatorMarginLeft); + this.mIndicatorMarginTop = dp2px(indicatorMarginTop); + this.mIndicatorMarginRight = dp2px(indicatorMarginRight); + this.mIndicatorMarginBottom = dp2px(indicatorMarginBottom); + invalidate(); + } + + public void setIndicatorAnimDuration(long indicatorAnimDuration) { + this.mIndicatorAnimDuration = indicatorAnimDuration; + } + + public void setIndicatorAnimEnable(boolean indicatorAnimEnable) { + this.mIndicatorAnimEnable = indicatorAnimEnable; + } + + public void setIndicatorBounceEnable(boolean indicatorBounceEnable) { + this.mIndicatorBounceEnable = indicatorBounceEnable; + } + + public void setDividerColor(int dividerColor) { + this.mDividerColor = dividerColor; + invalidate(); + } + + public void setDividerWidth(float dividerWidth) { + this.mDividerWidth = dp2px(dividerWidth); + invalidate(); + } + + public void setDividerPadding(float dividerPadding) { + this.mDividerPadding = dp2px(dividerPadding); + invalidate(); + } + + public void setTextsize(float textsize) { + this.mTextsize = sp2px(textsize); + updateTabStyles(); + } + + public void setTextSelectColor(int textSelectColor) { + this.mTextSelectColor = textSelectColor; + updateTabStyles(); + } + + public void setTextUnselectColor(int textUnselectColor) { + this.mTextUnselectColor = textUnselectColor; + updateTabStyles(); + } + + public void setTextBold(int textBold) { + this.mTextBold = textBold; + updateTabStyles(); + } + + public void setTextAllCaps(boolean textAllCaps) { + this.mTextAllCaps = textAllCaps; + updateTabStyles(); + } + + public int getTabCount() { + return mTabCount; + } + + public int getCurrentTab() { + return mCurrentTab; + } + + public float getTabPadding() { + return mTabPadding; + } + + public boolean isTabSpaceEqual() { + return mTabSpaceEqual; + } + + public float getTabWidth() { + return mTabWidth; + } + + public int getIndicatorColor() { + return mIndicatorColor; + } + + public float getIndicatorHeight() { + return mIndicatorHeight; + } + + public float getIndicatorCornerRadius() { + return mIndicatorCornerRadius; + } + + public float getIndicatorMarginLeft() { + return mIndicatorMarginLeft; + } + + public float getIndicatorMarginTop() { + return mIndicatorMarginTop; + } + + public float getIndicatorMarginRight() { + return mIndicatorMarginRight; + } + + public float getIndicatorMarginBottom() { + return mIndicatorMarginBottom; + } + + public long getIndicatorAnimDuration() { + return mIndicatorAnimDuration; + } + + public boolean isIndicatorAnimEnable() { + return mIndicatorAnimEnable; + } + + public boolean isIndicatorBounceEnable() { + return mIndicatorBounceEnable; + } + + public int getDividerColor() { + return mDividerColor; + } + + public float getDividerWidth() { + return mDividerWidth; + } + + public float getDividerPadding() { + return mDividerPadding; + } + + public float getTextsize() { + return mTextsize; + } + + public int getTextSelectColor() { + return mTextSelectColor; + } + + public int getTextUnselectColor() { + return mTextUnselectColor; + } + + public int getTextBold() { + return mTextBold; + } + + public boolean isTextAllCaps() { + return mTextAllCaps; + } + + public TextView getTitleView(int tab) { + View tabView = mTabsContainer.getChildAt(tab); + TextView tv_tab_title = (TextView) tabView.findViewById(R.id.tv_tab_title); + return tv_tab_title; + } + + //setter and getter + // show MsgTipView + private Paint mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private SparseArray mInitSetMap = new SparseArray<>(); + + /** + * 显示未读消息 + * + * @param position 显示tab位置 + * @param num num小于等于0显示红点,num大于0显示数字 + */ + public void showMsg(int position, int num) { + if (position >= mTabCount) { + position = mTabCount - 1; + } + + View tabView = mTabsContainer.getChildAt(position); + MsgView tipView = (MsgView) tabView.findViewById(R.id.rtv_msg_tip); + if (tipView != null) { + UnreadMsgUtils.show(tipView, num); + + if (mInitSetMap.get(position) != null && mInitSetMap.get(position)) { + return; + } + + setMsgMargin(position, 2, 2); + + mInitSetMap.put(position, true); + } + } + + /** + * 显示未读红点 + * + * @param position 显示tab位置 + */ + public void showDot(int position) { + if (position >= mTabCount) { + position = mTabCount - 1; + } + showMsg(position, 0); + } + + public void hideMsg(int position) { + if (position >= mTabCount) { + position = mTabCount - 1; + } + + View tabView = mTabsContainer.getChildAt(position); + MsgView tipView = (MsgView) tabView.findViewById(R.id.rtv_msg_tip); + if (tipView != null) { + tipView.setVisibility(View.GONE); + } + } + + /** + * 设置提示红点偏移,注意 + * 1.控件为固定高度:参照点为tab内容的右上角 + * 2.控件高度不固定(WRAP_CONTENT):参照点为tab内容的右上角,此时高度已是红点的最高显示范围,所以这时bottomPadding其实就是topPadding + */ + public void setMsgMargin(int position, float leftPadding, float bottomPadding) { + if (position >= mTabCount) { + position = mTabCount - 1; + } + View tabView = mTabsContainer.getChildAt(position); + MsgView tipView = (MsgView) tabView.findViewById(R.id.rtv_msg_tip); + if (tipView != null) { + TextView tv_tab_title = (TextView) tabView.findViewById(R.id.tv_tab_title); + mTextPaint.setTextSize(mTextsize); + float textWidth = mTextPaint.measureText(tv_tab_title.getText().toString()); + float textHeight = mTextPaint.descent() - mTextPaint.ascent(); + MarginLayoutParams lp = (MarginLayoutParams) tipView.getLayoutParams(); + + lp.leftMargin = dp2px(leftPadding); + lp.topMargin = mHeight > 0 ? (int) (mHeight - textHeight) / 2 - dp2px(bottomPadding) : dp2px(bottomPadding); + + tipView.setLayoutParams(lp); + } + } + + /** + * 当前类只提供了少许设置未读消息属性的方法,可以通过该方法获取MsgView对象从而各种设置 + */ + public MsgView getMsgView(int position) { + if (position >= mTabCount) { + position = mTabCount - 1; + } + View tabView = mTabsContainer.getChildAt(position); + MsgView tipView = (MsgView) tabView.findViewById(R.id.rtv_msg_tip); + return tipView; + } + + private OnTabSelectListener mListener; + + public void setOnTabSelectListener(OnTabSelectListener listener) { + this.mListener = listener; + } + + @Override + protected Parcelable onSaveInstanceState() { + Bundle bundle = new Bundle(); + bundle.putParcelable("instanceState", super.onSaveInstanceState()); + bundle.putInt("mCurrentTab", mCurrentTab); + return bundle; + } + + @Override + protected void onRestoreInstanceState(Parcelable state) { + if (state instanceof Bundle) { + Bundle bundle = (Bundle) state; + mCurrentTab = bundle.getInt("mCurrentTab"); + state = bundle.getParcelable("instanceState"); + if (mCurrentTab != 0 && mTabsContainer.getChildCount() > 0) { + updateTabSelection(mCurrentTab); + } + } + super.onRestoreInstanceState(state); + } + + class IndicatorPoint { + public float left; + public float right; + } + + private IndicatorPoint mCurrentP = new IndicatorPoint(); + private IndicatorPoint mLastP = new IndicatorPoint(); + + class PointEvaluator implements TypeEvaluator { + @Override + public IndicatorPoint evaluate(float fraction, IndicatorPoint startValue, IndicatorPoint endValue) { + float left = startValue.left + fraction * (endValue.left - startValue.left); + float right = startValue.right + fraction * (endValue.right - startValue.right); + IndicatorPoint point = new IndicatorPoint(); + point.left = left; + point.right = right; + return point; + } + } + + protected int dp2px(float dp) { + final float scale = mContext.getResources().getDisplayMetrics().density; + return (int) (dp * scale + 0.5f); + } + + protected int sp2px(float sp) { + final float scale = this.mContext.getResources().getDisplayMetrics().scaledDensity; + return (int) (sp * scale + 0.5f); + } +} diff --git a/FlycoTabLayout_Lib/src/main/java/com/flyco/tablayout/SegmentTabLayout.java b/FlycoTabLayout_Lib/src/main/java/com/flyco/tablayout/SegmentTabLayout.java index e9df2953..54d3d00c 100644 --- a/FlycoTabLayout_Lib/src/main/java/com/flyco/tablayout/SegmentTabLayout.java +++ b/FlycoTabLayout_Lib/src/main/java/com/flyco/tablayout/SegmentTabLayout.java @@ -16,6 +16,7 @@ import android.util.AttributeSet; import android.util.SparseArray; import android.util.TypedValue; +import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.animation.OvershootInterpolator; @@ -33,11 +34,13 @@ public class SegmentTabLayout extends FrameLayout implements ValueAnimator.AnimatorUpdateListener { private Context mContext; private String[] mTitles; - private LinearLayout mTabsContainer; + private ViewGroup mTabsContainer; private int mCurrentTab; private int mLastTab; private int mTabCount; - /** 用于绘制显示器 */ + /** + * 用于绘制显示器 + */ private Rect mIndicatorRect = new Rect(); private GradientDrawable mIndicatorDrawable = new GradientDrawable(); private GradientDrawable mRectDrawable = new GradientDrawable(); @@ -48,7 +51,9 @@ public class SegmentTabLayout extends FrameLayout implements ValueAnimator.Anima private boolean mTabSpaceEqual; private float mTabWidth; - /** indicator */ + /** + * indicator + */ private int mIndicatorColor; private float mIndicatorHeight; private float mIndicatorCornerRadius; @@ -59,13 +64,18 @@ public class SegmentTabLayout extends FrameLayout implements ValueAnimator.Anima private long mIndicatorAnimDuration; private boolean mIndicatorAnimEnable; private boolean mIndicatorBounceEnable; + private boolean mIndicatorDraggable; - /** divider */ + /** + * divider + */ private int mDividerColor; private float mDividerWidth; private float mDividerPadding; - /** title */ + /** + * title + */ private static final int TEXT_BOLD_NONE = 0; private static final int TEXT_BOLD_WHEN_SELECT = 1; private static final int TEXT_BOLD_BOTH = 2; @@ -81,7 +91,9 @@ public class SegmentTabLayout extends FrameLayout implements ValueAnimator.Anima private int mHeight; - /** anim */ + /** + * anim + */ private ValueAnimator mValueAnimator; private OvershootInterpolator mInterpolator = new OvershootInterpolator(0.8f); @@ -108,6 +120,8 @@ public SegmentTabLayout(Context context, AttributeSet attrs, int defStyleAttr) { obtainAttributes(context, attrs); + setContainerTouchListener(); + //get layout_height String height = attrs.getAttributeValue("http://schemas.android.com/apk/res/android", "layout_height"); @@ -138,6 +152,7 @@ private void obtainAttributes(Context context, AttributeSet attrs) { mIndicatorAnimEnable = ta.getBoolean(R.styleable.SegmentTabLayout_tl_indicator_anim_enable, false); mIndicatorBounceEnable = ta.getBoolean(R.styleable.SegmentTabLayout_tl_indicator_bounce_enable, true); mIndicatorAnimDuration = ta.getInt(R.styleable.SegmentTabLayout_tl_indicator_anim_duration, -1); + mIndicatorDraggable = ta.getBoolean(R.styleable.SegmentTabLayout_tl_indicator_draggable, false); mDividerColor = ta.getColor(R.styleable.SegmentTabLayout_tl_divider_color, mIndicatorColor); mDividerWidth = ta.getDimension(R.styleable.SegmentTabLayout_tl_divider_width, dp2px(1)); @@ -170,13 +185,17 @@ public void setTabData(String[] titles) { notifyDataSetChanged(); } - /** 关联数据支持同时切换fragments */ + /** + * 关联数据支持同时切换fragments + */ public void setTabData(String[] titles, FragmentActivity fa, int containerViewId, ArrayList fragments) { mFragmentChangeManager = new FragmentChangeManager(fa.getSupportFragmentManager(), containerViewId, fragments); setTabData(titles); } - /** 更新数据 */ + /** + * 更新数据 + */ public void notifyDataSetChanged() { mTabsContainer.removeAllViews(); this.mTabCount = mTitles.length; @@ -190,27 +209,34 @@ public void notifyDataSetChanged() { updateTabStyles(); } - /** 创建并添加tab */ + /** + * 创建并添加tab + */ private void addTab(final int position, View tabView) { TextView tv_tab_title = (TextView) tabView.findViewById(R.id.tv_tab_title); tv_tab_title.setText(mTitles[position]); - tabView.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - int position = (Integer) v.getTag(); - if (mCurrentTab != position) { - setCurrentTab(position); - if (mListener != null) { - mListener.onTabSelect(position); - } - } else { - if (mListener != null) { - mListener.onTabReselect(position); + //click会消费掉事件,让外层的touch拖动无效 + if (!mIndicatorDraggable) { + tabView.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + int position = (Integer) v.getTag(); + if (mCurrentTab != position) { + setCurrentTab(position); + if (mListener != null) { + mListener.onTabSelect(position); + } + } else { + if (mListener != null) { + mListener.onTabReselect(position); + } } } - } - }); + }); + } else { + tabView.setClickable(false); + } /** 每一个Tab的布局参数 */ LinearLayout.LayoutParams lp_tab = mTabSpaceEqual ? @@ -259,9 +285,8 @@ private void calcOffset() { mCurrentP.left = currentTabView.getLeft(); mCurrentP.right = currentTabView.getRight(); - final View lastTabView = mTabsContainer.getChildAt(this.mLastTab); - mLastP.left = lastTabView.getLeft(); - mLastP.right = lastTabView.getRight(); + mLastP.left = mIndicatorRect.left; + mLastP.right = mIndicatorRect.right; // Log.d("AAA", "mLastP--->" + mLastP.left + "&" + mLastP.right); // Log.d("AAA", "mCurrentP--->" + mCurrentP.left + "&" + mCurrentP.right); @@ -334,6 +359,109 @@ private void calcIndicatorRect() { } } + /** + * 拖动效果需要设置外层窗口的touch事件 + */ + private void setContainerTouchListener() { + //两种listener只能存在一个,反正只能有一个能消费事件嘛,一个消费了,另一个就没了,很好理解 + if (mIndicatorDraggable) { + mTabsContainer.setOnTouchListener(new OnTouchListener() { + float xDown; + int rectLeftDown, rectRightDown, downPosition; + + @Override + public boolean onTouch(View view, MotionEvent motionEvent) { + switch (motionEvent.getAction()) { + case MotionEvent.ACTION_DOWN: + xDown = motionEvent.getX(); + rectLeftDown = mIndicatorRect.left; + rectRightDown = mIndicatorRect.right; + for (int i = 0; i < mTabsContainer.getChildCount(); i++) { + View child = mTabsContainer.getChildAt(i); + if (child.getLeft() <= motionEvent.getX() && child.getRight() > motionEvent.getX()) { + downPosition = (int) child.getTag(); + break; + } + } + break; + case MotionEvent.ACTION_MOVE: + if (downPosition == getCurrentTab()) { + mIndicatorRect.left = (int) (motionEvent.getX() - xDown + rectLeftDown); + mIndicatorRect.right = (int) (motionEvent.getX() - xDown + rectRightDown); + invalidate(); + } + break; + case MotionEvent.ACTION_UP: + int position = 0; + if (motionEvent.getX() > mTabsContainer.getChildAt(getTabCount() - 1).getRight()) { + position = getTabCount() - 1; + } else if (motionEvent.getX() < mTabsContainer.getChildAt(0).getLeft()) { + position = 0; + } else { + for (int i = 0; i < getTabCount(); i++) { + View child = mTabsContainer.getChildAt(i); + if (child.getLeft() <= motionEvent.getX() && child.getRight() > motionEvent.getX()) { + position = (int) child.getTag(); + break; + } + if (i == getTabCount() - 1) { + position = getTabCount() - 1; + } + } + } + if (position != downPosition && downPosition != getCurrentTab()) { + //抬起和按下的不是同一个 + return true; + } + if (mCurrentTab != position) { + setCurrentTab(position); + if (mListener != null) { + mListener.onTabSelect(position); + } + } else { + if (mIndicatorAnimEnable) { + calcOffset(); + } else { + invalidate(); + } + if (mListener != null) { + mListener.onTabReselect(position); + } + } + break; + } + return true; + } + }); + for (int i = 0; i < mTabsContainer.getChildCount(); i++) { + View v = mTabsContainer.getChildAt(i); + v.setClickable(false); + } + } else { + mTabsContainer.setOnTouchListener(null); + for (int i = 0; i < mTabsContainer.getChildCount(); i++) { + View tabView = mTabsContainer.getChildAt(i); + tabView.setOnClickListener(null); + tabView.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + int position = (Integer) v.getTag(); + if (mCurrentTab != position) { + setCurrentTab(position); + if (mListener != null) { + mListener.onTabSelect(position); + } + } else { + if (mListener != null) { + mListener.onTabReselect(position); + } + } + } + }); + } + } + } + @Override public void onAnimationUpdate(ValueAnimator animation) { IndicatorPoint p = (IndicatorPoint) animation.getAnimatedValue(); @@ -598,6 +726,15 @@ public boolean isTextAllCaps() { return mTextAllCaps; } + public boolean ismIndicatorDraggable() { + return mIndicatorDraggable; + } + + public void setmIndicatorDraggable(boolean mIndicatorDraggable) { + this.mIndicatorDraggable = mIndicatorDraggable; + setContainerTouchListener(); + } + public TextView getTitleView(int tab) { View tabView = mTabsContainer.getChildAt(tab); TextView tv_tab_title = (TextView) tabView.findViewById(R.id.tv_tab_title); @@ -684,7 +821,9 @@ public void setMsgMargin(int position, float leftPadding, float bottomPadding) { } } - /** 当前类只提供了少许设置未读消息属性的方法,可以通过该方法获取MsgView对象从而各种设置 */ + /** + * 当前类只提供了少许设置未读消息属性的方法,可以通过该方法获取MsgView对象从而各种设置 + */ public MsgView getMsgView(int position) { if (position >= mTabCount) { position = mTabCount - 1; diff --git a/FlycoTabLayout_Lib/src/main/res/values/attrs.xml b/FlycoTabLayout_Lib/src/main/res/values/attrs.xml index b0afdbee..912be4c6 100644 --- a/FlycoTabLayout_Lib/src/main/res/values/attrs.xml +++ b/FlycoTabLayout_Lib/src/main/res/values/attrs.xml @@ -33,6 +33,8 @@ + + @@ -184,6 +186,7 @@ + diff --git a/app/build.gradle b/app/build.gradle index f2f86d4d..37ace998 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -20,13 +20,12 @@ android { } dependencies { - compile fileTree(dir: 'libs', include: ['*.jar']) + compile fileTree(include: ['*.jar'], dir: 'libs') compile 'com.android.support:appcompat-v7:25.1.0' -// compile project(':FlycoTabLayout_Lib') - + // compile project(':FlycoTabLayout_Lib') //--->support 3.0+ - compile 'com.flyco.tablayout:FlycoTabLayout_Lib:2.1.2@aar' //--->support 2.2+ -// compile 'com.flyco.tablayout:FlycoTabLayout_Lib:2.0.0@aar' -// compile 'com.nineoldandroids:library:2.4.0' + // compile 'com.flyco.tablayout:FlycoTabLayout_Lib:2.0.0@aar' + // compile 'com.nineoldandroids:library:2.4.0' + compile project(':FlycoTabLayout_Lib') } diff --git a/app/src/main/java/com/flyco/tablayoutsamples/ui/SegmentTabActivity.java b/app/src/main/java/com/flyco/tablayoutsamples/ui/SegmentTabActivity.java index 9ac154cc..53419fcc 100644 --- a/app/src/main/java/com/flyco/tablayoutsamples/ui/SegmentTabActivity.java +++ b/app/src/main/java/com/flyco/tablayoutsamples/ui/SegmentTabActivity.java @@ -47,12 +47,14 @@ protected void onCreate(Bundle savedInstanceState) { mTabLayout_3 = ViewFindUtils.find(mDecorView, R.id.tl_3); SegmentTabLayout tabLayout_4 = ViewFindUtils.find(mDecorView, R.id.tl_4); SegmentTabLayout tabLayout_5 = ViewFindUtils.find(mDecorView, R.id.tl_5); + SegmentTabLayout tabLayout_6 = ViewFindUtils.find(mDecorView, R.id.tl_6); tabLayout_1.setTabData(mTitles); tabLayout_2.setTabData(mTitles_2); tl_3(); tabLayout_4.setTabData(mTitles_2, this, R.id.fl_change, mFragments2); tabLayout_5.setTabData(mTitles_3); + tabLayout_6.setTabData(mTitles_3); //显示未读红点 tabLayout_1.showDot(2); diff --git a/app/src/main/res/layout/activity_segment_tab.xml b/app/src/main/res/layout/activity_segment_tab.xml index 81b27eca..0165488c 100644 --- a/app/src/main/res/layout/activity_segment_tab.xml +++ b/app/src/main/res/layout/activity_segment_tab.xml @@ -48,6 +48,7 @@ tl:tl_indicator_margin_bottom="2dp" tl:tl_indicator_margin_left="2dp" tl:tl_indicator_margin_right="2dp" + tl:tl_indicator_draggable="true" tl:tl_indicator_margin_top="2dp" tl:tl_textBold="SELECT"/> @@ -91,5 +92,21 @@ tl:tl_indicator_margin_right="2dp" tl:tl_indicator_margin_top="2dp" tl:tl_tab_space_equal="true"/> + + \ No newline at end of file From f0accdd7fbcfddf30421ae164d33ef1d8a551159 Mon Sep 17 00:00:00 2001 From: keaideluren <513421345@qq.com> Date: Mon, 4 Dec 2017 17:07:47 +0800 Subject: [PATCH 2/5] set SegmentTabLayout indicator draggable --- .../src/main/java/com/flyco/tablayout/SegmentTabLayout.java | 1 - 1 file changed, 1 deletion(-) diff --git a/FlycoTabLayout_Lib/src/main/java/com/flyco/tablayout/SegmentTabLayout.java b/FlycoTabLayout_Lib/src/main/java/com/flyco/tablayout/SegmentTabLayout.java index 54d3d00c..4ad8e443 100644 --- a/FlycoTabLayout_Lib/src/main/java/com/flyco/tablayout/SegmentTabLayout.java +++ b/FlycoTabLayout_Lib/src/main/java/com/flyco/tablayout/SegmentTabLayout.java @@ -441,7 +441,6 @@ public boolean onTouch(View view, MotionEvent motionEvent) { mTabsContainer.setOnTouchListener(null); for (int i = 0; i < mTabsContainer.getChildCount(); i++) { View tabView = mTabsContainer.getChildAt(i); - tabView.setOnClickListener(null); tabView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { From a4899b9bac9ce3c832bc199eb3d94b818ca00cd1 Mon Sep 17 00:00:00 2001 From: fengxinlin Date: Thu, 16 Aug 2018 09:55:58 +0800 Subject: [PATCH 3/5] =?UTF-8?q?=E4=BA=8B=E4=BB=B6=E5=8F=AF=E6=B6=88?= =?UTF-8?q?=E8=B4=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FlycoTabLayout_Lib/build.gradle | 12 ++-- .../com/flyco/tablayout/CommonTabLayout.java | 55 ++++++++++++++----- .../flyco/tablayout/PullSegmentTabLayout.java | 7 ++- .../com/flyco/tablayout/SegmentTabLayout.java | 21 +++++-- .../com/flyco/tablayout/SlidingTabLayout.java | 10 ++-- .../listener/OnTabSelectListener.java | 8 ++- app/build.gradle | 14 ++--- build.gradle | 4 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 9 files changed, 89 insertions(+), 44 deletions(-) diff --git a/FlycoTabLayout_Lib/build.gradle b/FlycoTabLayout_Lib/build.gradle index 166f8c62..009e0395 100644 --- a/FlycoTabLayout_Lib/build.gradle +++ b/FlycoTabLayout_Lib/build.gradle @@ -5,12 +5,12 @@ apply plugin: 'com.android.library' // 这个version是区分library版本的,因此当我们需要更新library时记得修改这个version version = "2.1.2" android { - compileSdkVersion 25 - buildToolsVersion "25.0.1" + compileSdkVersion 27 + buildToolsVersion '27.0.3' defaultConfig { - minSdkVersion 11 - targetSdkVersion 25 + minSdkVersion 14 + targetSdkVersion 27 versionCode 212 versionName version } @@ -23,8 +23,8 @@ android { } dependencies { - compile fileTree(dir: 'libs', include: ['*.jar']) - compile 'com.android.support:support-v4:25.1.0' + api fileTree(dir: 'libs', include: ['*.jar']) + implementation 'com.android.support:support-v4:27.1.1' } //def siteUrl = 'https://github.com/H07000223' // 项目的主页 diff --git a/FlycoTabLayout_Lib/src/main/java/com/flyco/tablayout/CommonTabLayout.java b/FlycoTabLayout_Lib/src/main/java/com/flyco/tablayout/CommonTabLayout.java index b0db9cd1..f7a08aa3 100644 --- a/FlycoTabLayout_Lib/src/main/java/com/flyco/tablayout/CommonTabLayout.java +++ b/FlycoTabLayout_Lib/src/main/java/com/flyco/tablayout/CommonTabLayout.java @@ -34,7 +34,9 @@ import java.util.ArrayList; -/** 没有继承HorizontalScrollView不能滑动,对于ViewPager无依赖 */ +/** + * 没有继承HorizontalScrollView不能滑动,对于ViewPager无依赖 + */ public class CommonTabLayout extends FrameLayout implements ValueAnimator.AnimatorUpdateListener { private Context mContext; private ArrayList mTabEntitys = new ArrayList<>(); @@ -42,7 +44,9 @@ public class CommonTabLayout extends FrameLayout implements ValueAnimator.Animat private int mCurrentTab; private int mLastTab; private int mTabCount; - /** 用于绘制显示器 */ + /** + * 用于绘制显示器 + */ private Rect mIndicatorRect = new Rect(); private GradientDrawable mIndicatorDrawable = new GradientDrawable(); @@ -59,7 +63,9 @@ public class CommonTabLayout extends FrameLayout implements ValueAnimator.Animat private boolean mTabSpaceEqual; private float mTabWidth; - /** indicator */ + /** + * indicator + */ private int mIndicatorColor; private float mIndicatorHeight; private float mIndicatorWidth; @@ -73,17 +79,23 @@ public class CommonTabLayout extends FrameLayout implements ValueAnimator.Animat private boolean mIndicatorBounceEnable; private int mIndicatorGravity; - /** underline */ + /** + * underline + */ private int mUnderlineColor; private float mUnderlineHeight; private int mUnderlineGravity; - /** divider */ + /** + * divider + */ private int mDividerColor; private float mDividerWidth; private float mDividerPadding; - /** title */ + /** + * title + */ private static final int TEXT_BOLD_NONE = 0; private static final int TEXT_BOLD_WHEN_SELECT = 1; private static final int TEXT_BOLD_BOTH = 2; @@ -93,7 +105,9 @@ public class CommonTabLayout extends FrameLayout implements ValueAnimator.Animat private int mTextBold; private boolean mTextAllCaps; - /** icon */ + /** + * icon + */ private boolean mIconVisible; private int mIconGravity; private float mIconWidth; @@ -102,7 +116,9 @@ public class CommonTabLayout extends FrameLayout implements ValueAnimator.Animat private int mHeight; - /** anim */ + /** + * anim + */ private ValueAnimator mValueAnimator; private OvershootInterpolator mInterpolator = new OvershootInterpolator(1.5f); @@ -201,13 +217,17 @@ public void setTabData(ArrayList tabEntitys) { notifyDataSetChanged(); } - /** 关联数据支持同时切换fragments */ + /** + * 关联数据支持同时切换fragments + */ public void setTabData(ArrayList tabEntitys, FragmentActivity fa, int containerViewId, ArrayList fragments) { mFragmentChangeManager = new FragmentChangeManager(fa.getSupportFragmentManager(), containerViewId, fragments); setTabData(tabEntitys); } - /** 更新数据 */ + /** + * 更新数据 + */ public void notifyDataSetChanged() { mTabsContainer.removeAllViews(); this.mTabCount = mTabEntitys.size(); @@ -230,7 +250,9 @@ public void notifyDataSetChanged() { updateTabStyles(); } - /** 创建并添加tab */ + /** + * 创建并添加tab + */ private void addTab(final int position, View tabView) { TextView tv_tab_title = (TextView) tabView.findViewById(R.id.tv_tab_title); tv_tab_title.setText(mTabEntitys.get(position).getTabTitle()); @@ -242,9 +264,12 @@ private void addTab(final int position, View tabView) { public void onClick(View v) { int position = (Integer) v.getTag(); if (mCurrentTab != position) { - setCurrentTab(position); + boolean b = false; if (mListener != null) { - mListener.onTabSelect(position); + b = mListener.onTabSelect(position); + } + if (!b) { + setCurrentTab(position); } } else { if (mListener != null) { @@ -885,7 +910,9 @@ public void setMsgMargin(int position, float leftPadding, float bottomPadding) { } } - /** 当前类只提供了少许设置未读消息属性的方法,可以通过该方法获取MsgView对象从而各种设置 */ + /** + * 当前类只提供了少许设置未读消息属性的方法,可以通过该方法获取MsgView对象从而各种设置 + */ public MsgView getMsgView(int position) { if (position >= mTabCount) { position = mTabCount - 1; diff --git a/FlycoTabLayout_Lib/src/main/java/com/flyco/tablayout/PullSegmentTabLayout.java b/FlycoTabLayout_Lib/src/main/java/com/flyco/tablayout/PullSegmentTabLayout.java index eda6d240..17ee2f1a 100644 --- a/FlycoTabLayout_Lib/src/main/java/com/flyco/tablayout/PullSegmentTabLayout.java +++ b/FlycoTabLayout_Lib/src/main/java/com/flyco/tablayout/PullSegmentTabLayout.java @@ -188,9 +188,12 @@ public boolean onTouch(View view, MotionEvent motionEvent) { return true; } if (mCurrentTab != position) { - setCurrentTab(position); + boolean b = false; if (mListener != null) { - mListener.onTabSelect(position); + b = mListener.onTabSelect(position); + } + if (!b) { + setCurrentTab(position); } } else { if (mIndicatorAnimEnable) { diff --git a/FlycoTabLayout_Lib/src/main/java/com/flyco/tablayout/SegmentTabLayout.java b/FlycoTabLayout_Lib/src/main/java/com/flyco/tablayout/SegmentTabLayout.java index 4ad8e443..14843a6e 100644 --- a/FlycoTabLayout_Lib/src/main/java/com/flyco/tablayout/SegmentTabLayout.java +++ b/FlycoTabLayout_Lib/src/main/java/com/flyco/tablayout/SegmentTabLayout.java @@ -223,9 +223,12 @@ private void addTab(final int position, View tabView) { public void onClick(View v) { int position = (Integer) v.getTag(); if (mCurrentTab != position) { - setCurrentTab(position); + boolean b = false; if (mListener != null) { - mListener.onTabSelect(position); + b = mListener.onTabSelect(position); + } + if (!b) { + setCurrentTab(position); } } else { if (mListener != null) { @@ -414,9 +417,12 @@ public boolean onTouch(View view, MotionEvent motionEvent) { return true; } if (mCurrentTab != position) { - setCurrentTab(position); + boolean b = false; if (mListener != null) { - mListener.onTabSelect(position); + b = mListener.onTabSelect(position); + } + if (!b) { + setCurrentTab(position); } } else { if (mIndicatorAnimEnable) { @@ -446,9 +452,12 @@ public boolean onTouch(View view, MotionEvent motionEvent) { public void onClick(View v) { int position = (Integer) v.getTag(); if (mCurrentTab != position) { - setCurrentTab(position); + boolean b = false; if (mListener != null) { - mListener.onTabSelect(position); + b = mListener.onTabSelect(position); + } + if (!b) { + setCurrentTab(position); } } else { if (mListener != null) { diff --git a/FlycoTabLayout_Lib/src/main/java/com/flyco/tablayout/SlidingTabLayout.java b/FlycoTabLayout_Lib/src/main/java/com/flyco/tablayout/SlidingTabLayout.java index 9ab7e5ed..26f26149 100644 --- a/FlycoTabLayout_Lib/src/main/java/com/flyco/tablayout/SlidingTabLayout.java +++ b/FlycoTabLayout_Lib/src/main/java/com/flyco/tablayout/SlidingTabLayout.java @@ -262,15 +262,15 @@ public void onClick(View v) { int position = mTabsContainer.indexOfChild(v); if (position != -1) { if (mViewPager.getCurrentItem() != position) { - if (mSnapOnTabClick) { + boolean b = false; + if (mListener != null) { + b = mListener.onTabSelect(position); + } + if (!b && mSnapOnTabClick) { mViewPager.setCurrentItem(position, false); } else { mViewPager.setCurrentItem(position); } - - if (mListener != null) { - mListener.onTabSelect(position); - } } else { if (mListener != null) { mListener.onTabReselect(position); diff --git a/FlycoTabLayout_Lib/src/main/java/com/flyco/tablayout/listener/OnTabSelectListener.java b/FlycoTabLayout_Lib/src/main/java/com/flyco/tablayout/listener/OnTabSelectListener.java index edf6cdb8..a45dada6 100644 --- a/FlycoTabLayout_Lib/src/main/java/com/flyco/tablayout/listener/OnTabSelectListener.java +++ b/FlycoTabLayout_Lib/src/main/java/com/flyco/tablayout/listener/OnTabSelectListener.java @@ -1,6 +1,10 @@ package com.flyco.tablayout.listener; public interface OnTabSelectListener { - void onTabSelect(int position); - void onTabReselect(int position); + /** + * @param position + * @return 消费掉,不让tab设置 + */ + boolean onTabSelect(int position); + boolean onTabReselect(int position); } \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 37ace998..8493429c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,13 +1,13 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 25 - buildToolsVersion "25.0.2" + compileSdkVersion 27 + buildToolsVersion '27.0.3' defaultConfig { applicationId "com.flyco.tablayoutsamples" - minSdkVersion 11 - targetSdkVersion 25 + minSdkVersion 14 + targetSdkVersion 27 versionCode 1 versionName "1.0" } @@ -20,12 +20,12 @@ android { } dependencies { - compile fileTree(include: ['*.jar'], dir: 'libs') - compile 'com.android.support:appcompat-v7:25.1.0' + implementation fileTree(include: ['*.jar'], dir: 'libs') + implementation 'com.android.support:appcompat-v7:27.1.1' // compile project(':FlycoTabLayout_Lib') //--->support 3.0+ //--->support 2.2+ // compile 'com.flyco.tablayout:FlycoTabLayout_Lib:2.0.0@aar' // compile 'com.nineoldandroids:library:2.4.0' - compile project(':FlycoTabLayout_Lib') + implementation project(':FlycoTabLayout_Lib') } diff --git a/build.gradle b/build.gradle index 062f3830..9bec4b8e 100644 --- a/build.gradle +++ b/build.gradle @@ -3,9 +3,10 @@ buildscript { repositories { jcenter() + google() } dependencies { - classpath 'com.android.tools.build:gradle:2.2.3' + classpath 'com.android.tools.build:gradle:3.1.4' // classpath 'com.github.dcendents:android-maven-gradle-plugin:1.4.1' // classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.2' // NOTE: Do not place your application dependencies here; they belong @@ -19,6 +20,7 @@ allprojects { // maven { // url "http://dl.bintray.com/h07000223/maven" // } + google() } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 77c260b9..45a1cf55 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip From 8f34a498b52850329db5a65732400ab81c264392 Mon Sep 17 00:00:00 2001 From: fengxinlin Date: Thu, 16 Aug 2018 10:03:19 +0800 Subject: [PATCH 4/5] =?UTF-8?q?=E4=BA=8B=E4=BB=B6=E5=8F=AF=E6=B6=88?= =?UTF-8?q?=E8=B4=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tablayoutsamples/ui/CommonTabActivity.java | 13 ++++++++----- .../tablayoutsamples/ui/SegmentTabActivity.java | 6 ++++-- .../tablayoutsamples/ui/SlidingTabActivity.java | 6 ++++-- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/com/flyco/tablayoutsamples/ui/CommonTabActivity.java b/app/src/main/java/com/flyco/tablayoutsamples/ui/CommonTabActivity.java index b898c2ce..923e8dd5 100644 --- a/app/src/main/java/com/flyco/tablayoutsamples/ui/CommonTabActivity.java +++ b/app/src/main/java/com/flyco/tablayoutsamples/ui/CommonTabActivity.java @@ -92,7 +92,7 @@ protected void onCreate(Bundle savedInstanceState) { mTabLayout_3.setOnTabSelectListener(new OnTabSelectListener() { @Override - public void onTabSelect(int position) { + public boolean onTabSelect(int position) { mTabLayout_1.setCurrentTab(position); mTabLayout_2.setCurrentTab(position); mTabLayout_4.setCurrentTab(position); @@ -100,11 +100,12 @@ public void onTabSelect(int position) { mTabLayout_6.setCurrentTab(position); mTabLayout_7.setCurrentTab(position); mTabLayout_8.setCurrentTab(position); + return false; } @Override - public void onTabReselect(int position) { - + public boolean onTabReselect(int position) { + return false; } }); mTabLayout_8.setCurrentTab(2); @@ -145,16 +146,18 @@ private void tl_2() { mTabLayout_2.setTabData(mTabEntities); mTabLayout_2.setOnTabSelectListener(new OnTabSelectListener() { @Override - public void onTabSelect(int position) { + public boolean onTabSelect(int position) { mViewPager.setCurrentItem(position); + return false; } @Override - public void onTabReselect(int position) { + public boolean onTabReselect(int position) { if (position == 0) { mTabLayout_2.showMsg(0, mRandom.nextInt(100) + 1); // UnreadMsgUtils.show(mTabLayout_2.getMsgView(0), mRandom.nextInt(100) + 1); } + return false; } }); diff --git a/app/src/main/java/com/flyco/tablayoutsamples/ui/SegmentTabActivity.java b/app/src/main/java/com/flyco/tablayoutsamples/ui/SegmentTabActivity.java index 53419fcc..cf4241c3 100644 --- a/app/src/main/java/com/flyco/tablayoutsamples/ui/SegmentTabActivity.java +++ b/app/src/main/java/com/flyco/tablayoutsamples/ui/SegmentTabActivity.java @@ -77,12 +77,14 @@ private void tl_3() { mTabLayout_3.setTabData(mTitles_3); mTabLayout_3.setOnTabSelectListener(new OnTabSelectListener() { @Override - public void onTabSelect(int position) { + public boolean onTabSelect(int position) { vp_3.setCurrentItem(position); + return false; } @Override - public void onTabReselect(int position) { + public boolean onTabReselect(int position) { + return false; } }); diff --git a/app/src/main/java/com/flyco/tablayoutsamples/ui/SlidingTabActivity.java b/app/src/main/java/com/flyco/tablayoutsamples/ui/SlidingTabActivity.java index 290c9b03..6c03d325 100644 --- a/app/src/main/java/com/flyco/tablayoutsamples/ui/SlidingTabActivity.java +++ b/app/src/main/java/com/flyco/tablayoutsamples/ui/SlidingTabActivity.java @@ -108,13 +108,15 @@ protected void onCreate(Bundle savedInstanceState) { } @Override - public void onTabSelect(int position) { + public boolean onTabSelect(int position) { Toast.makeText(mContext, "onTabSelect&position--->" + position, Toast.LENGTH_SHORT).show(); + return false; } @Override - public void onTabReselect(int position) { + public boolean onTabReselect(int position) { Toast.makeText(mContext, "onTabReselect&position--->" + position, Toast.LENGTH_SHORT).show(); + return false; } private class MyPagerAdapter extends FragmentPagerAdapter { From eab32d9924e3521ee8c6aa00247c37dcb251259c Mon Sep 17 00:00:00 2001 From: fengxinlin Date: Thu, 10 Jan 2019 10:18:34 +0800 Subject: [PATCH 5/5] =?UTF-8?q?=E6=B3=9B=E5=9E=8B=E4=BD=BF=E7=94=A8=3F?= =?UTF-8?q?=E9=80=9A=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/flyco/tablayout/CommonTabLayout.java | 4 ++-- .../src/main/java/com/flyco/tablayout/SegmentTabLayout.java | 5 ++++- .../src/main/java/com/flyco/tablayout/SlidingTabLayout.java | 6 +++--- .../com/flyco/tablayout/utils/FragmentChangeManager.java | 4 ++-- app/src/main/res/layout/activity_segment_tab.xml | 2 ++ 5 files changed, 13 insertions(+), 8 deletions(-) diff --git a/FlycoTabLayout_Lib/src/main/java/com/flyco/tablayout/CommonTabLayout.java b/FlycoTabLayout_Lib/src/main/java/com/flyco/tablayout/CommonTabLayout.java index f7a08aa3..2da36999 100644 --- a/FlycoTabLayout_Lib/src/main/java/com/flyco/tablayout/CommonTabLayout.java +++ b/FlycoTabLayout_Lib/src/main/java/com/flyco/tablayout/CommonTabLayout.java @@ -206,7 +206,7 @@ private void obtainAttributes(Context context, AttributeSet attrs) { ta.recycle(); } - public void setTabData(ArrayList tabEntitys) { + public void setTabData(ArrayList tabEntitys) { if (tabEntitys == null || tabEntitys.size() == 0) { throw new IllegalStateException("TabEntitys can not be NULL or EMPTY !"); } @@ -220,7 +220,7 @@ public void setTabData(ArrayList tabEntitys) { /** * 关联数据支持同时切换fragments */ - public void setTabData(ArrayList tabEntitys, FragmentActivity fa, int containerViewId, ArrayList fragments) { + public void setTabData(ArrayList tabEntitys, FragmentActivity fa, int containerViewId, ArrayList fragments) { mFragmentChangeManager = new FragmentChangeManager(fa.getSupportFragmentManager(), containerViewId, fragments); setTabData(tabEntitys); } diff --git a/FlycoTabLayout_Lib/src/main/java/com/flyco/tablayout/SegmentTabLayout.java b/FlycoTabLayout_Lib/src/main/java/com/flyco/tablayout/SegmentTabLayout.java index 14843a6e..a1e0121e 100644 --- a/FlycoTabLayout_Lib/src/main/java/com/flyco/tablayout/SegmentTabLayout.java +++ b/FlycoTabLayout_Lib/src/main/java/com/flyco/tablayout/SegmentTabLayout.java @@ -188,7 +188,7 @@ public void setTabData(String[] titles) { /** * 关联数据支持同时切换fragments */ - public void setTabData(String[] titles, FragmentActivity fa, int containerViewId, ArrayList fragments) { + public void setTabData(String[] titles, FragmentActivity fa, int containerViewId, ArrayList fragments) { mFragmentChangeManager = new FragmentChangeManager(fa.getSupportFragmentManager(), containerViewId, fragments); setTabData(titles); } @@ -435,6 +435,9 @@ public boolean onTouch(View view, MotionEvent motionEvent) { } } break; + case MotionEvent.ACTION_CANCEL: + setCurrentTab(getCurrentTab()); + break; } return true; } diff --git a/FlycoTabLayout_Lib/src/main/java/com/flyco/tablayout/SlidingTabLayout.java b/FlycoTabLayout_Lib/src/main/java/com/flyco/tablayout/SlidingTabLayout.java index 26f26149..87c32349 100644 --- a/FlycoTabLayout_Lib/src/main/java/com/flyco/tablayout/SlidingTabLayout.java +++ b/FlycoTabLayout_Lib/src/main/java/com/flyco/tablayout/SlidingTabLayout.java @@ -205,7 +205,7 @@ public void setViewPager(ViewPager vp, String[] titles) { } /** 关联ViewPager,用于连适配器都不想自己实例化的情况 */ - public void setViewPager(ViewPager vp, String[] titles, FragmentActivity fa, ArrayList fragments) { + public void setViewPager(ViewPager vp, String[] titles, FragmentActivity fa, ArrayList fragments) { if (vp == null) { throw new IllegalStateException("ViewPager can not be NULL !"); } @@ -848,10 +848,10 @@ public void setOnTabSelectListener(OnTabSelectListener listener) { } class InnerPagerAdapter extends FragmentPagerAdapter { - private ArrayList fragments = new ArrayList<>(); + private ArrayList fragments = new ArrayList<>(); private String[] titles; - public InnerPagerAdapter(FragmentManager fm, ArrayList fragments, String[] titles) { + public InnerPagerAdapter(FragmentManager fm, ArrayList fragments, String[] titles) { super(fm); this.fragments = fragments; this.titles = titles; diff --git a/FlycoTabLayout_Lib/src/main/java/com/flyco/tablayout/utils/FragmentChangeManager.java b/FlycoTabLayout_Lib/src/main/java/com/flyco/tablayout/utils/FragmentChangeManager.java index dcba1688..ef9a1940 100644 --- a/FlycoTabLayout_Lib/src/main/java/com/flyco/tablayout/utils/FragmentChangeManager.java +++ b/FlycoTabLayout_Lib/src/main/java/com/flyco/tablayout/utils/FragmentChangeManager.java @@ -10,11 +10,11 @@ public class FragmentChangeManager { private FragmentManager mFragmentManager; private int mContainerViewId; /** Fragment切换数组 */ - private ArrayList mFragments; + private ArrayList mFragments; /** 当前选中的Tab */ private int mCurrentTab; - public FragmentChangeManager(FragmentManager fm, int containerViewId, ArrayList fragments) { + public FragmentChangeManager(FragmentManager fm, int containerViewId, ArrayList fragments) { this.mFragmentManager = fm; this.mContainerViewId = containerViewId; this.mFragments = fragments; diff --git a/app/src/main/res/layout/activity_segment_tab.xml b/app/src/main/res/layout/activity_segment_tab.xml index 0165488c..c45135e8 100644 --- a/app/src/main/res/layout/activity_segment_tab.xml +++ b/app/src/main/res/layout/activity_segment_tab.xml @@ -97,6 +97,8 @@ android:id="@+id/tl_6" android:layout_width="match_parent" android:layout_height="36dp" + android:layout_marginTop="500dp" + android:layout_marginBottom="200dp" android:layout_gravity="center_horizontal" android:paddingLeft="30dp" android:paddingRight="30dp"