首頁 > 軟體

Android封裝Banner控制元件方法介紹

2023-08-24 18:01:02

如上圖所示效果我們應該都不陌生,這是一個簡單的banner輪播效果,網上也有很多的開源專案,但有時候可能我們僅僅只需要一些簡單的效果,並不需要其他過多的東西。這裡簡單的對banner進行一下封裝,隨時呼叫和新增一些新的功能。

程式碼展示

/**
 * Created by xiaolong on 2018/1/23.
 */
public class BannerView extends FrameLayout implements ViewPager.OnPageChangeListener{
    private ViewPager viewPager;
    //網路圖片地址
    private List<String> imageUrls;
    //指示點的容器
    private LinearLayout pointLayout;
    //當前頁面位置
    private int currentItem;
    //自動播放時間
    private int autoPlayTime = 2000;
    //是否自動播放
    private boolean isAutoPlay;
    //是否是一張圖片
    private boolean isOneImage;
    //監聽事件
    private OnBannerItemClick onBannerItemClick;
    //這裡利用handler實現迴圈播放
    private Handler handler = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            currentItem++;
            currentItem = currentItem % (imageUrls.size() + 2);
            viewPager.setCurrentItem(currentItem);
            handler.sendEmptyMessageDelayed(0,autoPlayTime);
            return false;
        }
    });
    public BannerView(@NonNull Context context) {
        this(context,null);
    }
    public BannerView(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);
    }
    public BannerView(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs,R.styleable.BannerView,0,0);
        //預設自動播放
        isAutoPlay = typedArray.getBoolean(R.styleable.BannerView_isAutoPlay,true);
        typedArray.recycle();
        viewPager = new ViewPager(getContext());
        pointLayout = new LinearLayout(getContext());
        //新增監聽事件
        viewPager.addOnPageChangeListener(this);
        //利用佈局屬性將指示器容器放置底部並居中
        FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        params.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
        params.bottomMargin = 60;
        addView(viewPager);
        addView(pointLayout,params);
    }
    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
    }
    @Override
    public void onPageSelected(int position) {
        currentItem = position;
        if (!isOneImage) {
            switchToPoint(toRealPosition(position));
        }
    }
    @Override
    public void onPageScrollStateChanged(int state) {
    //根據滑動鬆開後的狀態,去判斷當前的current 並跳轉到指定current
        if (state == ViewPager.SCROLL_STATE_IDLE) {
            int current = viewPager.getCurrentItem();
            int lastReal = viewPager.getAdapter().getCount() - 2;
            if (current == 0) {
                viewPager.setCurrentItem(lastReal, false);
            } else if (current == lastReal + 1) {
                viewPager.setCurrentItem(1, false);
            }
        }
    }
    //設定viewpager介面卡
    private class BannerAdapter extends PagerAdapter {
        @Override
        public int getCount() {
            return imageUrls.size() + 2;
        }
        @Override
        public boolean isViewFromObject(View view, Object object) {
            return view == object;
        }
        @Override
        public Object instantiateItem(ViewGroup container, final int position) {
            ImageView imageView = new ImageView(getContext());
            imageView.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (onBannerItemClick != null) {
                        onBannerItemClick.onItemClick(toRealPosition(position));
                    }
                }
            });
            imageView.setScaleType(ImageView.ScaleType.FIT_XY);
            Glide.with(getContext()).load(imageUrls.get(toRealPosition(position))).into(imageView);
            container.addView(imageView);
            return imageView;
        }
        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            container.removeView((View) object);
        }
    }
    //新增網路圖片
    public void setImageUrls(List<String> imageUrls) {
        this.imageUrls = imageUrls;
        if (imageUrls.size() <= 1) {
            isOneImage = true;
        }else {
            isOneImage = false;
        }
        initViewPager();
    }
    //載入viewPager
    private void initViewPager() {
        if (!isOneImage) {
            //新增指示點
            addPoints();
        }
        BannerAdapter adapter = new BannerAdapter();
        viewPager.setAdapter(adapter);
        //預設當前圖片
        viewPager.setCurrentItem(1);
        //判斷是否自動播放和是否是一張圖片的情況
        if (isAutoPlay && !isOneImage) {
            handler.sendEmptyMessageDelayed(0,autoPlayTime);
        }
    }
    //新增指示點
    private void addPoints() {
        LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        lp.setMargins(10, 10, 10, 10);
        ImageView imageView;
        int length = imageUrls.size();
        for (int i = 0; i < length; i++) {
            imageView = new ImageView(getContext());
            imageView.setLayoutParams(lp);
            imageView.setImageResource(R.drawable.select_point_bg);
            pointLayout.addView(imageView);
        }
        switchToPoint(0);
    }
    //切換指示器
    private void switchToPoint(int currentPoint) {
        for (int i = 0; i < pointLayout.getChildCount(); i++) {
            pointLayout.getChildAt(i).setEnabled(false);
        }
        pointLayout.getChildAt(currentPoint).setEnabled(true);
    }
    //返回真實的位置
    private int toRealPosition(int position) {
        int realPosition;
        if (imageUrls.size() > 0) {
            realPosition = (position - 1) % imageUrls.size();
            if (realPosition < 0)
                realPosition += imageUrls.size();
        }else{
            realPosition = 0;
        }
        return realPosition;
    }
    public void setAutoPlay(boolean autoPlay) {
        isAutoPlay = autoPlay;
    }
    public void setOnBannerItemClick(OnBannerItemClick onBannerItemClick) {
        this.onBannerItemClick = onBannerItemClick;
    }
    //新增監聽事件回撥
    public interface OnBannerItemClick{
        void onItemClick(int position);
    }
}

呼叫方式

        //設定是否自動播放
        bannerView.setAutoPlay(true);
        //新增網路圖片
        bannerView.setImageUrls(data);
        //banner的點選事件
        bannerView.setOnBannerItemClick(new BannerView.OnBannerItemClick() {
            @Override
            public void onItemClick(int position) {
                Toast.makeText(MainActivity.this,"圖片" + position,Toast.LENGTH_LONG).show();
            }
        });

程式碼分析

這裡我只考慮了使用網路圖片進行展示,使用本地圖片原理是一樣的,在裡面多加個方法即可。此效果程式碼不是很複雜,通俗易懂。唯一值得一說的是我在實現viewpager無限滑動時採用的是return imageUrls.size() + 2的方法。這裡我們新增兩條資料分別為第一條和最後一條。第一條代表著最後一張圖片而最後一條則代表著第一張圖片,這裡手動畫個圖:

通過此圖我們應該不難發現,當我們滑動到第二個0的時候則跳轉到第一個0,滑動到第一個2的時候則跳轉到第二個2。這裡0代表第一張圖片,2代表第二張圖片。這樣就可以實現無限滑動的效果了,可能有些人會覺得這樣做有些複雜還要判斷真實的位置不如直接將getConut()返回一個最大值然後取其中間值即可。但這樣做其實程式碼效能並不是很高。

結束

這樣一個常用的banner就寫好了,當我們需要實現一些滑動動畫的時候,可以在裡面實現viewpager的動畫屬性即可。先從簡單的入手,慢慢的就可以瞭解更多的原理和知識點,哈哈!這裡貼出傳送門以便參考。

到此這篇關於Android封裝Banner控制元件方法介紹的文章就介紹到這了,更多相關Android封裝Banner內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com