这里说的ViewPager的使用主要是结合Fragment的使用,对于ViewPager我们也需要新建适配器,然后我们把Fragment集合传入进去,调用Adapter就好了。这部分比较简单。
package com.gin.xjh.shin_music.adapter;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import java.util.List;
/**
* Created by Gin on 2018/4/23.
*/
public class FragmentAdapter extends FragmentPagerAdapter {
private List fragments;
private FragmentManager fm;
public FragmentAdapter(FragmentManager fm, List fragmentList) {
super(fm);
this.fragments=fragmentList;
this.fm=fm;
}
@Override
public Fragment getItem(int position) {
return fragments.get(position);
}
@Override
public int getCount() {
return fragments.size();
}
}
最重要的是后面我们对于ViewPager的监听以及我们想要一个指示器的效果。
这里我们就要提及其中的三个实现方法的功能(代码注释中有参数的详细解释)
方法名 | 功能 |
---|---|
onPageScrolled | 在屏幕滚动过程中不断被调用,表示翻页程度 |
onPageSelected | 用手指滑动翻页的时候表示哪个页面被选中 |
onPageScrollStateChanged | 在手指操作屏幕的时候发生变化 |
根据上面所说到的,我们可以想到指示器肯定是在onPageScrolled上面实现的。
想要点击调转的效果的化我们就需要把Button设置点击事件,然后编写下面的代码mViewPager.setCurrentItem(0)
就好了。这样我们在onPageSelected方法中改变对应的样式变化(计算方法在注释中说的很明白)。
private List fragments = new ArrayList<>();
private FragmentAdapter adapter;
private void initEvent() {
fragments.add(new Fragment_Shin());
fragments.add(new Fragment_Online());
fragments.add(new Fragment_Local());
Index = 0;
shin_img.setImageResource(R.drawable.shin_red);
shin_text.setTextColor(Color.RED);
mSreenWidth = getWindowManager().getDefaultDisplay().getWidth();
adapter = new FragmentAdapter(getSupportFragmentManager(), fragments);
mViewPager.setAdapter(adapter);
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mline.getLayoutParams();
lp.width = mSreenWidth / 3;
mline.setLayoutParams(lp);
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
/**
* 这个方法会在屏幕滚动过程中不断被调用。
* 有三个参数,第一个position,这个参数要特别注意一下。当用手指滑动时,如果手指按在页面上不动,position和当前页面index是一致的;
* 如果手指向左拖动(相应页面向右翻动),这时候position大部分时间和当前页面是一致的,
* 只有翻页成功的情况下最后一次调用才会变为目标页面;
* 如果手指向右拖动(相应页面向左翻动),这时候position大部分时间和目标页面是一致的,只有翻页不成功的情况下最后一次调用才会变为原页面。
* 当直接设置setCurrentItem翻页时,如果是相邻的情况(比如现在是第二个页面,跳到第一或者第三个页面),
* 如果页面向右翻动,大部分时间是和当前页面是一致的,只有最后才变成目标页面;
* 如果向左翻动,position和目标页面是一致的。这和用手指拖动页面翻动是基本一致的。
* 如果不是相邻的情况,比如我从第一个页面跳到第三个页面,position先是0,然后逐步变成1,然后逐步变成2;
* 我从第三个页面跳到第一个页面,position先是1,然后逐步变成0,并没有出现为2的情况。
* positionOffset是当前页面滑动比例,如果页面向右翻动,这个值不断变大,最后在趋近1的情况后突变为0。
* 如果页面向左翻动,这个值不断变小,最后变为0。
* positionOffsetPixels是当前页面滑动像素,变化情况和positionOffset一致。
**/
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if (Index == position) {//向右移动
ChangeLine((int) ((Index + positionOffset) * mSreenWidth / 3));
} else {//向左移动
ChangeLine((int) ((Index + positionOffset - 1) * mSreenWidth / 3));
}
}
/**
* 用手指滑动翻页的时候表示哪个页面被选中
* 如果翻动成功了(滑动的距离够长),手指抬起来就会立即执行这个方法,
* position就是当前滑动到的页面
*/
@Override
public void onPageSelected(int position) {
switch (position) {
case 0:
if(Index==1){
Online_music_img.setImageResource(R.drawable.online_music_white);
Online_music_text.setTextColor(Color.WHITE);
}
else if(Index==2){
Local_music_img.setImageResource(R.drawable.local_music_white);
Local_music_text.setTextColor(Color.WHITE);
}
shin_img.setImageResource(R.drawable.shin_red);
shin_text.setTextColor(Color.RED);
Index = 0;
ChangeLine(0);
break;
case 1:
if(Index==0){
shin_img.setImageResource(R.drawable.shin_white);
shin_text.setTextColor(Color.WHITE);
}
else if(Index==2){
Local_music_img.setImageResource(R.drawable.local_music_white);
Local_music_text.setTextColor(Color.WHITE);
}
Online_music_img.setImageResource(R.drawable.online_music_red);
Online_music_text.setTextColor(Color.RED);
Index = 1;
ChangeLine(mSreenWidth / 3);
break;
case 2:
if(Index==0){
shin_img.setImageResource(R.drawable.shin_white);
shin_text.setTextColor(Color.WHITE);
}
else if(Index==1){
Online_music_img.setImageResource(R.drawable.online_music_white);
Online_music_text.setTextColor(Color.WHITE);
}
Local_music_img.setImageResource(R.drawable.local_music_red);
Local_music_text.setTextColor(Color.RED);
Index = 2;
ChangeLine(2 * (mSreenWidth / 3));
break;
}
}
/**
* 这个方法在手指操作屏幕的时候发生变化。有三个值:0(END),1(PRESS) , 2(UP) 。
* 当用手指滑动翻页时,手指按下去的时候会触发这个方法,state值为1,
* 手指抬起时,如果发生了滑动(即使很小),这个值会变为2,然后最后变为0 。总共执行这个方法三次。
* 一种特殊情况是手指按下去以后一点滑动也没有发生,这个时候只会调用这个方法两次,state值分别是1,0 。
* 当setCurrentItem翻页时,会执行这个方法两次,state值分别为2 , 0 。
*/
@Override
public void onPageScrollStateChanged(int state) {
}
});
shin.setOnClickListener(this);
Online_music.setOnClickListener(this);
Local_music.setOnClickListener(this);
}
/**
- 改变偏移长度
- @param len
*/
private void ChangeLine(int len) {
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mline.getLayoutParams();
lp.leftMargin = len;
mline.setLayoutParams(lp);
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.shin:
mViewPager.setCurrentItem(0);
break;
case R.id.Online_music:
mViewPager.setCurrentItem(1);
break;
case R.id.Local_music:
mViewPager.setCurrentItem(2);
break;
}
}
但是我们这样写就会发现,如果我们在第二个页面输入了值,然后我们跳转到第三个页面再跳回第二个页面,我们输入的值并没有清除,这个的原因就是,ViewPager缓存了你显示的页面的左右页面的,所以数据不会清除。
我们主要有两种解决方法:
我们需要在OnPageChangeListener监听ViewPager的移动,然后对于改变发送通知给Fragment手动对控件进行清空,这里主要是通知,就不多说了。
在Fragment的生命周期中有下面的setUserVisibleHint方法(但是在官方的生命周期图中看不到),当fragment被用户可见时,setUserVisibleHint()会调用且传入true值,当fragment不被用户可见时,setUserVisibleHint()则得到false值。所以这个方法是肯定会在Tab变动的伤害被调用的,所以我们在这里进行初始化会好很多,但是在在这里有一点不好是因为是主要画面变动了就会调用所以不建议使用。
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
if(mFind!=null){
mFind.setText("");
}
super.setUserVisibleHint(isVisibleToUser);
}