浅析Android-ViewPagerIndicator

   Android-ViewPagerIndicator是一个和Viewpager一起搭配使用的第三方开源库。我当时使用他时去跟了一下他的源代码,现在在这里分享一下。

   Android-ViewPagerIndicator地址: https://github.com/JakeWharton/Android-ViewPagerIndicator

   从它提供的Samples开始切入(这里都是以SampleTabsDefault页面为例):

   先看Samples中代码:

package com.viewpagerindicator.sample;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import com.viewpagerindicator.TabPageIndicator;

public class SampleTabsDefault extends FragmentActivity {
	private static final String[] CONTENT = new String[] { "Recent", "Artists", "Albums", "Songs", "Playlists", "Genres" };

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.simple_tabs);

		FragmentPagerAdapter adapter = new GoogleMusicAdapter(getSupportFragmentManager());

		ViewPager pager = (ViewPager) findViewById(R.id.pager);
		pager.setAdapter(adapter);

		TabPageIndicator indicator = (TabPageIndicator) findViewById(R.id.indicator);
		indicator.setViewPager(pager);
	}

	class GoogleMusicAdapter extends FragmentPagerAdapter {
		public GoogleMusicAdapter(FragmentManager fm) {
			super(fm);
		}

		@Override
		public Fragment getItem(int position) {
			return TestFragment.newInstance(CONTENT[position % CONTENT.length]);
		}

		@Override
		public CharSequence getPageTitle(int position) {
			return CONTENT[position % CONTENT.length].toUpperCase();
		}

		@Override
		public int getCount() {
			return CONTENT.length;
		}
	}
}
 

  这里的代码就不多解释了。查看布局:

 

<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2011 Jake Wharton

     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.
-->

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <com.viewpagerindicator.TabPageIndicator
        android:id="@+id/indicator"
        android:layout_height="wrap_content"
        android:layout_width="fill_parent"
        />
    <android.support.v4.view.ViewPager
        android:id="@+id/pager"
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        />

</LinearLayout>

  布局也没什么介绍了。从代码和布局看,好像并没有设置tab的相关属性。所有只有从TabPageIndicator的构造器着手,因为布局中只能看到他的节点,所以他必定会执行构造方法。看下图:

 

    他是一个继承了HorizontalScrollView的类,再看看他的方法:

    如图,TabPageIndicator实现了PageIndicator接口,所以也就实现了相应的方法。内部还有OnTabReselectedListener接口、内部类TabView。OnTabReselectedListener接口就是一个自己定义的接口,他只有一个onTabReselected()方法;TabView是一个TextView的子类。有个成员变量mIndex。其实这就是Tab的item了。TabView类只提供了一个参数的构造器,也就是只能通过代码new出来了,但是在这个构造器中调用了TextView的三个参数的构造器。AttributeSet参数给的是null,而且给了一个自定义的属性R.attr.vpiTabPageIndicatorStyle。也就是会用该窗口中名字为vpiTabPageIndicatorStyle的样式。现在看看在哪里设置了vpiTabPageIndicatorStyle的值,前面已经看过了布局文件,那里并没有定义vpiTabPageIndicatorStyle。现在只有看manifest文件了。

  在manifest文件中,SampleTabsDefault页面使用了 android:theme="@style/Theme.PageIndicatorDefaults"。看看是怎么定义的。只看到了vpiTabPageIndicatorStyle、vpiIconPageIndicatorStyle两个属性。

  vpiIconPageIndicatorStyle只是定义了android:layout_marginLeft、android:layout_marginRight属性。在TabView的构造器中用的是vpiTabPageIndicatorStyle,所以现在就看这里是怎么定义vpiTabPageIndicatorStyle属性值了。看下图:

 

      这里面的属性就是系统属性,TabView使用的就是这里定义了的系统属性了。这里定义了一个android:background属性,这里是引用了一个selector,这里就是实现选中的横线和没选中的更细一点的线了。所以要改变他的样式,可以直接改drawable就可以了。

    TabPageIndicator中有个IcsLinearLayout的成员变量,它继承自LinearLayout,它是用来装TabView的。IcsLinearLayout也是通过代码new出的,而且这里又使用了vpiTabPageIndicatorStyle属性。不过在IcsLinearLayout的构造器中只是 super(context); 所以那些属性在这个IcsLinearLayout中是无效的。应该是这个库的作者想用Divider的形式画出下面的横线不成遗留的代码吧。IcsLinearLayout中有一个成员变量mDivider,一开始我以为横线的效果是这个mDivider画出的呢,然而他获得mDivider的方式不对(我认为的),通过debug返回mDivider的值也是null。特意在这指出,坐等指点。

    用过这个库的人会发现,当Tab切换时,用TabPageIndicator下的横线不是像动画那样过度。前面已经分析过,Tab下的横线是通过设置TabView的android:background属性实现的,要实现动画过度的话,就必须是一个View中在onDraw()中画,现在这个横线效果是由多个Tab的android:background实现的。所以在原库中是没法实现的。


 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值