自定義PageAdapter實現無限輪播

自定義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) {
        
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章