在本人开发第一个安卓应用的时候就想到多屏滑动的界面(类似于微信5.0的滑动界面,已经流行了很长一段时间),鉴于知识有限,变依靠Tabhos实现了这种效果。思路是:监听并计算滑动距离,切换Tabhost。你可能已经想到了,没错,效果特别差,Tabhost切换仅仅是刷了一下页面而已,什么也没做。后来在网上搜到,导入(现在新建项目都是默认导入)android-support-v4.jar实现里面的ViewPager就行了。
在Activity里面建立一个ViewPager,然后将我们需要的视图添加到里面就行了。当然最好的方法是ViewPager+Fragment去实现。Fragment类似于Activity,有自己的生命周期。
(想要具体了解就可以谷歌查询API文档)
以下为正文:
项目文件:
PagerScrollerActivity和TitleIndicator为此项目的核心功能。
PagerScrollerActivity是就是一个继承了FragmentActivity抽象的类,实现了项目具体功能(管理TitleIndicator)
关键代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
private
void initView() throws
IndexOutOfBoundsException, NullPointerException {
setTabsAndAdapter(); //抽象方法,用于实例化Fragment页面以及标题栏
viewPager = (ViewPager) findViewById(R.id.vPager);
// 设置viewpager内部页面之间的间距
viewPager.setPageMargin(getResources().getDimensionPixelSize(R.dimen.fragment_viewpager_margin));
// 设置viewpager内部页面间距的drawable
viewPager.setPageMarginDrawable(color.myblue);
viewPager.setAdapter(adapter);
//必须让viewPager设置此OnPageChangeListener的实现类,才能对滑动和页面状态监听
viewPager.setOnPageChangeListener( this );
title = (TitleIndicator) findViewById(R.id.title);
title.init(tabs, viewPager);
}
} |
PagerScrollerActivity实现 onPageScrolled(int position, float positionOffset, int positionOffsetPixels)用于监听滚动过程,以实现标题栏的实时滚动。
1
2
3
|
public void onPageScrolled( int
position, float
positionOffset, int
positionOffsetPixels) {<br> //title 为 TitleIndicator的实例
title.onScroll((viewPager.getWidth() + viewPager.getPageMargin()) * position + positionOffsetPixels); <br> //读者可在纸上画出多个页面的示意图,自己进行计算便能得出这个结果(将坐标想象成所有页面以及变局的总和)
} |
TitleIndicator是标题栏,数据来自List<TabInfo> tabs,实现实时滚动游标以及点击子标题切换到页面
先贴上TabInfo的关键代码
1
2
3
4
5
6
7
8
9
10
|
public class TabInfo {
<br> //用于获取到子标题的布局内容,需要的话可以添加ImageView.
public
View getTab(LayoutInflater inflater, ViewGroup root) {
tab = inflater.inflate(R.layout.tab_item, root, false );
tv = (TextView) tab.findViewById(R.id.tab_name);
tv.setText(name);
tab.setId(id);
return
tab;
}
} |
TitleIndicator的初始化操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
public void init(List<TabInfo> tabs, ViewPager viewPager) {
this .viewPager = viewPager;
setWillNotDraw( false ); // 调用invalidate()时强制调用onDraw()方法
<br> totalTabs = tabs.size();
// 设置标题的每一个Tab的位置属性
for
( int i = 0 ; i < totalTabs; i++) {
View view = tabs.get(i).getTab(inflater, this );
LinearLayout.LayoutParams lP = (LinearLayout.LayoutParams) view.getLayoutParams();
lP.gravity = Gravity.CENTER_VERTICAL;
view.setOnClickListener( this );
addView(view);
}
setCurrentTab(currentTab);
}
|
TitleIndicator的关键代码,用于重绘游标
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
|
protected
void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super .onDraw(canvas);
if
(!initialize) {
initTab(canvas);
}
float
scroll_x = 0 ;
if
(totalTabs != 0 ) {
// 计算滚动条实际滚动距离
scroll_x = (currentLocationlX - ((currentTab) * (mWidth + viewPager.getPageMargin()))) / totalTabs;
} else
{
scroll_x = currentLocationlX;
}
cursorPath.rewind(); // 清楚之前的路径状态
float
left_x = currentTab * cursorWidth + scroll_x;
float
right_x = (currentTab + 1 ) * cursorWidth + scroll_x;
float
top_y = mHeight - cursorHeight - 2 ;
float
bottom_y = mHeight - 2 ;
cursorPath.moveTo(left_x, top_y); // 移动到基点到左上角
cursorPath.lineTo(right_x, top_y); // 画线:基点到右上角
cursorPath.lineTo(right_x, bottom_y); // 基点到右下角
cursorPath.lineTo(left_x, bottom_y); // 基点到左下角
cursorPath.close();
canvas.drawPath(cursorPath, paint);
initialize = true ;
} |
设置当前显示的页面
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
public void setCurrentTab( int
i) {
// 清除旧Tab的文字状态
View view = getChildAt(currentTab);
view.setSelected( false );
currentTab = i;
// 设置新Tab的文字状态
view = getChildAt(currentTab);
view.setSelected( true );
invalidate();
if
(viewPager.getCurrentItem() != i) viewPager.setCurrentItem(i);
} |
注:大神就不要看这么渣的文章了,新手看看就还行。
本人在网上找了许多demo。后来发现几乎都是同一个大神的文章(http://blog.csdn.net/singwhatiwanna/article/details/17201587),这位大神的demo功能实现非常完善,但本人完全是安卓(java)新手,里面核心代码能够看懂,但是许多细节的不是很清楚。在读懂这个demo的代码后,自己尝试着写一个类似的demo(几乎是一样的,只是功能简单些,对于我这种安卓新手来说比较容易读懂的)。