android SlidingTabLayout实现ViewPager页卡滑动效果

本文介绍如何利用SlidingTabLayout实现流畅的导航功能,包括配置代码、自定义Tab样式及实现平均分配屏幕宽度的方法。

先来张效果图(可以滑动切换页卡)

\

 

主页面布局文件 remind_auction_new_list.xml :

 

主页面代码:

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public class MyRemindAuctionNewListActivity extends ActionBarActivity implements IInit {
 
     private SlidingTabLayout mSlidingTabLayout;
     private ViewPager mViewPager;
 
     private RemindAdapter mRemindAdapter;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super .onCreate(savedInstanceState);
         setContentView(R.layout.remind_auction_new_list);
 
         init();
     }
 
     @Override
     public void init() {
         ActionBarUtil.setup( this , R.string.my_remind);
 
         mSlidingTabLayout = (SlidingTabLayout) findViewById(R.id.stl_square);
         mViewPager =(ViewPager)findViewById(R.id.vp_square);
 
         // 设置ViewPager属性
         mRemindAdapter = new RemindAdapter(getSupportFragmentManager(), this );
         mViewPager.setOffscreenPageLimit( 2 );
         mViewPager.setAdapter(mRemindAdapter);
 
         // 定义 SlidingTabLayout
         mSlidingTabLayout.setDistributeEvenly( true );
         mSlidingTabLayout.setSelectedIndicatorColors(getResources().getColor(R.color.primary));
         mSlidingTabLayout.setBackgroundColor(getResources().getColor(R.color.white));
         mSlidingTabLayout.setCustomTabView(R.layout.view_tab, R.id.tv_text);
         mSlidingTabLayout.setViewPager(mViewPager); // 加载ViewPager
 
     }
 
}

 

 

为ViewPager添加多个页卡的Adapter:

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class RemindAdapter extends FragmentStatePagerAdapter {
 
     private String[] titles;
     private Context ctx;
 
     public RemindAdapter(FragmentManager fm, Context ctx) {
         super (fm);
         this .ctx = ctx;
         titles = ctx.getResources().getStringArray(R.array.remind_type);
     }
 
     @Override
     public Fragment getItem( int position) {
         if (position == 0 ) { //专场提醒
             return MyRemindAuctionListFragment.newInstance( 0 );
         } else { //卖家提醒
             return MyRemindSallerListFragment.newInstance( 1 );
         }
     }
 
     @Override
     public CharSequence getPageTitle( int position) {
         return titles[position];
     }
 
     @Override
     public int getCount() {
         return titles.length;
     }
}

 

 

每个页卡实际内容的Fragment:

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
public class MyRemindAuctionListFragment extends BaseFragment implements IPagination, IResponseHandler, SwipeRefreshLayout.OnRefreshListener {
 
     private int mTag;
     private ListView mListView; //拍场列表
     private ListAdapter mAdapter; //拍场适配器
     private MyRemindAuctionNewListActivity mActivity;
 
     //下拉刷新组件
     private SwipeRefreshLayout mSwipeRefreshLayout;
     private AuctionInfoViewModel mViewModel = new AuctionInfoViewModel();
     private TextView mEmptyView;   // 空白视图
 
     public static MyRemindAuctionListFragment newInstance( int tag) {
         MyRemindAuctionListFragment f = new MyRemindAuctionListFragment();
         f.mTag = tag;
         return f;
     }
 
     @Override
     public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
         View v = inflater.inflate(R.layout.remind_auction_list, null );
 
         mSwipeRefreshLayout = $(v, R.id.srl_refresh);
         mListView = $(v, R.id.remind_auction_listview);
         mEmptyView = $(v, R.id.tv_remind_warning);
 
         mSwipeRefreshLayout.setOnRefreshListener( this );
         mSwipeRefreshLayout.setColorSchemeResources(R.color.background_blue_standard, R.color.white, R.color.background_blue_standard, R.color.white);
         fetchData(FIRST);
 
         return v;
     }
 
     @Override
     public void onAttach(Activity activity) {
         super .onAttach(activity);
 
         if (activity instanceof MyRemindAuctionNewListActivity) {
             mActivity = ((MyRemindAuctionNewListActivity) activity);
         }
     }
 
     @Override
     public void fetchNewData( int tag) {
         mViewModel.increasePageIndex();
         fetchData(FIRST);
     }
 
     @Override
     public void fetchData( int tag) {
         mActivity.toggleProgress( true );
         GetMyRemindAuctionListParam param = new GetMyRemindAuctionListParam(Data.getUserID(), mViewModel.getPageIndex(), Data.PAGE_SIZE_MEDIUM);
         AuctionApi.getMyRemindAuctionList( this , param);
     }
 
     @Override
     public void updateUI(Object response, int tag) {
         mActivity.toggleProgress( false );
         mSwipeRefreshLayout.setRefreshing( false );
 
         mViewModel.inflate(response);
 
         if (mAdapter == null ) {
 
             mAdapter = new ListAdapter(mActivity, mViewModel.getList(), R.layout.item_list_remind_auction) {
                 @Override
                 protected void onBind( int position, AuctionInfoViewModel item, ViewHolder holder) {
                     holder.setImageUrl(R.id.head_icon, item.getImageUrl());
                     holder.setText(R.id.title, item.getAuctionIDStr());
                     holder.setText(R.id.sub_title, item.getAuctionName());
                     holder.setText(R.id.tv_auction_status, item.getStatusStr());
                     ((TextView) holder.get(R.id.tv_auction_status)).setTextColor(getResources().getColor(item.getColor()));
                 }
             };
 
             mListView.setAdapter(mAdapter);
             mEmptyView.setText(R.string.notice_auction_no_remind);
             mEmptyView.setGravity(Gravity.CENTER);
             mListView.setEmptyView(mEmptyView);
 
             /**
              *  上拉更多
              */
             mListView.setOnScrollListener( new AbsListView.OnScrollListener() {
                 @Override
                 public void onScrollStateChanged(AbsListView view, int scrollState) {
                     switch (scrollState) {
                         case SCROLL_STATE_IDLE:
 
                             if (mListView.getLastVisiblePosition() == mViewModel.getList().size() - 1 ) {
                                 if (!mViewModel.isComplete()) {
                                     fetchNewData(FIRST);
                                 }
                             }
                             break ;
                     }
                 }
 
                 @Override
                 public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
                 }
             });
         } else {
             mAdapter.notifyDataSetChanged();
         }
 
         mListView.setOnItemClickListener( new onItemClickListener());
     }
 
     @Override
     public void onRefresh() {
         refresh();
     }
 
     @Override
     public void refresh() { // 重置页索引、适配器
         mViewModel.reset();
         fetchData(FIRST);
     }
 
     @Override
     public int getTotal() {
         if (mAdapter == null ) return 0 ;
         return mAdapter.getCount();
     }
 
     /**
      * 监听事件,以此启动不同页面
      */
     class onItemClickListener implements AdapterView.OnItemClickListener {
         @Override
         public void onItemClick(AdapterView<!--?--> parent, View view, int position, long id) {
 
             int temp = mViewModel.getList().get(position).getStatus();
             int auctionID = mViewModel.getList().get(position).getAuctionID();
 
             Intent mIntent = new Intent();
             switch (temp) {
                 case 1 :
                     mIntent.setClass(getActivity(), AuctionPreviewActivity. class );
                     break ;
                 case 2 :
                     mIntent.setClass(getActivity(), AuctionPreviewActivity. class );
                     break ;
                 case 3 :
                     mIntent.setClass(getActivity(), AuctionPreviewActivity. class );
                     break ;
                 default :
                     break ;
             }
             mIntent.putExtra(EnumIntentKey.AUCTION_ID.toString(), auctionID);
             startActivity(mIntent);
         }
     }
}
</auctioninfoviewmodel></auctioninfoviewmodel>


最近在使用ActionBar的时候,如果使用的是最新版V7包或者最新的SDK平台,就会发现 ActionBar的导航功能已经不建议使用了。主要的原因是ActionBar自带Tab导航自定义性差(只能通过style修改),而且不再建议使用ActionBar。SlidingTabLayout就是ActionBar导航的替代品,使用它可以轻松的实现导航功能。


使用SlidingTabLayout需要准备2个类,分别是 SlidingTabLayout,与SlidingTabStrip。点击下载 ,放进项目中时只用修改下包名即可。

SlidingTabLayout主要配合ViewPager实现Tab导航,且需要在ActionBarActivity中使用,具体代码如下:

[java]  view plain copy
  1. public class MainActivity extends ActionBarActivity {  
  2.   
  3.     @Override  
  4.     protected void onCreate(Bundle savedInstanceState) {  
  5.         super.onCreate(savedInstanceState);  
  6.         setContentView(R.layout.activity_main);  
  7.         ViewPager pager= (ViewPager) findViewById(R.id.pager);  
  8.         SlidingTabLayout tab= (SlidingTabLayout) findViewById(R.id.tab);  
  9.   
  10.         MyAdapte adapter= new MyAdapte();  
  11.         pager.setAdapter(adapter);  
  12.         tab.setViewPager(pager);  
  13.     }  
  14.   
  15.     int[] colors={0xFF123456,0xFF654321,0xFF336699};  
  16.   
  17.     class MyAdapte extends PagerAdapter{  
  18.         String[] titles={"AA","BB","CC"};  
  19.   
  20.         ArrayList<LinearLayout> layouts=new ArrayList<LinearLayout>();  
  21.         MyAdapte() {  
  22.   
  23.             for (int i = 0; i < 3; i++) {  
  24.                 LinearLayout l=new LinearLayout(MainActivity.this);  
  25.                 l.setBackgroundColor(colors[i]);  
  26.                 l.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT));  
  27.                 layouts.add(l);  
  28.             }  
  29.   
  30.         }  
  31.   
  32.         @Override  
  33.         public int getCount() {  
  34.             return layouts.size();  
  35.         }  
  36.   
  37.         @Override  
  38.         public boolean isViewFromObject(View view, Object o) {  
  39.             return view==o;  
  40.         }  
  41.   
  42.         @Override  
  43.         public Object instantiateItem(ViewGroup container, int position) {  
  44.             LinearLayout l=layouts.get(position);  
  45.             container.addView(l);  
  46.             return l;  
  47.         }  
  48.   
  49.         @Override  
  50.         public void destroyItem(ViewGroup container, int position, Object object) {  
  51.             container.removeView(layouts.get(position));  
  52.         }  
  53. <span style="white-space:pre">    </span>//Tab上显示的文字  
  54.         @Override  
  55.         public CharSequence getPageTitle(int position) {  
  56.             return titles[position];  
  57.         }  
  58.     }  
  59. }  

布局如下:

[java]  view plain copy
  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:orientation="vertical"  
  6.     tools:context=".MainActivity">  
  7.   
  8.     <com.example.wanggang.slindingtablayouttest001.SlidingTabLayout  
  9.         android:id="@+id/tab"  
  10.         android:layout_width="match_parent"  
  11.         android:layout_height="wrap_content" />  
  12.   
  13.     <android.support.v4.view.ViewPager  
  14.         android:layout_width="match_parent"  
  15.         android:layout_height="match_parent"  
  16.         android:id="@+id/pager" />  
  17. </LinearLayout>  

运行效果如下:

       

如果要修改 选中效果 的颜色,或者加上选中颜色过度效果,或者 分割线的颜色,可以为 SlidingTabLayout设置属性

[java]  view plain copy
  1. tab.setCustomTabColorizer(new SlidingTabLayout.TabColorizer() {  
  2.             @Override  
  3.             public int getIndicatorColor(int position) {  
  4.                 return colors[position];//每个选项卡所对应的颜色  
  5.             }  
  6. <span style="white-space:pre">    </span>    //分割线颜色  
  7.             @Override  
  8.             public int getDividerColor(int position) {  
  9.                 return 0x00FFFFFF;  
  10.             }  
  11.         });  
效果如下:



根据以上的运行效果可以看出,每个Tab上面显示的内容都是文本。如果要显示图片,就需要将图片变成  ImageSpan,通过PagerAdapter  的 getPageTitle() 返回到 SlidingTabLayout。

[java]  view plain copy
  1. <span style="white-space:pre">    </span>int[] imageResId = {  
  2.                 R.drawable.ic_launcher,  
  3.                 R.drawable.ic_launcher,  
  4.                 R.drawable.ic_launcher  
  5.         };  
  6.   
  7.         @Override  
  8.         public CharSequence getPageTitle(int position) {  
  9.             Drawable image = getResources().getDrawable(imageResId[position]);  
  10.             image.setBounds(00, image.getIntrinsicWidth(), image.getIntrinsicHeight());  
  11.             SpannableString sb = new SpannableString(" ");  
  12.             ImageSpan imageSpan = new ImageSpan(image, ImageSpan.ALIGN_BOTTOM);  
  13.             sb.setSpan(imageSpan, 01, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);  
  14.             return sb;  
  15.             //return titles[position];  
  16.         }  

  但是由于SlidingTabLayout自带的TextView会调用 setAllCaps(true),会取消所有的 ImageSpan 的效果。所以需要自定义TabView。

res/layout/custom_tab.xml

[java]  view plain copy
  1. <TextView xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     android:layout_width="wrap_content"  
  3.     android:layout_height="wrap_content"  
  4.     android:textSize="12sp"  
  5.     android:gravity="center"  
  6.     android:textStyle="bold"  
  7.     android:padding="16dp" />  
然后 在 tab.setViewPager(pager) 之前调用  tab.setCustomTabView(R.layout.custom_tab,0) 设置自定义TabView

[java]  view plain copy
  1. tab.setCustomTabView(R.layout.custom_tab,0);  
  2. tab.setViewPager(pager);  

运行效果如下:


最后,我们会发现,所有的TabView都没有铺满屏幕宽度。如果要每个TabView都平分屏幕宽度,只需在自定义的TextView 上加上权重属性即可。

[java]  view plain copy
  1. <TextView xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     android:layout_width="0dp"  
  3.     android:layout_weight="1"  
  4.     android:layout_height="wrap_content"  
  5.     android:textSize="12sp"  
  6.     android:gravity="center"  
  7.     android:textStyle="bold"  
  8.     android:padding="16dp" />  

效果如下:



源码下载



评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值