之前公司做直播的项目时,也想模仿现在比较流行的上下滑动切换直播间的方式。稍稍想了一种比较简便的方式。
1.使用竖直方向的ViewPager实现上线滑动切换的效果。
2.为了让ViewPager能无限循环下去,同时考虑到不能再ViewPager里面方大量的Fragment对象。这样也就想到了类似ListView的重用机制。只改变显示的数据,而不使用大量的Fragment。这样也比较符合直播间的样式都一样。 只是每个直播间的数据都不一样的情况。
3.由于直播间的页面显示的控件View太多。所以采用Fragment来较好的控制View的机制。
竖直方向的ViewPager实现网上有太多的方案,大都比较合理,我就采用了设置ViewPager.PageTransformer的方式;后面的需求就需要做一个循环的ViewPager来加载Fragment。我把它命名为LoopFragmentPageAdapter。
通过ViewPager的原理知道。在大量数据的时候,ViewPager里面至少加载3页的对象。所以我们至少要创建3个页面的Fragment对象。让ViewPager总是显示在中间的位置,而中间的页面总是显示我们需要的类容就行。其他页面来做切换的辅助效果。
直接上代码:
/**
*要求每个页面的样式是一致的
*改变的只是数据不一样
* Created by liuwb on 2017/2/22.
*/
public abstract class LoopFragmentPageAdapter extends PagerAdapter
implements ViewPager.OnPageChangeListener {
private ViewPagerviewPager;
private final FragmentManager mFragmentManager;
private Fragment TransactionmCurTransaction=null;
private Fragment mCurrentPrimaryItem=null;
private final static intPAGE=3;
private final static intINDEX=1;
private final static intSTART_INDEX=0;
private ArrayList fragments;
private Context context;
//记录真正的位置
private int realPage;
private boolean isInitDataToView;
public LoopFragmentPageAdapter(Context context,FragmentManager fm,
ViewPager viewPager) {
this.context= context;
mFragmentManager= fm;
this.viewPager= viewPager;
viewPager.clearOnPageChangeListeners();
viewPager.addOnPageChangeListener(this);
if(0== getDataSourceCount())return;
initView();
}
public void nextPage() {
if(0== getDataSourceCount())return;
viewPager.setCurrentItem(2, true);
}
/**
*初始显示Fragment
**/
private voidinitView() {
fragments=newArrayList<>(PAGE);
if(getDataSourceCount() ==1) {
fragments.add(createFragment(0));
return;
}
for(inti =0;i
if(i ==0) {
fragments.add(createFragment(getDataSourceCount() -1));
}else if(i ==PAGE-1) {
fragments.add(createFragment(PAGE-2));
}else{
fragments.add(createFragment(i -1));
}
}
}
/**
*根据数据的位置创建显示的Fragment对象页面
*
*@paramposition数据的真实位置
*@return
*/
public abstractFragmentcreateFragment(intposition);
/**
*加载数据
*
*@paramfragment
*@paramposition
*/
public abstract voidloadFragmentData(Fragment fragment, intposition);
/**
*显示数据的数量
*
*@return
*/
public abstract intgetDataSourceCount();
private voidsetDataToFragment() {
if(!isInitDataToView) {
isInitDataToView=true;
intsize = getDataSourceCount();
if(size ==1) {
loadFragmentData(fragments.get(0),0);
return;
}
for(inti =0;i
intindex =0;
if(0== i) {
index = size -1;
}else{
index = i -1;
}
loadFragmentData(fragments.get(i),index);
}
viewPager.setCurrentItem(1, false);
}
}
public voidshowIndex(intindex) {
if(0== getDataSourceCount())return;
if(index == getDataSourceCount()) {
realPage=0;
}else{
realPage= index;
}
if(getDataSourceCount() ==1) {
loadFragmentData(fragments.get(0),0);
}else{
indexChange();
}
}
@Override
public intgetCount() {
return(null==fragments) ?0:fragments.size();
}
@Override
public booleanisViewFromObject(View view,Object object) {
return((Fragment) object).getView() == view;
}
@Override
publicObjectinstantiateItem(ViewGroup container, intposition) {
if(mCurTransaction==null) {
mCurTransaction=mFragmentManager.beginTransaction();
}
final longitemId = getItemId(position);
// Do we already have this fragment?
String name =makeFragmentName(container.getId(),itemId);
Fragment fragment =mFragmentManager.findFragmentByTag(name);
if(fragment !=null) {
mCurTransaction.attach(fragment);
}else{
fragment =fragments.get(position);
mCurTransaction.add(container.getId(),fragment,
makeFragmentName(container.getId(),itemId));
}
if(fragment !=mCurrentPrimaryItem) {
fragment.setMenuVisibility(false);
fragment.setUserVisibleHint(false);
}
returnfragment;
}
@Override
public voiddestroyItem(ViewGroup container, intposition,Object object) {
if(mCurTransaction==null) {
mCurTransaction=mFragmentManager.beginTransaction();
}
mCurTransaction.detach((Fragment) object);
}
@Override
public voidsetPrimaryItem(ViewGroup container, intposition,Object object) {
Fragment fragment = (Fragment) object;
if(fragment !=mCurrentPrimaryItem) {
if(mCurrentPrimaryItem!=null) {
mCurrentPrimaryItem.setMenuVisibility(false);
mCurrentPrimaryItem.setUserVisibleHint(false);
}
if(fragment !=null) {
fragment.setMenuVisibility(true);
fragment.setUserVisibleHint(true);
}
mCurrentPrimaryItem= fragment;
}
}
@Override
public voidfinishUpdate(ViewGroup container) {
setDataToFragment();
if(mCurTransaction!=null) {
mCurTransaction.commitAllowingStateLoss();
mCurTransaction=null;
mFragmentManager.executePendingTransactions();
}
}
@Override
public voidonPageScrolled(intposition, floatpositionOffset, intpositionOffsetPixels) {
if(0== positionOffset && position !=INDEX&& getDataSourceCount() !=1) {
fragmentPageExit(fragments.get(INDEX),realPage);
if(position >INDEX) {
realPage++;
}else{
realPage--;
}
if(realPage== -INDEX) {
realPage= getDataSourceCount() -INDEX;
}else if(realPage== getDataSourceCount()) {
realPage=START_INDEX;
}
indexChange();
fragmentPageSelected(fragments.get(INDEX),realPage);
}
}
/**
*数据离开页面
*
*@paramposition
*/
protected voidfragmentPageExit(Fragment fragment, intposition) {
}
/**
*数据进入页面
*
*@paramposition
*/
protected voidfragmentPageSelected(Fragment fragment, intposition) {
}
private voidindexChange() {
if(realPage==START_INDEX) {
loadFragmentData(fragments.get(0),getDataSourceCount() -1);
}else{
loadFragmentData(fragments.get(0),realPage-1);
}
loadFragmentData(fragments.get(1),realPage);
if(realPage== getDataSourceCount() -1) {
loadFragmentData(fragments.get(2),0);
}else{
if(realPage==0&& getDataSourceCount() ==2) {
loadFragmentData(fragments.get(2),getDataSourceCount() -1);
}else{
loadFragmentData(fragments.get(2),realPage+1);
}
}
viewPager.setCurrentItem(1, false);
}
@Override
public voidonPageSelected(intposition) {
}
@Override
public voidonPageScrollStateChanged(intstate) {
}
public longgetItemId(intposition) {
returnposition;
}
public intgetRealPage() {
returnrealPage;
}
private staticStringmakeFragmentName(intviewId, longid) {
return"android:switcher:"+ viewId +":"+ id;
}
}