在札记(5)中我们就说过要弄一个模仿微信页面切换的东东,就是ViewPager+Fragment实现的一个东西,札记(6)中也学习了一下ViewPager的一些基本用法,本节就来将两者结合以实现我们想要的效果!
先看下Google官网怎么说:
大概意思就是:
ViewPager更多的时候是与Fragment协同使用,这样可以更加方便地去创建Page和管理Page的生命周期,但是使用的不再是PageAdapter适配器,而是他的子类:FragmentPagerAdapter和FragmentStatePagerAdapter,他们提供了更加简单代码来构建我们的用户界面!
看完这段话,可能会有下面的疑问:
1)FragmentPagerAdapter和FragmentStatePagerAdapter有什么区别,用哪个?
答:前者适用于页面较少的情况,后者对应页面较多的情况,现在只能这样告诉你;貌似这个和他们缓存page的问题有关,以后再研究吧,通常用的都是FragmentPagerAdapter较多!
2)提供更加简单的代码…怎么简单法? 答:如官方文档所述,只需要实现getItem()与getCount()两个方法即可!相比起PagerAdapter要实现四个方法简单多了
必须要实现的两个方法:getItem( )与getCount( )
意思:返回与特定postion(下标)有关联的Fragment!
意思:返回有效的View的数目,就是View集合中的View的个数
3)代码实现微信页面切换效果:
什么都别说,先看下效果图:
上面的实现其实还是蛮简单的,核心就是ViewPager + Fragment来实现的,那么现在就来讲解下如何实现上面的效果
step 1:首先肯定是先弄我们的主布局文件啦:
一条装逼的顶部标题栏+可切换Page的ViewPager+底部导航栏
底部导航栏和札记6中的实现方法是一致的,就不讲了
activity_main.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 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 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 <LinearLayout xmlns:android ="http://schemas.android.com/apk/res/android" xmlns:tools ="http://schemas.android.com/tools" android:id ="@+id/LinearLayout1" android:layout_width ="match_parent" android:layout_height ="match_parent" android:orientation ="vertical" tools:context =".MainActivity" > <RelativeLayout android:layout_width ="match_parent" android:layout_height ="50dp" android:background ="#22292C" > <TextView android:id ="@+id/textView1" android:layout_width ="wrap_content" android:layout_height ="wrap_content" android:layout_centerVertical ="true" android:layout_marginLeft ="18dp" android:text ="微信(4)" android:textColor ="#ffffff" android:textSize ="18sp" /> <Button android:id ="@+id/btnadd" android:layout_width ="30dp" android:layout_height ="30dp" android:layout_marginRight ="15dp" android:layout_centerVertical ="true" android:layout_alignBaseline ="@+id/textView1" android:layout_alignBottom ="@+id/textView1" android:layout_alignParentRight ="true" android:background ="@drawable/ap9" /> <Button android:layout_width ="30dp" android:layout_height ="30dp" android:layout_marginRight ="15dp" android:layout_toLeftOf ="@id/btnadd" android:layout_centerVertical ="true" android:background ="@drawable/alt" /> </RelativeLayout > <android.support.v4.view.ViewPager android:id ="@+id/vPager" android:layout_width ="wrap_content" android:layout_height ="0dp" android:layout_gravity ="center" android:layout_weight ="1.0" android:background ="#000000" android:flipInterval ="30" android:persistentDrawingCache ="animation" /> <ImageView android:layout_width ="match_parent" android:layout_height ="1dp" android:src ="@drawable/aoc" /> <LinearLayout android:orientation ="horizontal" android:layout_width ="match_parent" android:layout_height ="55dp" android:background ="#FCFCFC" > <RelativeLayout android:id ="@+id/weixin_layout" android:layout_width ="0dp" android:layout_height ="match_parent" android:layout_weight ="1" > <LinearLayout android:layout_width ="match_parent" android:layout_height ="wrap_content" android:layout_centerVertical ="true" android:orientation ="vertical" > <ImageView android:id ="@+id/weixin_img" android:layout_width ="30dp" android:layout_height ="30dp" android:layout_gravity ="center_horizontal" android:src ="@drawable/ahk" /> <TextView android:id ="@+id/weixin_txt" android:layout_width ="wrap_content" android:layout_height ="wrap_content" android:layout_gravity ="center_horizontal" android:text ="微信" android:textColor ="#999999" /> </LinearLayout > </RelativeLayout > <RelativeLayout android:id ="@+id/tongxunlu_layout" android:layout_width ="0dp" android:layout_height ="match_parent" android:layout_weight ="1" > <LinearLayout android:layout_width ="match_parent" android:layout_height ="wrap_content" android:layout_centerVertical ="true" android:orientation ="vertical" > <ImageView android:id ="@+id/tongxunlu_img" android:layout_width ="30dp" android:layout_height ="30dp" android:layout_gravity ="center_horizontal" android:src ="@drawable/ahi" /> <TextView android:id ="@+id/tongxunlu_txt" android:layout_width ="wrap_content" android:layout_height ="wrap_content" android:layout_gravity ="center_horizontal" android:text ="通讯录" android:textColor ="#999999" /> </LinearLayout > </RelativeLayout > <RelativeLayout android:id ="@+id/faxian_layout" android:layout_width ="0dp" android:layout_height ="match_parent" android:layout_weight ="1" > <LinearLayout android:layout_width ="match_parent" android:layout_height ="wrap_content" android:layout_centerVertical ="true" android:orientation ="vertical" > <ImageView android:id ="@+id/faxian_img" android:layout_width ="30dp" android:layout_height ="30dp" android:layout_gravity ="center_horizontal" android:src ="@drawable/ahm" /> <TextView android:id ="@+id/faxian_txt" android:layout_width ="wrap_content" android:layout_height ="wrap_content" android:layout_gravity ="center_horizontal" android:text ="发现" android:textColor ="#999999" /> </LinearLayout > </RelativeLayout > <RelativeLayout android:id ="@+id/me_layout" android:layout_width ="0dp" android:layout_height ="match_parent" android:layout_weight ="1" > <LinearLayout android:layout_width ="match_parent" android:layout_height ="wrap_content" android:layout_centerVertical ="true" android:orientation ="vertical" > <ImageView android:id ="@+id/me_img" android:layout_width ="30dp" android:layout_height ="30dp" android:layout_gravity ="center_horizontal" android:src ="@drawable/aho" /> <TextView android:id ="@+id/me_txt" android:layout_width ="wrap_content" android:layout_height ="wrap_content" android:layout_gravity ="center_horizontal" android:text ="我" android:textColor ="#999999" /> </LinearLayout > </RelativeLayout > </LinearLayout > </LinearLayout >
step 2:主布局写完了,接着就写每个Fragment的布局和对应的Fragment类咯,这里每个Fragment就是一个简单的TextView + 不同的背景颜色,一式四份就可以了!
fg1.xml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <?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:gravity ="center" android:background ="#FAEBD7" android:orientation ="vertical" > <TextView android:layout_width ="wrap_content" android:layout_height ="wrap_content" android:text ="微信Fragment" /> </LinearLayout >
Fg1.java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 package com.jay.example.viewpagerfragment; import android.os.Bundle ; import android.support.v4.app.Fragment ; import android.view.LayoutInflater ; import android.view.View ; import android.view.ViewGroup ; public class Fg1 extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R .layout.fg1, container,false ); return view; } }
step 3:接着就要自定义我们的FragmentPagerAdapter,这个也很简单,只要重写那两个基本方法就可以了,分别是getItem( )和getCount( )
MyFragmentPagerAdapter.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 package com.jay.example.viewpagerfragment; import java.util.ArrayList; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; public class MyFragmentPageAadpter extends FragmentPagerAdapter { private ArrayList<Fragment> fragmentsList; public MyFragmentPageAadpter (FragmentManager fm) {super (fm);} public MyFragmentPageAadpter (FragmentManager fm, ArrayList<Fragment> fragments) { super (fm); this .fragmentsList = fragments; } @Override public Fragment getItem (int index) { return fragmentsList.get (index) ; } @Override public int getCount () { return fragmentsList.size () ; } }
step 4:接着就到我们最后一步MainActivity的编写了,同样也是不复杂的,要做什么呢?
①实例化四个Fragment对象后,把他们放到View集合中,通过Adapter适配器与ViewPager进行绑定咯!然后就可以滑动ViewPager进行页面的切换了
②当我们点击底部导航条的按钮时,我们需要切换ViewPager中显示的Fragment,这怎么搞?
答:对点击的按钮的id进行判断,判断点击的是第几个,调用viewpager.setCurrentItem(index)即可
③当我们滑动页面时,底部导航条的图标也要跟着变换,这又怎么搞?
答这个也很简单,重写ViewPager的OnPageChangeListener的onPageScrollStateChanged()方法
当参数等于2时,说明此时滑动完毕,viewpager.getCurrentItem( )获得当前页面序号,从而设置第几个按钮处于选中状态!
MainActivity.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 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 package com.jay.example.viewpagerfragment; import java.util.ArrayList; 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.view.ViewPager; import android.support.v4.view.ViewPager.OnPageChangeListener; import android.view.View; import android.view.View.OnClickListener; import android.widget.ImageView; import android.widget.RelativeLayout; import android.widget.TextView; public class MainActivity extends FragmentActivity { private Fg1 fg1; private Fg2 fg2; private Fg3 fg3; private Fg4 fg4; private ViewPager mPager; private ArrayList<Fragment> fragmentsList; private MyFragmentPageAadpter mAdapter; private RelativeLayout weixin_layout; private RelativeLayout tongxunlu_layout; private RelativeLayout faxian_layout; private RelativeLayout me_layout; private ImageView weixin_img; private ImageView tongxunlu_img; private ImageView faxian_img; private ImageView me_img; private TextView weixin_txt; private TextView tongxunlu_txt; private TextView faxian_txt; private TextView me_txt; private int Gray = 0xFF999999 ; private int Green =0xFF45C01A ; public FragmentManager fManager; public MyOnClick myclick; public MyPageChangeListener myPageChange; @Override protected void onCreate(Bundle savedInstanceState ) { super.onCreate(savedInstanceState ) ; setContentView(R.layout .activity_main ) ; getActionBar() .hide() ; fManager = getSupportFragmentManager() ; initViewPager() ; initViews() ; initState() ; } private void initViews() { myclick = new MyOnClick() ; myPageChange = new MyPageChangeListener() ; mPager = (ViewPager) findViewById(R.id .vPager ) ; weixin_layout = (RelativeLayout) findViewById(R.id .weixin_layout ) ; tongxunlu_layout = (RelativeLayout) findViewById(R.id .tongxunlu_layout ) ; faxian_layout = (RelativeLayout) findViewById(R.id .faxian_layout ) ; me_layout = (RelativeLayout) findViewById(R.id .me_layout ) ; weixin_img = (ImageView) findViewById(R.id .weixin_img ) ; tongxunlu_img = (ImageView) findViewById(R.id .tongxunlu_img ) ; faxian_img = (ImageView) findViewById(R.id .faxian_img ) ; me_img = (ImageView) findViewById(R.id .me_img ) ; weixin_txt = (TextView) findViewById(R.id .weixin_txt ) ; tongxunlu_txt = (TextView) findViewById(R.id .tongxunlu_txt ) ; faxian_txt = (TextView) findViewById(R.id .faxian_txt ) ; me_txt = (TextView) findViewById(R.id .me_txt ) ; mPager.setAdapter(mAdapter ) ; mPager.setOnPageChangeListener(myPageChange ) ; weixin_layout.setOnClickListener(myclick ) ; tongxunlu_layout.setOnClickListener(myclick ) ; faxian_layout.setOnClickListener(myclick ) ; me_layout.setOnClickListener(myclick ) ; } private void initViewPager() { fragmentsList = new ArrayList<Fragment>() ; fg1 = new Fg1() ; fg2 = new Fg2() ; fg3 = new Fg3() ; fg4 = new Fg4() ; fragmentsList.add(fg1); fragmentsList.add(fg2); fragmentsList.add(fg3); fragmentsList.add(fg4); mAdapter = new MyFragmentPageAadpter(fManager ,fragmentsList ) ; } private void initState() { weixin_img.setImageResource(R.drawable .ahj ) ; weixin_txt.setTextColor(Green) ; mPager.setCurrentItem(0) ; } public class MyOnClick implements OnClickListener { @Override public void onClick(View view ) { clearChioce() ; iconChange(view .getId () ); } } public class MyPageChangeListener implements OnPageChangeListener { @Override public void onPageScrollStateChanged(int arg0 ) { if (arg0 == 2 ) { int i = mPager.getCurrentItem() ; clearChioce() ; iconChange(i ) ; } } @Override public void onPageScrolled(int arg0 , float arg1 , int arg2 ) {} @Override public void onPageSelected(int index ) {} } public void clearChioce() { weixin_img.setImageResource(R.drawable .ahk ) ; weixin_txt.setTextColor(Gray) ; tongxunlu_img.setImageResource(R.drawable .ahi ) ; tongxunlu_txt.setTextColor(Gray) ; faxian_img.setImageResource(R.drawable .ahm ) ; faxian_txt.setTextColor(Gray) ; me_img.setImageResource(R.drawable .aho ) ; me_txt.setTextColor(Gray) ; } public void iconChange(int num ) { switch (num) { case R . id.weixin_layout:case 0 : weixin_img.setImageResource(R.drawable .ahj ) ; weixin_txt.setTextColor(Green) ; mPager.setCurrentItem(0) ; break; case R . id.tongxunlu_layout:case 1 : tongxunlu_img.setImageResource(R.drawable .ahh ) ; tongxunlu_txt.setTextColor(Green) ; mPager.setCurrentItem(1) ; break; case R . id.faxian_layout:case 2 : faxian_img.setImageResource(R.drawable .ahl ) ; faxian_txt.setTextColor(Green) ; mPager.setCurrentItem(2) ; break; case R . id.me_layout:case 3 : me_img.setImageResource(R.drawable .ahn ) ; me_txt.setTextColor(Green) ; mPager.setCurrentItem(3) ; break; } } }
最后说几句:
代码还是比较简单的哈,没什么高大上的技术,只是希望可以帮到和我一样的初学者….
另外viewPager好像有缓冲page的功能
就是保存Page的状态,不过是相邻的两个,比如,你现在在2号页,此时1号和3号是缓存
在内存当中的,但是上面如果我们是1然后切换到4页面的话,会发现,2,3两个界面也加载了!
流程如下:
1 –>2(此时缓存1,2和3) –>3(此时缓存2,3和4) –>4(此时缓存3和4);
总结来说就是:ViewPager会缓存当前页面相邻的两个Page
不过好像有个是设置缓存页面数量的属性吧,一时半伙想不起来,如果有知道的读者欢迎指出,万分感激! (使用ViewPagerAdapter可以用ViewPager的setOffscreenPageLimit来增加缓冲页。FragmentStatePagerAdapter有点类似ListView只缓冲当前页面)
本节代码下载:
http://pan.baidu.com/s/1dDcTNFj
扩展阅读:PagerAdapter和FragmentPagerAdapter和FragmentStatePagerAdapter区别
子view里使用这个方法,getParent().requestDisallowInterceptTouchEvent(true)
可以中断ViewPager获取到事件。
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 public class GalleryViewPager extends ViewPager { private float lastX; private boolean slidingLeft; private boolean slidingRight; public GalleryViewPager(final Context context, final AttributeSet attrs) { super (context, attrs); } public GalleryViewPager(final Context context) { super (context); } @Override public boolean onTouchEvent(final MotionEvent ev) { final int action = ev.getAction(); switch (action) { case MotionEvent.ACTION_DOWN: this .getParent().requestDisallowInterceptTouchEvent(true ); this .lastX = ev.getX(); break ; case MotionEvent.ACTION_UP: this .getParent().requestDisallowInterceptTouchEvent(false ); this .lastX = ev.getX(); this .slidingLeft = false ; this .slidingRight = false ; break ; case MotionEvent.ACTION_MOVE: if (this .getCurrentItem() == 0 ) { if (this .lastX <= ev.getX() && !this .slidingRight) { this .getParent().requestDisallowInterceptTouchEvent(false ); } else { this .slidingRight = true ; this .lastX = ev.getX(); this .getParent().requestDisallowInterceptTouchEvent(true ); } } else if (this .getCurrentItem() == this .getAdapter().getCount() - 1 ) { if (this .lastX >= ev.getX() && !this .slidingLeft) { this .getParent().requestDisallowInterceptTouchEvent(false ); } else { this .slidingLeft = true ; this .lastX = ev.getX(); this .getParent().requestDisallowInterceptTouchEvent(true ); } } break ; } super .onTouchEvent(ev); return true ; } }