改进型Tab页导航,TabBarView解析


   在开发中经常遇问问到页面的滑动,这时我们需要提供一个tab页的导航条来显示滑动到了哪一页,类似这样的

 

但是如果我们的tab页比较少,再加上使用ActionBar,这样就会很占空间,像安卓默认提供tab

是不是很浪费空间,我们可以把他挪到ActionBar上,简单的方法就是使用反射

<span style="font-size:18px;">private void enableEmbeddedTabs(Object actionBar){  
        try {  
            Method setHasEmbeddedTabsMethod = actionBar.getClass().getDeclaredMethod("setHasEmbeddedTabs", boolean.class);  
            setHasEmbeddedTabsMethod.setAccessible(true);  
            setHasEmbeddedTabsMethod.invoke(actionBar, true);  
              
        } catch (Exception e) {  
            // TODO: handle exception  
        }  
} </span>

结果变成这样的

这样只能显示文字,不能显示各种图片,不利于我们的拓展,也很不美观。

下面来介绍一种可以自定义在ActionBar上的tab页方法。

  

   对于ActionBar,有一个方法是可以设置自定义的View

ActionBar.setCustomView(View view, LayoutParams layoutParams),这样再结合我们平时使用tab页的方法来定制这样的布局。类似像Fuubo


不过在GitHub上,有实现好的开源项目,https://github.com/Mirkoddd/TabBarView,我们来分析一下他的实现方法。

  

首先我们down下来他的源码,发现其实实现的很简单,整个库关键的就三个类


 先看TabView,这个类继承自LinearLayout,是实现某个具体的Tab页,类的实现也很简单,里面只有两个空间,一个ImageView用来显示icon,一个TextView用来显示文字,在屏幕为竖的时候,是不显示文字的,因为整个ActionBar空间有限,这个实现后面再说,类里面就是一些空间的初始化以及暴漏出一些方法给外界,setTextsetIcon看名字就知道是什么意思,不多解释

  再看TabBarView,这个是实现整个的核心,也是继承自LinearLayout,控制整个tabs的布局,在tab导航条下面还有一条线用来显示滑动到哪个tab页,通过调用传进来的ViewPageroffset属性来确定横线的位置,然后调用ondraw方法进行绘制,贴一下代码

<span style="font-size:18px;">@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		// Draw the strip manually
		child = getChildAt(mSelectedTab);
		int height = getHeight();
		if (child != null) {
			float left = child.getLeft();
			Log.e("child.getLeft()==========", child.getLeft()+"");
			float right = child.getRight();
			if (mOffset >  0f && mSelectedTab < tabCount - 1 ) {
				nextChild = getChildAt(mSelectedTab + 1);
				if (nextChild != null) {
					final float nextTabLeft = nextChild.getLeft();
					Log.e("nextChild.getLeft()==========", nextChild.getLeft()+"");
					final float nextTabRight = nextChild.getRight();
					left =  (mOffset * nextTabLeft + (1f - mOffset) * left);
					right = (mOffset * nextTabRight + (1f - mOffset) * right);
				}
			}
			canvas.drawRect(left, height - mStripHeight, right, height, mPaint);
		}
	}</span>

    其中的mOffset 就是实现OnPageChangeListener,实现其中的onPageScrolled方法,方法中的positionOffset是一个从01变化的浮点数,当滑动到下一个tab页再变回0

   当屏幕变化时tab也应该进行相应的变化,就是横排和竖排的变化,前面也提到了,当竖排时,是不显示文字的,当横排时,显示文字,像这样



其中在TabBarView中有个更新状态的方法,

<span style="font-size:18px;">public void notifyDataSetChanged() {
		this.removeAllViews();
		tabCount = pager.getAdapter().getCount();
		for (int i = 0; i < tabCount; i++) {
			if(getResources().getConfiguration().orientation==1){
				//横排
				addTabViewP(i, pager.getAdapter().getPageTitle(i).toString(),
						((IconTabProvider) pager.getAdapter()).getPageIconResId(i));
			}else{
				addTabViewL(i, pager.getAdapter().getPageTitle(i).toString(),
						((IconTabProvider) pager.getAdapter()).getPageIconResId(i));
			}
		}
		getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
			@SuppressLint("NewApi")
			@Override
			public void onGlobalLayout() {
				getViewTreeObserver().removeOnGlobalLayoutListener(this);
				mSelectedTab = pager.getCurrentItem();
			}
		});

	}</span>

通过getResources().getConfiguration().orientation获取当前屏幕的方向,然后进行赋值。贴一下代码

<span style="font-size:18px;">/**
	 * 竖排
	 * @param i
	 * @param string
	 * @param pageIconResId
	 */
	private void addTabViewP(final int i, final String string, int pageIconResId) {
		final TabView tab = new TabView(getContext());
		tab.setIcon(pageIconResId);
		tab.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				pager.setCurrentItem(i);
			}
		});
		//长按显示文字
		CheatSheet.setup(tab, string);
		this.addView(tab);
	}</span>


值得提醒的是,当横排时,是不需要再进行tab.setIcon(pageIconResId);避免显示两个icon

  最后CheatSheet类就一个主要的方法,setup(),就是当我们长按tab时,在下面显示文字,和actionBar默认的tab页是一样的体验,这个是用Toast来实现的,主要就是计算Toast的位置比较麻烦,其他没什么好说的。

  对于这个开源项目的使用可以去GitHub上去看一下,很简单就可以搞定



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值