【Android开源项目分析】TAB导航栏PagerSlidingTabStrip的使用和源码分析

转载请注明出处:http://blog.csdn.net/zhoubin1992/article/details/47382021
本文分为两部分:

  • PagerSlidingTabStrip的使用
  • PagerSlidingTabStrip源码分析

    PagerSlidingTabStrip项目源码下载:
    https://github.com/astuetz/PagerSlidingTabStrip
    PagerSlidingTabStrip是配合ViewPager使用的导航栏,导航栏会随着ViewPager滑动而滑动,如下图。打开源码会发现只有一个继承了HorizontalScrollView的类——PagerSlidingTabStrip.java,实现不是特别复杂。
    这里写图片描述这里写图片描述

PagerSlidingTabStrip的使用

我这里展示使用步骤,记录下当时遇到的问题以及解决方法。
1. 按照上面的地址下载,项目文件名PagerSlidingTabStrip-master。把library导入工程,加入library作为引用工程。
这里当时我导入后,library项目报错了。
首先是Unable to resolve target ‘android-17’错误
解决方法:http://stackoverflow.com/questions/20975056/unable-to-resolve-target-android-17
还有是项目引用了android-support-v4,然而项目并没有导入android-support-v4.jar,出现The import android.support cannot be resolved错误
解决方法:http://stackoverflow.com/questions/18299898/the-import-android-support-cannot-be-resolved
再者当导入android-support-v4.jar后,出现multiple dex files define landroid/support/annotation/AnimRes错误
解决方法:http://stackoverflow.com/questions/26342444/multiple-dex-files-define-landroid-support-annotation-animres
2. 在layout布局文件里配置PagerSlidingTabStrip控件,它通常要在ViewPager控件之上。

   <!--  通常要在ViewPager控件之上 -->
    <com.astuetz.PagerSlidingTabStrip
        android:id="@+id/tabs"
        android:layout_width="match_parent"
        android:layout_height="48dip" />  
    <android.support.v4.view.ViewPager
        android:id="@+id/pager"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/tabs" />

3.在activity的onCreate方法或者fragment的onCreateView方法,获取PagerSlidingTabStrip控件,绑定控件到ViewPager上。
activity的onCreate方法:

        mTabs = (PagerSlidingTabStrip) findViewById(R.id.tabs);
        //初始化ViewPager并添加适配器
        mPager = (ViewPager) findViewById(R.id.pager);
        mAdapter = new MyPagerAdapter(getSupportFragmentManager());
        mPager.setAdapter(mAdapter);
        //绑定PagerSlidingTabStrip控件到ViewPager上
        mTabs.setViewPager(mPager);  

我的需求是在fragment的onCreateView方法,注意代码如下:

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.activity_recipe,
                container, false);

        mTabs = (PagerSlidingTabStrip) view.findViewById(R.id.tabs);
        //初始化ViewPager并且添加适配器
        mPager = (ViewPager) view.findViewById(R.id.pager);
        mAdapter = new MyPagerAdapter(getActivity().getSupportFragmentManager());
        mPager.setAdapter(mAdapter);
        //绑定PagerSlidingTabStrip控件到ViewPager上
        mTabs.setViewPager(mPager);  
        return view;
    }

要注意到findViewById前需要加view,getSupportFragmentManager()前需要加getActivity()。
当时一开始没有加。出现nullpointer exception in oncreateView() of fragment错误。
解决方法:http://stackoverflow.com/questions/15644617/nullpointer-exception-in-oncreateview-of-fragment
同时注意内部类MyPagerAdapter需要自己定义,参考官方demo。这样就完成了。
总结下PagerSlidingTabStrip的使用:

  • library导入工程,加入library作为引用工程;
  • 布局文件配置PagerSlidingTabStrip控件;
  • 在onCreate方法或onCreateView方法中获取PagerSlidingTabStrip控件,绑定到ViewPager上。

PagerSlidingTabStrip源码分析

首先我先总结下PagerSlidingTabStrip的主要原理,让大家有个整体把握。然后再进入源码一步步分析。

PagerSlidingTabStrip的主要原理:
  1. 首先在构造方法里创建Tab的LinearLayout容器,初始化样式值,创建指示器分割线画笔等;
  2. 进入setViewPager()绑定ViewPager,设置了viewpager的OnPageChangeListener为内部类PageListener,以及调用notifyDataSetChanged();
  3. 在notifyDataSetChanged()根据adapter内容创建TAB导航栏标题(icon/text);
  4. 在PageListener监听类里实现了导航栏会随着ViewPager滑动而滑动,以及调用invalidate()方法 ;
  5. 触发ondraw()函数完成最终的绘制。绘制指示器,下划线和分割线。


/*
 * Copyright (C) 2013 Andreas Stuetz <andreas.stuetz@gmail.com>
 *
 * 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 com.astuetz;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Typeface;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.HorizontalScrollView;
import android.wid
  • 8
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值