之前公司做直播的項目時,也想模仿現在比較流行的上下滑動切換直播間的方式。稍稍想了一種比較簡便的方式。
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;
}
}