仿京東,淘寶廣告滾動(dòng)

最近看UI再設(shè)計(jì)新的APP效果圖,發(fā)現(xiàn)首頁(yè)使用了類似京東首頁(yè)京東日?qǐng)?bào)模塊類似的廣告自動(dòng)滾動(dòng)效果,于是就想著提前準(zhǔn)備,寫(xiě)個(gè)通用組件。網(wǎng)上查閱了很多的文章,絕大多數(shù)都是說(shuō)使用TextSwitcher來(lái)實(shí)現(xiàn)這個(gè)效果。我也用TextSwitcher實(shí)踐了一下,確實(shí)能實(shí)現(xiàn),然后也很簡(jiǎn)單只需要給TextSwitcher設(shè)置inAnimation(進(jìn)入動(dòng)畫(huà)),outAnimation(離開(kāi)動(dòng)畫(huà)),factory(在他的makeView中生成View),然后需要一個(gè)Handler定時(shí)切換即可完成,不理解的同學(xué)可以去看一下TextSwitcher的用法。

京東快報(bào).png

但是,無(wú)意間,發(fā)現(xiàn)淘寶首頁(yè)也有這么一個(gè)功能,叫淘寶頭條,雖然說(shuō)都是廣告的上下滾動(dòng),但是淘寶頭條的內(nèi)容還有有區(qū)別的,他包含了兩條文本廣告信息,以及一張圖片。

淘寶頭條.png

此時(shí),這樣子的需求,使用TextSwitcher是無(wú)法滿足我們的需求了,原因很簡(jiǎn)單,TextSwitcher中的子View是由我們?cè)O(shè)置的Factory的makeView方法創(chuàng)建的,而這個(gè)方法返回的,必須是TextView對(duì)象,這一點(diǎn)再TextSwitcher的源碼中可以證實(shí).

@Override
public void addView(View child, int index, ViewGroup.LayoutParams params) {
  if (!(child instanceof TextView)) {
    throw new IllegalArgumentException(
      "TextSwitcher children must be instances of TextView");
  }
  super.addView(child, index, params);
}

其實(shí),android SDK中不僅僅提供了用于文本滾動(dòng)的TextSwitcher,同時(shí)還提供了用于圖片滾動(dòng)的ImageSwitcher,但是他們都無(wú)法滿足我們的需求,因此,就尋思著是否可以有一個(gè)自定義布局的組件,來(lái)實(shí)現(xiàn)這個(gè)功能呢,這時(shí)候我查閱了一下TextSwitcher與ImageSwitcher,發(fā)現(xiàn)他們都是ViewSwitcher的子類,那就通過(guò)一個(gè)集成ViewSwitcher來(lái)實(shí)現(xiàn)我們的需求吧。

廢話不多說(shuō),先把效果圖拿上來(lái)(似乎已經(jīng)扯了很多廢話了。。。)

廣告滾動(dòng).gif

整個(gè)流程其實(shí)很簡(jiǎn)單,我們只需要將一開(kāi)始講述的幾點(diǎn)封裝到我們的Switcher中就可以了,首先我們定義一個(gè)Adapter,讓他作為數(shù)據(jù)與Switcher之間的橋梁,同時(shí),這邊使用了泛型,讓我們使用過(guò)程中更加靈活

public interface IAdvertAdapter<T> {

    /**
     * 獲取當(dāng)前數(shù)據(jù)個(gè)數(shù)
     * @return
     */
    public int getCount();

    /**
     * 獲取position位置對(duì)應(yīng)的數(shù)據(jù)
     * @param position
     * @return
     */
    public T getItem(int position);

    /**
     * 創(chuàng)建View
     * 這邊僅僅是創(chuàng)建View,不要給View綁定數(shù)據(jù),或者添加事件監(jiān)聽(tīng)之類
     * Only new View or inflate layout
     * @return
     */
    public View makeView();

    /**
     * 為View綁定數(shù)據(jù),同時(shí)添加對(duì)應(yīng)的事件監(jiān)聽(tīng)
     * @param view
     * @param data
     */
    public void bindView(View view, T data);
}

然后,重點(diǎn)來(lái)了,創(chuàng)建我們的組件,繼承ViewSwitcher,同時(shí)也實(shí)現(xiàn)ViewSwitcher.ViewFactory接口,該類中其實(shí)也沒(méi)有太多動(dòng)心,就不貼出來(lái)了,下面會(huì)給出源碼地址,比較核心的還是Handler,實(shí)現(xiàn)自動(dòng)輪播,定時(shí)發(fā)送一條消息,然后調(diào)用ViewSwitcher的showNext()方法,就能實(shí)現(xiàn)自動(dòng)輪播功能了。

private class ScrollHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what){
                case FLAG_START_SCROLL:
                    View view = getNextView();
                    mAdapter.bindView(view, mAdapter.getItem(currentIndex));
                    Log.e(TAG, "Index:" + currentIndex + " //" + mAdapter.getItem(currentIndex).toString());
                    showNext();
                    currentIndex = ++currentIndex % mAdapter.getCount();
                    mHandler.sendEmptyMessageDelayed(FLAG_START_SCROLL, mTimeSpan);
                    break;
                case FLAG_STOP_SCROLL:
                    mHandler.removeMessages(FLAG_START_SCROLL);
                    break;
                case FLAG_REFRESH:
                    currentIndex = 0;
                    removeAllViews();
                    start();
                    break;
            }
        }
    }

使用起來(lái)也非常簡(jiǎn)單,類似與列表的使用,分一下幾步走

1.實(shí)現(xiàn)IAdvertAdapter,關(guān)鍵實(shí)現(xiàn)makeView(),再這個(gè)方法中加載我們自定義的布局,或者自己創(chuàng)建的View,當(dāng)然,這邊不要去做數(shù)據(jù)綁定相關(guān)的操作。

2.實(shí)現(xiàn)IAdvertAdapter中的bindView,做一下數(shù)據(jù)綁定,事件綁定相關(guān)的操作

3.switchers.setAdapter(new IAdvertAdapter(context, data));

這邊只是寫(xiě)了大體的使用步驟,具體還是看源碼吧,非常簡(jiǎn)單,喜歡的加伙伴可以幫忙加一個(gè)小星星,算是一點(diǎn)鼓勵(lì)吧_

https://github.com/yunzhouhua/AdvertSwitcher

疑問(wèn)

1.如果廣告很多創(chuàng)建了很多的View,而最終也就顯示兩個(gè),是否浪費(fèi)性能?有優(yōu)化嘛?

? 開(kāi)始我就有這樣的疑問(wèn),以為makeView每次都會(huì)創(chuàng)建新的View添加帶ViewSwitcher中,也準(zhǔn)備做一下View復(fù)用,但是看了ViewSwitcher的源碼后,發(fā)現(xiàn)多費(fèi)心了,google爸爸早就幫我們想到了。ViewSwitcher中只會(huì)有兩個(gè)View,makeView也只會(huì)調(diào)用兩次,如果有第三次的情況,程序肯定會(huì)奔潰,不信嘛?看下下面的代碼,ViewSwitcher-addView

@Override
    public void addView(View child, int index, ViewGroup.LayoutParams params) {
        if (getChildCount() >= 2) {
            throw new IllegalStateException("Can't add more than 2 views to a ViewSwitcher");
        }
        super.addView(child, index, params);
    }

ViewSwitcher內(nèi)部再setFactory的時(shí)候連續(xù)調(diào)用了兩次obtainView創(chuàng)建出了對(duì)應(yīng)的View并添加到ViewSwitcher,而之后的滾動(dòng)效果完全就是這兩個(gè)view通過(guò)動(dòng)畫(huà),控制顯示/隱藏實(shí)現(xiàn)的。感興趣的可以看一下源碼。

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

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

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,716評(píng)論 25 709
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,020評(píng)論 4 61
  • 把你的詩(shī)編成我的歌, 唱給你聽(tīng), 躺在你的文字里, 如若躺在崇山一席綠地上, 聽(tīng)蜜蜂與蝴蝶的輕吟, 看暮色與炊煙的...
    孝蒽閱讀 358評(píng)論 0 1
  • 啟幕杯男籃邀請(qǐng)賽,豐瑞男籃的型男們打出了第二名的好成績(jī)。通過(guò)比賽,增強(qiáng)了團(tuán)隊(duì)凝聚力,也驚喜地發(fā)現(xiàn)豐瑞所存在很多外冷...
    d155b3e6ac2c閱讀 470評(píng)論 0 0
  • 1.每餐八分飽 營(yíng)養(yǎng)得到補(bǔ)充,并且精神充沛;少兩分,沒(méi)有精力做事,多兩分過(guò)飽,人變得懶散。
    太陽(yáng)花_崔文杰閱讀 544評(píng)論 1 8

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