ViewPagerTabs,绘制tab底部线条长度小于文字

代码为android联系人中源码:


  ViewPager mPager;
  private ViewPagerTabStrip mTabStrip;

  /**
   * Linearlayout that will contain the TextViews serving as tabs. This is the only child
   * of the parent HorizontalScrollView.
   */
  final int mTextStyle;
  final ColorStateList mTextColor;
  final int mTextSize;
  final boolean mTextAllCaps;
  int mPrevSelected = -1;
  int mSidePadding;
  int mUnderlineColor;
  int mUnderlineThickness;

  private static final int TAB_SIDE_PADDING_IN_DPS = 10;


  /**
   * Simulates actionbar tab behavior by showing a toast with the tab title when long clicked.
   */
  private class OnTabLongClickListener implements OnLongClickListener {
      final int mPosition;

      public OnTabLongClickListener(int position) {
          mPosition = position;
      }

      @Override
      public boolean onLongClick(View v) {
          final int[] screenPos = new int[2];
          getLocationOnScreen(screenPos);

          final Context context = getContext();
          final int width = getWidth();
          final int height = getHeight();
          final int screenWidth = context.getResources().getDisplayMetrics().widthPixels;

          Toast toast = Toast.makeText(context, mPager.getAdapter().getPageTitle(mPosition),
                  Toast.LENGTH_SHORT);

          // Show the toast under the tab
          toast.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL,
                  (screenPos[0] + width / 2) - screenWidth / 2, screenPos[1] + height);

          toast.show();
          return true;
      }
  }

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

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

  public ViewPagerTabs(Context context, AttributeSet attrs, int defStyle) {
      super(context, attrs, defStyle);
      setFillViewport(true);

      mSidePadding = (int) (getResources().getDisplayMetrics().density * TAB_SIDE_PADDING_IN_DPS);

      final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ViewPagerTabs,defStyle,0);
      mTextSize = a.getDimensionPixelSize(R.styleable.ViewPagerTabs_textSize, 0);
      mTextStyle = a.getInt(R.styleable.ViewPagerTabs_textStyle, 0);
      mTextColor = a.getColorStateList(R.styleable.ViewPagerTabs_textColor);
      mTextAllCaps = a.getBoolean(R.styleable.ViewPagerTabs_textAllCap, false);
      mUnderlineColor = a.getColor(R.styleable.ViewPagerTabs_underlineColor,0);
      mUnderlineThickness = a.getDimensionPixelOffset(R.styleable.ViewPagerTabs_underlineThickness,dp2px(2f));

      mTabStrip = new ViewPagerTabStrip(context);
      mTabStrip.setUnderlineColor(mUnderlineColor);
      mTabStrip.setSelectedUnderlineThickness(mUnderlineThickness);

      addView(mTabStrip,
              new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT));
      a.recycle();
  }

  public void setViewPager(ViewPager viewPager) {
      mPager = viewPager;
      addTabs(mPager.getAdapter());
      mPager.addOnPageChangeListener(this);
  }

  private void addTabs(PagerAdapter adapter) {
      mTabStrip.removeAllViews();

      final int count = adapter.getCount();
      for (int i = 0; i < count; i++) {
          addTab(adapter.getPageTitle(i), i);
      }
  }

  private void addTab(CharSequence tabTitle, final int position) {
      final TextView textView = new TextView(getContext());
      textView.setText(tabTitle);
      textView.setBackgroundResource(R.drawable.view_pager_tab_background);
      textView.setGravity(Gravity.CENTER);
      textView.setOnClickListener(new OnClickListener() {
          @Override
          public void onClick(View v) {
              mPager.setCurrentItem(getRtlPosition(position));
          }
      });

      textView.setOnLongClickListener(new OnTabLongClickListener(position));

      // Assign various text appearance related attributes to child views.
      if (mTextStyle > 0) {
          textView.setTypeface(textView.getTypeface(), mTextStyle);
      }
      if (mTextSize > 0) {
          textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTextSize);
      }
      if (mTextColor != null) {
          textView.setTextColor(mTextColor);
      }
      textView.setAllCaps(mTextAllCaps);
      textView.setPadding(mSidePadding, 0, mSidePadding, 0);
      mTabStrip.addView(textView, new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT,
              LayoutParams.MATCH_PARENT, 1));
      // Default to the first child being selected
      if (position == 0) {
          mPrevSelected = 0;
          textView.setSelected(true);
      }
  }

  @Override
  public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
      position = getRtlPosition(position);
      int tabStripChildCount = mTabStrip.getChildCount();
      if ((tabStripChildCount == 0) || (position < 0) || (position >= tabStripChildCount)) {
          return;
      }
      mTabStrip.onPageScrolled(position, positionOffset, positionOffsetPixels);
      if(null != onPageChangeListener){
          onPageChangeListener.onPageScrolled(position,positionOffset,positionOffsetPixels);
      }
  }

  @Override
  public void onPageSelected(int position) {
      position = getRtlPosition(position);
      if (mPrevSelected >= 0) {
          mTabStrip.getChildAt(mPrevSelected).setSelected(false);
      }
      final View selectedChild = mTabStrip.getChildAt(position);
      selectedChild.setSelected(true);

      // Update scroll position
      final int scrollPos = selectedChild.getLeft() - (getWidth() - selectedChild.getWidth()) / 2;
      smoothScrollTo(scrollPos, 0);
      mPrevSelected = position;
      if(null != onPageChangeListener){
          onPageChangeListener.onPageSelected(position);
      }
  }

  @Override
  public void onPageScrollStateChanged(int state) {
      if(null != onPageChangeListener){
          onPageChangeListener.onPageSelected(state);
      }
  }

  private int getRtlPosition(int position) {
      if (getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
          return mTabStrip.getChildCount() - 1 - position;
      }
      return position;
  }

  private int dp2px(float dpVal){
      return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
              dpVal, getContext().getResources().getDisplayMetrics());
  }

  private OnPageChangeListener onPageChangeListener;

  public void setOnPageChangeListener(OnPageChangeListener onPageChangeListener){
      this.onPageChangeListener = onPageChangeListener;
  }

  public interface OnPageChangeListener{
      public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels);
      public void onPageSelected(int position);
      public void onPageScrollStateChanged(int state);
  }

}

ViewPagerTabStrip.java:

public class ViewPagerTabStrip extends LinearLayout {
    private int mSelectedUnderlineThickness;
    private final Paint mSelectedUnderlinePaint;

    private int mIndexForSelection;
    private float mSelectionOffset;
    private int mUnderlineColor;
    private int mBackgroundColor;

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

    public ViewPagerTabStrip(Context context, AttributeSet attrs) {
        super(context, attrs);

        final Resources res = context.getResources();

        mSelectedUnderlineThickness =
                res.getDimensionPixelSize(R.dimen.tab_selected_underline_height);
        mUnderlineColor = res.getColor(R.color.tab_selected_underline_color);
        mBackgroundColor = res.getColor(R.color.actionbar_background_color);

        mSelectedUnderlinePaint = new Paint();
        mSelectedUnderlinePaint.setColor(mUnderlineColor);

        setBackgroundColor(mBackgroundColor);
        setWillNotDraw(false);
    }

    @Override
    public void setBackgroundColor(int color) {
        super.setBackgroundColor(color);
    }

    public void setUnderlineColor(int underlineColor){
        mUnderlineColor = underlineColor;
        mSelectedUnderlinePaint.setColor(mUnderlineColor);
    }

    public void setSelectedUnderlineThickness(int size){
        mSelectedUnderlineThickness = size;
    }

    /**
     * Notifies this view that view pager has been scrolled. We save the tab index
     * and selection offset for interpolating the position and width of selection
     * underline.
     */
    void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        mIndexForSelection = position;
        mSelectionOffset = positionOffset;
        invalidate();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        int childCount = getChildCount();

        // Thick colored underline below the current selection
        if (childCount > 0) {
            View selectedTitle = getChildAt(mIndexForSelection);
            int selectedLeft = selectedTitle.getLeft();
            int selectedRight = selectedTitle.getRight();
            final boolean isRtl = isRtl();
            final boolean hasNextTab = isRtl ? mIndexForSelection > 0
                    : (mIndexForSelection < (getChildCount() - 1));
            if ((mSelectionOffset > 0.0f) && hasNextTab) {
                // Draw the selection partway between the tabs
                View nextTitle = getChildAt(mIndexForSelection + (isRtl ? -1 : 1));
                int nextLeft = nextTitle.getLeft();
                int nextRight = nextTitle.getRight();

                selectedLeft = (int) (mSelectionOffset * nextLeft +
                        (1.0f - mSelectionOffset) * selectedLeft);
                selectedRight = (int) (mSelectionOffset * nextRight +
                        (1.0f - mSelectionOffset) * selectedRight);
            }

            int height = getHeight();
            canvas.drawRect(selectedLeft, height - mSelectedUnderlineThickness,
                    selectedRight, height, mSelectedUnderlinePaint);
        }
    }

    private boolean isRtl() {
        return getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
    }

使用:

    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_activity);
        List<Fragment> mFragmentList = new ArrayList<>();
        mAfragment = new Afragment();
        mFragmentList.add(0,Afragment);
        mFragmentList.add(1, new Bfragment());
        mFragmentList.add(2, new Cfragment());

        TabFragmentPageAdapter pageAdapter = new     
        TabFragmentPageAdapter(getSupportFragmentManager(),mFragmentList);
        ViewPager viewPager = findViewById(R.id.vp_game);
        viewPager.setAdapter(pageAdapter);
        final ViewPagerTabs mViewPagerTabs = findViewById(R.id.view_tab);
        mViewPagerTabs.setViewPager(viewPager);

        addOnPageChangeListener(mViewPagerTabs);
        viewPager.setCurrentItem(0);
        viewPager.setOffscreenPageLimit(3);
        viewPager.addOnPageChangeListener(this);
        
    }
  public void addOnPageChangeListener(ViewPager.OnPageChangeListener           
    onPageChangeListener) {
        if (!mOnPageChangeListeners.contains(onPageChangeListener)) {
            mOnPageChangeListeners.add(onPageChangeListener);
        }
    }

private ArrayList<ViewPager.OnPageChangeListener> mOnPageChangeListeners =
            new ArrayList<ViewPager.OnPageChangeListener>();


    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        final int count = mOnPageChangeListeners.size();
        for (int i = 0; i < count; i++) {
            mOnPageChangeListeners.get(i).onPageScrolled(position, positionOffset,
                    positionOffsetPixels);
        }
    }

    @Override
    public void onPageSelected(int position) {
        final int count = mOnPageChangeListeners.size();
        for (int i = 0; i < count; i++) {
            mOnPageChangeListeners.get(i).onPageSelected(position);
        }
    }

    @Override
    public void onPageScrollStateChanged(int state) {
        final int count = mOnPageChangeListeners.size();
        for (int i = 0; i < count; i++) {
            mOnPageChangeListeners.get(i).onPageScrollStateChanged(state);
        }
    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,588评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,456评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,146评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,387评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,481评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,510评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,522评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,296评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,745评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,039评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,202评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,901评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,538评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,165评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,415评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,081评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,085评论 2 352

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,974评论 25 707
  • 转眼半个月的年假就没有了,现在就要屁颠屁颠的跑来上班了,作为一个产品经理,虽然面临新产品上线的情况(要自己测试),...
    粟长霉阅读 357评论 0 0
  • 《继续活下去》 著/菲利普•拉金 译/舒丹丹 继续活下去——也就是,重复 既定的习惯去获取必需—— 它不断丢失,即...
    梦呓ricot阅读 632评论 10 11
  • 作者~大鱼爱虾米 偶然看到一个纪实性的采访节目,主要是对现在社会剩女问题所进行的深入探讨。 看着那些站在镜头扬起明...
    蔓玖阅读 327评论 1 1
  • 周末回家,父亲正忙着上房补漏。 记得刚建新房时,父亲事必躬亲,呕心沥血,从打地基、砌墙、拉木料,运砖瓦砂灰,运筹策...
    山意阅读 258评论 0 0