自定義PageAdapter實現無限輪播
我們要是實現如下圖所示無限輪播的ViewPager,使用ViewPager就要寫Adapter
自定義PageAdapter需要重寫幾個方法
-
public int getCount()
-
public Object instantiateItem(@NonNull ViewGroup container, int position)
-
public boolean isViewFromObject(@NonNull View view, @NonNull Object object)
-
public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object)
分別來解釋下這幾個方法的含義
-
public int getCount()
返回填充數據的大小
注意,如果想實現無限輪播,就需要將這個返回值設置爲Integer.MAX_VALUE
如果只是希望從頭滑到尾,那就返回填充數據的大小
-
public Object instantiateItem(@NonNull ViewGroup container, int position)
創建給定位置的頁面。適配器負責將視圖添加到此處給定的容器中,保證執行finishUpdate(ViewGroup)之前完成這個函數的操作
/**
* Create the page for the given position. The adapter is responsible
* for adding the view to the container given here, although it only
* must ensure this is done by the time it returns from
* {@link #finishUpdate(ViewGroup)}.
*
* @param container The containing View in which the page will be shown.
* @param position The page position to be instantiated.
* @return Returns an Object representing the new page. This does not
* need to be a View, but can be some other container of the page.
*/
@NonNull
public Object instantiateItem(@NonNull ViewGroup container, int position) {
return instantiateItem((View) container, position);
}
我們可以得知,instantiateItem是爲了填充視圖內容,所以,我們在這裏將圖片集合添加到這個容器中container。
我們這裏是實現無限輪播,那就不能使用position來獲取圖片,如果你設置三張圖片,從第三張向右滑需要切換到第一張圖片,但是position這個參數會給你返回3(從0開始是第一張照片),就會出現邊界越界,那我們如何獲取滑到了哪個位置呢,使用取模,position對數據長度取模,當你滑到位置3時,數據長度爲3,取模結果爲0,正好是第一張圖片的位置。
重點來了!!!!!!
重點來了!!!!!!
重點來了!!!!!!
爲什麼我們要加 if (parent != null) parent.removeView(imageView);
這個判斷呢?
如果我們不加這句判斷,就會報 java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
異常,因爲我們addView的時候,你的view已經有了parent(就是container),不能再添加了,所以,我們需要先判斷添加的view是否有parent,如果有,我們就這個view remove,然後再添加。
public Object instantiateItem(@NonNull ViewGroup container, int position) {
int realPosition = position % imageViews.size();
ImageView imageView = imageViews.get(realPosition);
ViewPager parent = (ViewPager) imageView.getParent();
if (parent != null) {
parent.removeView(imageView);
}
container.addView(imageView, 0);
imageView.setTag(position);
return imageView;
}
- public boolean isViewFromObject(@NonNull View view, @NonNull Object object)
確定頁面視圖是否與特定的鍵對象相關聯由{@link
#instantiateItem(ViewGroup,int)}返回。**這個方法是PagerAdapter正常運行所必需的。**我們只需要返回view==object即可
/**
* Determines whether a page View is associated with a specific key object
* as returned by {@link #instantiateItem(ViewGroup, int)}. This method is
* required for a PagerAdapter to function properly.
*
* @param view Page View to check for association with <code>object</code>
* @param object Object to check for association with <code>view</code>
* @return true if <code>view</code> is associated with the key object <code>object</code>
*/
public abstract boolean isViewFromObject(@NonNull View view, @NonNull Object object);
- public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object)
刪除給定位置的頁面。適配器負責用於從其容器中刪除視圖,儘管它僅必須確保當它從{@link
#finishUpdate(ViewGroup)}返回時完成此操作。
我們在instantiateItem方法中判斷了刪除邏輯,這裏就空着就好了。
/**
* Remove a page for the given position. The adapter is responsible
* for removing the view from its container, although it only must ensure
* this is done by the time it returns from {@link #finishUpdate(ViewGroup)}.
*
* @param container The containing View from which the page will be removed.
* @param position The page position to be removed.
* @param object The same object that was returned by
* {@link #instantiateItem(View, int)}.
*/
public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
destroyItem((View) container, position, object);
}
完整代碼如下
package com.felix.baselibrary.UI.banner;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;
import java.util.ArrayList;
import java.util.Observable;
public class FxBannerAdapter extends PagerAdapter {
private static final String TAG = FxBannerAdapter.class.getSimpleName();
private OnAdapterItemClickListener mItemClickListener;
public void setImageViews(ArrayList<ImageView> imageViews) {
this.imageViews = imageViews;
}
private ArrayList<ImageView> imageViews;
@NonNull
@Override
public Object instantiateItem(@NonNull ViewGroup container, int position) {
int realPosition = position % imageViews.size();
ImageView imageView = imageViews.get(realPosition);
ViewPager parent = (ViewPager) imageView.getParent();
if (parent != null) {
Log.d(TAG, "removeView(imageView)");
parent.removeView(imageView);
}
imageView.setTag(position);
return imageView;
}
@Override
public int getCount() {
return Integer.MAX_VALUE;
}
@Override
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
return view == object;
}
@Override
public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
}
}