时人不识凌云木,直待凌云始道高。这篇文章主要讲述Android中ViewPager实现滑动条及与Fragment结合的实例教程相关的知识,希望能为你提供帮助。
ViewPager类主要被用来实现可滑动的视图功能,这里我们就来共同学习android中ViewPager实现滑动条及与Fragment结合的实例教程,需要的朋友可以参考下自主实现滑动指示条
先上一个基本效果图:
文章图片
文章图片
1.XML布局
布局代码如下:
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <
LinearLayout xmlns:android = "http://schemas.android.com/apk/res/android"
xmlns:tools = "http://schemas.android.com/tools"
android:layout_width = "match_parent"
android:layout_height = "match_parent"
android:orientation = "vertical"
tools:context = "com.example.testviewpage_2.MainActivity" >
<
ImageView
android:id = "@+id/cursor"
android:layout_width = "fill_parent"
android:layout_height = "wrap_content"
android:scaleType = "matrix"
android:src = "@drawable/a" />
<
android.support.v4.view.ViewPager
android:id = "@+id/viewpager"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:layout_gravity = "center" />
<
/ LinearLayout >
|
2.JAVA代码
?
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 | public class MainActivity extends Activity {
private View view1, view2, view3;
private List<
View>
viewList;
// view数组
private ViewPager viewPager;
// 对应的viewPager
private ImageView cursor;
private int bmpw = 0 ;
// 游标宽度
private int offset = 0 ;
// // 动画图片偏移量
private int currIndex = 0 ;
// 当前页卡编号
@Override
protected void onCreate(Bundle savedInstanceState) {
super .onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager = (ViewPager) findViewById(R.id.viewpager);
LayoutInflater inflater = getLayoutInflater();
view1 = inflater.inflate(R.layout.layout1, null );
view2 = inflater.inflate(R.layout.layout2, null );
view3 = inflater.inflate(R.layout.layout3, null );
viewList = new ArrayList<
View>
();
// 将要分页显示的View装入数组中
viewList.add(view1);
viewList.add(view2);
viewList.add(view3);
//初始化指示器位置
initCursorPos();
viewPager.setAdapter( new MyPagerAdapter(viewList));
viewPager.setOnPageChangeListener( new MyPageChangeListener());
}
//初始化指示器位置
public void initCursorPos() {
// 初始化动画
cursor = (ImageView) findViewById(R.id.cursor);
bmpw = BitmapFactory.decodeResource(getResources(), R.drawable.a)
.getWidth();
// 获取图片宽度
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
int screenW = dm.widthPixels;
// 获取分辨率宽度
offset = (screenW / viewList.size() - bmpw) / 2 ;
// 计算偏移量
Matrix matrix = new Matrix();
matrix.postTranslate(offset, 0 );
cursor.setImageMatrix(matrix);
// 设置动画初始位置
}
//页面改变监听器
public class MyPageChangeListener implements OnPageChangeListener {
int one = offset * 2 + bmpw;
// 页卡1 ->
页卡2 偏移量
int two = one * 2 ;
// 页卡1 ->
页卡3 偏移量
@Override
public void onPageSelected( int arg0) {
Animation animation = null ;
switch (arg0) {
case 0 :
if (currIndex == 1 ) {
animation = new TranslateAnimation(one, 0 , 0 , 0 );
} else if (currIndex == 2 ) {
animation = new TranslateAnimation(two, 0 , 0 , 0 );
}
break ;
case 1 :
if (currIndex == 0 ) {
animation = new TranslateAnimation(offset, one, 0 , 0 );
} else if (currIndex == 2 ) {
animation = new TranslateAnimation(two, one, 0 , 0 );
}
break ;
case 2 :
if (currIndex == 0 ) {
animation = new TranslateAnimation(offset, two, 0 , 0 );
} else if (currIndex == 1 ) {
animation = new TranslateAnimation(one, two, 0 , 0 );
}
break ;
}
currIndex = arg0;
animation.setFillAfter( true );
// True:图片停在动画结束位置
animation.setDuration( 300 );
cursor.startAnimation(animation);
}
@Override
public void onPageScrolled( int arg0, float arg1, int arg2) {
}
@Override
public void onPageScrollStateChanged( int arg0) {
}
}
/**
* ViewPager适配器
*/
public class MyPagerAdapter extends PagerAdapter {
public List<
View>
mListViews;
public MyPagerAdapter(List<
View>
mListViews) {
this .mListViews = mListViews;
}
@Override
public boolean isViewFromObject(View arg0, Object arg1) {
// TODO Auto-generated method stub
return arg0 == arg1;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return mListViews.size();
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
// TODO Auto-generated method stub
container.removeView(mListViews.get(position));
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
// TODO Auto-generated method stub
container.addView(mListViews.get(position));
return mListViews.get(position);
}
}
} |
从易到难一步步来讲。
(1)initCursorPos()---初始化指示器位置
游标在初始化显示时,我们要根据屏幕宽度来显示游标位置。先看看这部分代码:
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | //初始化指示器位置
public void initCursorPos() {
// 初始化动画
cursor = (ImageView) findViewById(R.id.cursor);
bmpw = BitmapFactory.decodeResource(getResources(), R.drawable.a)
.getWidth();
// 获取图片宽度
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
int screenW = dm.widthPixels;
// 获取分辨率宽度
offset = (screenW / viewList.size() - bmpw) / 2 ;
// 计算偏移量
Matrix matrix = new Matrix();
matrix.postTranslate(offset, 0 );
cursor.setImageMatrix(matrix);
// 设置动画初始位置
} |
文章图片
最后对于偏移的方法,可用的很多,这里仿网上的代码用了matrix;当然大家可以用其它的偏移方法,一样。
(2)MyPageChangeListener()---页面改变监听器
代码如下 :
?
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 | public class MyPageChangeListener implements OnPageChangeListener {
int one = offset * 2 + bmpw;
// 页卡1 ->
页卡2 偏移量
int two = one * 2 ;
// 页卡1 ->
页卡3 偏移量
@Override
public void onPageSelected( int arg0) {
Animation animation = null ;
switch (arg0) {
case 0 :
if (currIndex == 1 ) {
animation = new TranslateAnimation(one, 0 , 0 , 0 );
} else if (currIndex == 2 ) {
animation = new TranslateAnimation(two, 0 , 0 , 0 );
}
break ;
case 1 :
if (currIndex == 0 ) {
animation = new TranslateAnimation(offset, one, 0 , 0 );
} else if (currIndex == 2 ) {
animation = new TranslateAnimation(two, one, 0 , 0 );
}
break ;
case 2 :
if (currIndex == 0 ) {
animation = new TranslateAnimation(offset, two, 0 , 0 );
} else if (currIndex == 1 ) {
animation = new TranslateAnimation(one, two, 0 , 0 );
}
break ;
}
currIndex = arg0;
animation.setFillAfter( true );
// True:图片停在动画结束位置
animation.setDuration( 300 );
cursor.startAnimation(animation);
} |
这里可能有难度的地方在于,数学……
我画了一张图,解释从第一个页面到第二个页面时的距离为什么是“游标宽度+offset*2”,其它距离类似。
文章图片
【Android中ViewPager实现滑动条及与Fragment结合的实例教程】使用Fragment实现ViewPager滑动
效果图:
文章图片
在第一个页面加一个Btn
文章图片
第一页面向第二页面滑动
文章图片
第二页面向第三个页面滑动
一些说明:
FragmentPagerAdapter派生自PagerAdapter,它是用来呈现Fragment页面的,这些Fragment页面会一直保存在fragment manager中,以便用户可以随时取用。
这个适配器最好用于有限个静态fragment页面的管理。尽管不可见的视图有时会被销毁,但用户所有访问过的fragment都会被保存在内存中。因此fragment实例会保存大量的各种状态,这就造成了很大的内存开销。所以如果要处理大量的页面切换,建议使用FragmentStatePagerAdapter.
每一个使用FragmentPagerAdapter的ViewPager都要有一个有效的ID集合,有效ID的集合就是Fragment的集合(感谢夫诸同学的提示)
对于FragmentPagerAdapter的派生类,只需要重写getItem(int)和getCount()就可以了。
具体实现:
1、适配器实现——FragmentPagerAdapter
先看完整代码,再细讲:
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | public class FragAdapter extends FragmentPagerAdapter {
private List<
Fragment>
mFragments;
public FragAdapter(FragmentManager fm,List<
Fragment>
fragments) {
super (fm);
// TODO Auto-generated constructor stub
mFragments=fragments;
}
@Override
public Fragment getItem( int arg0) {
// TODO Auto-generated method stub
return mFragments.get(arg0);
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return mFragments.size();
}
} |
对于构造函数,这里申请了一个Fragment的List对象,用于保存用于滑动的Fragment对象,并在创造函数中初始化:
?
1 2 3 4 5 | public FragAdapter(FragmentManager fm,List<
Fragment>
fragments) {
super (fm);
// TODO Auto-generated constructor stub
mFragments=fragments;
} |
最后,getCount()返回用于滑动的fragment总数;
从构造函数所以看出,我们要构造Fragment的集合才行,所以下面我们就先产生我们所需要的Fragment类;
2、三个Fragment类
第一个Fragment类:
XML:(layout1.xml)
?
1 2 3 4 5 6 7 8 9 10 11 12 13 | <
? xml version = "1.0" encoding = "utf-8" ?>
<
LinearLayout xmlns:android = "http://schemas.android.com/apk/res/android"
android:layout_width = "match_parent"
android:layout_height = "match_parent"
android:background = "#ffffff"
android:orientation = "vertical" >
<
Button android:id = "@+id/fragment1_btn"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "show toast"
/>
<
/ LinearLayout >
|
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | public class Fragment1 extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
View view= inflater.inflate(R.layout.layout1, container, false );
//对View中控件的操作方法
Button btn = (Button)view.findViewById(R.id.fragment1_btn);
btn.setOnClickListener( new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Toast.makeText(getActivity(), "点击了第一个fragment的BTN" , Toast.LENGTH_SHORT).show();
}
});
return view;
}
} |
第二个Fragment类:
XML代码:(layout2.xml)原生代码,没有做任何更改
?
1 2 3 4 5 6 7 8 9 | <
? xml version = "1.0" encoding = "utf-8" ?>
<
LinearLayout xmlns:android = "http://schemas.android.com/apk/res/android"
android:layout_width = "match_parent"
android:layout_height = "match_parent"
android:background = "#ffff00"
android:orientation = "vertical" >
<
/ LinearLayout >
|
1 2 3 4 5 6 7 8 9 10 11 | public class Fragment2 extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
View view=inflater.inflate(R.layout.layout2, container, false );
return view;
}
} |
XML代码:(layout3.xml)同样,原生代码,没做任何更改
?
1 2 3 4 5 6 7 8 9 | <
? xml version = "1.0" encoding = "utf-8" ?>
<
LinearLayout xmlns:android = "http://schemas.android.com/apk/res/android"
android:layout_width = "match_parent"
android:layout_height = "match_parent"
android:background = "#ff00ff"
android:orientation = "vertical" >
<
/ LinearLayout >
|
?
1 2 3 4 5 6 7 8 9 10 11 | public class Fragment3 extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
View view=inflater.inflate(R.layout.layout3, container, false );
return view;
}
} |
核心代码:
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | public class MainActivity extends FragmentActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super .onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//构造适配器
List<
Fragment>
fragments= new ArrayList<
Fragment>
();
fragments.add( new Fragment1());
fragments.add( new Fragment2());
fragments.add( new Fragment3());
FragAdapter adapter = new FragAdapter(getSupportFragmentManager(), fragments);
//设定适配器
ViewPager vp = (ViewPager)findViewById(R.id.viewpager);
vp.setAdapter(adapter);
}
} |
这段代码主要分为两步,第一步:构造适配器;第二步:设定适配器。
先看构造适配器的过程:
?
1 2 3 4 5 6 | //构造适配器
List<
Fragment>
fragments= new ArrayList<
Fragment>
();
fragments.add( new Fragment1());
fragments.add( new Fragment2());
fragments.add( new Fragment3());
FragAdapter adapter = new FragAdapter(getSupportFragmentManager(), fragments);
|
至于第二步,设定适配器,没什么好讲的。
推荐阅读
- [Android Pro]开发一流Android SDK
- Spring,@Controller,@RequestMapping, @ResponseBody,@RequestParam
- [Android Pro]开发一流的 Android SDK(Fabric SDK 的创建经验)
- Android之动画
- Android 走向MD的配色风格
- Android学习 之 ColorStateList按钮文字变色
- mac 下载软件无法将程序拖移至app出现错误
- Android Handler官方说明
- android 生命周期