Android仿轉(zhuǎn)轉(zhuǎn)首頁banner

banner_g--.gif
代碼地址:Github

效果由來

我司設(shè)計(jì)一向比較喜歡高大上的東西(我也喜歡...),無意中看到轉(zhuǎn)轉(zhuǎn)首頁banner動(dòng)畫不錯(cuò),想得之,由于項(xiàng)目工期和人手限制,遭到IOS開發(fā)和我的強(qiáng)烈反對,設(shè)計(jì)也即將妥協(xié),我抱著獵奇心態(tài)(手欠)搜了下網(wǎng)上看看有沒有類似效果,結(jié)果讓我搜到了iOS版本 ,iOS開發(fā)歡心集成,我則愁眉苦展,輾轉(zhuǎn)兩天之久,出此代碼.

具體效果

  • 底部背景圖片隨著banner滾動(dòng)實(shí)現(xiàn)reveal效果
  • banner上層圖片縮放效果

實(shí)現(xiàn)原理

  • 上層banner用viewPager實(shí)現(xiàn),通過handler定時(shí)發(fā)送消息實(shí)現(xiàn)可循環(huán)自動(dòng)播放的banner
  • 下層背景圖片通過多張圖片折疊,然后通過viewPager滾動(dòng)監(jiān)聽來操作底部圖片的顯示和隱藏
  • 縮放動(dòng)畫用屬性動(dòng)畫實(shí)現(xiàn),根據(jù)viewPager滑動(dòng)停止和移動(dòng)判斷是否放大或縮小

特性

  • 可獨(dú)立拆分使用,設(shè)置屬性可變?yōu)槠胀╞anner,修改如需特殊要求可修改源碼item_banner.xml布局即可

部分關(guān)鍵代碼

    private class ViewPageChangeListener implements ViewPager.OnPageChangeListener {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            // 判斷viewPager左右滑動(dòng)相關(guān)
            if (mViewPagerIndex == position) {
                if (bannerBgContainer.getBannerBgViews().size() > position % bannerBgContainer.getBannerBgViews().size() + 1) {
                    bannerBgContainer.getBannerBgViews().get(position % bannerBgContainer.getBannerBgViews().size() + 1).bringToFront();
                    bannerBgContainer.getBannerBgViews().get(position % bannerBgContainer.getBannerBgViews().size() + 1)
                            .hideClipAnimation((positionOffset - reduceValue) * upValue > 1 ? 1 : (positionOffset - reduceValue) * upValue);
                } else if (bannerBgContainer.getBannerBgViews().size() == position % bannerBgContainer.getBannerBgViews().size() + 1) {
                    bannerBgContainer.getBannerBgViews().get(0).bringToFront();
                    bannerBgContainer.getBannerBgViews().get(0)
                            .hideClipAnimation((positionOffset - reduceValue) * upValue > 1 ? 1 : (positionOffset - reduceValue) * upValue);
                }
            } else {
                if (position / bannerBgContainer.getBannerBgViews().size() >= 0) {
                    bannerBgContainer.getBannerBgViews().get(position % bannerBgContainer.getBannerBgViews().size()).bringToFront();
                    bannerBgContainer.getBannerBgViews().get(position % bannerBgContainer.getBannerBgViews().size())
                            .showClipAnimation(0, bannerBgContainer.getHeight() / 2,
                                    (1 - (positionOffset + reduceValue)) * upValue > 1 ? 1 : (1 - (positionOffset + reduceValue)) * upValue);
                }
            }

        }

        @Override
        public void onPageSelected(int position) {
            int i = position % bannerInfos.size();
            if (i == 0) {
                animIndicator.setTranslationX(totalDistance * 0.0f);
            } else if (i == bannerInfos.size() - 1) {
                animIndicator.setTranslationX(totalDistance * 1.0f);
            }
            // 不是手動(dòng)拖拽時(shí), 當(dāng)前position 減1 因?yàn)閟etCurrentItem方法會(huì)在滑動(dòng)之前把position設(shè)置成當(dāng)前位置(此處是坑)
            mViewPagerIndex = position - 1;
        }

        @Override
        public void onPageScrollStateChanged(int state) {
            // 如果是手動(dòng)拖拽,則取當(dāng)前位置
            if (state == 1) {
                if (loopViewPager != null) {
                    mViewPagerIndex = loopViewPager.getCurrentItem();
                }
            }
        }
    }

使用方法

  • 在 app的build.gradle 里面引用
implementation 'com.tokiii:reveal-banner:1.0.0'
  • 布局文件
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="240dp">

    <com.wikikii.bannerlib.banner.view.BannerBgContainer
        android:id="@+id/banner_bg_container"
        android:layout_width="match_parent"
        android:layout_height="240dp" />


    <com.wikikii.bannerlib.banner.LoopLayout
        android:id="@+id/loop_layout"
        android:layout_width="match_parent"
        android:layout_height="168dp"
        android:layout_gravity="bottom" />
</FrameLayout>
  • 代碼設(shè)置屬性
        // 設(shè)置輪播圖屬性
        loopLayout.setLoop_ms(3000);//輪播的速度(毫秒)
        loopLayout.setLoop_duration(400);//滑動(dòng)的速率(毫秒)
        loopLayout.setScaleAnimation(true);// 設(shè)置是否需要?jiǎng)赢?        loopLayout.setLoop_style(LoopStyle.Empty);//輪播的樣式-默認(rèn)empty
        loopLayout.setIndicatorLocation(IndicatorLocation.Center);//指示器位置-中Center
        loopLayout.initializeData(this);
        // 設(shè)置輪播圖屬性end
        
        // 準(zhǔn)備數(shù)據(jù)
        ArrayList<BannerInfo> bannerInfos = new ArrayList<>();
        List<Object> bgList = new ArrayList<>();
        bannerInfos.add(new BannerInfo(R.mipmap.banner_1, "first"));
        bannerInfos.add(new BannerInfo(R.mipmap.banner_2, "second"));
        bgList.add(R.mipmap.banner_bg1);
        bgList.add(R.mipmap.banner_bg2);
        // 設(shè)置監(jiān)聽
        loopLayout.setOnLoadImageViewListener(new OnDefaultImageViewLoader() {
            @Override
            public void onLoadImageView(ImageView view, Object object) {
                Glide.with(view.getContext())
                        .load(object)
                        .into(view);
            }
        });
        loopLayout.setOnBannerItemClickListener(this);
        if (bannerInfos.size() == 0) {
            return;
        }
        loopLayout.setLoopData(bannerInfos);// 設(shè)置輪播數(shù)據(jù)
        bannerBgContainer.setBannerBackBg(this, bgList);// 背景容器設(shè)置輪播圖片
        loopLayout.setBannerBgContainer(bannerBgContainer);// 聯(lián)動(dòng)
        loopLayout.startLoop();// 開始循環(huán)

后記

詳細(xì)請看具體代碼已經(jīng)上傳到Github ,由于時(shí)間倉促,實(shí)際效果與轉(zhuǎn)轉(zhuǎn)還是多少有些不同,代碼注釋較少,等后續(xù)優(yōu)化接近完美會(huì)補(bǔ)上關(guān)鍵代碼邏輯和原理(也沒有多復(fù)雜),敬請期待.....

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,030評論 25 709
  • 秒針滴滴答答轉(zhuǎn)個(gè)不停,青春消失在那個(gè)不起眼的黃昏。 在那個(gè)街角,我送出的祝福你是否都收到了。車流涌動(dòng)的街道,我們隔...
    夜光姑娘閱讀 112評論 0 1
  • 我,一個(gè)人名教師,一枚忙碌的單身汪,每天起來會(huì)先點(diǎn)開“喜馬拉雅FM”,我喜歡聽里面的文章,最近關(guān)注了一個(gè)名叫“行動(dòng)...
    宅女也風(fēng)流閱讀 367評論 2 3
  • 昨天一直糾結(jié)的一件事,被一個(gè)朋友說了句,別太把自己當(dāng)回事,你真的沒有那么重要。 起因,好奇害死貓 ...
    張姝_心歡閱讀 325評論 0 1
  • 以前總認(rèn)為堅(jiān)持會(huì)讓我們變強(qiáng)大 但是長大后發(fā)現(xiàn) 讓我們強(qiáng)大的是放下
    沫小草閱讀 138評論 0 0

友情鏈接更多精彩內(nèi)容