Android滾動條廣告實現(xiàn)

前言

幾乎每個上線的App上面都會有個滾動條廣告将鸵,滾動條廣告主要以文字標題的形式存在作儿,什么點開文章你就能賺一百萬啊饭于、看完轉(zhuǎn)走這個你就能平安一生啊這樣的標題伸蚯,都是以標題廣告的形式吸引人的,當然開個小玩笑啦膘壶,哈哈错蝴,畢竟是要賺錢的嘛,接上幾個廣告是正常滴~~

image.png

之前在項目中要求要做一個滾動條輪播的展示颓芭,就是在滾動條上放幾條廣告進行輪播顷锰。一開始知識覺得直接用TextSwitcher或者ViewSwitcher就可以了。雖然這樣也能滿足需求亡问,但是項目里有好幾個地方都用到了滾動條廣告官紫。如果每個地方都寫一套同樣的代碼的話,就有點浪費了州藕。況且代碼的設(shè)計原則其中之一就是復(fù)用束世,所以就寫了一個自定義的viewSwitcher來直接用了,當然寫了自定義的床玻,功能要求當然要完善一點毁涉。這個viewSwitcher支持我們在滾動條上自定義view。外部需要設(shè)置滾動條上自定義的布局和設(shè)置數(shù)據(jù)源锈死。我們先看下效果圖吧贫堰。


ViewSwitcher的介紹

  • ViewSwitcher 設(shè)置動畫
    ViewSwitcher 代表了視圖切換組件, 本身繼承了FrameLayout ,可以將多個View疊在一起 ,每次只顯示一個組件,ViewSwitcher 支持指定動畫效果.我們自定義ViewSwitcher的時候,當程序控制從一個View切換到另個View時馅精,我們可以可以重寫下面這兩個方法來設(shè)置組件切換動畫效果
       setInAnimation(Animation inAnimation)
       setOutAnimation(Animation outAnimation)
  • ViewSwitcher 設(shè)置view
    給ViewSwitcher設(shè)置view的方法時是調(diào)用下面這個方法
setFactory(ViewFactory factory)

這個ViewFactory是一個接口,里面有一個makeview方法粱檀,正是通過這個方法我們構(gòu)造并顯示在ViewSwitcher洲敢,當然我們自定義ViewSwitcher時候,這里是傳入一個布局id茄蚯,這樣我們就可以自由的設(shè)置顯示布局啦~

   /* 給viewSwitch添加顯示的view压彭,可以自由設(shè)置 外部調(diào)用     
    * @param layoutId    
    */  
  public void addView(final int layoutId){      
     setFactory(new ViewFactory(){       
       @Override       
       public View makeView() {            
               return LayoutInflater.from(getContext()).inflate(layoutId,null);     
       }    
    }); 
   }

實例介紹

實現(xiàn)原理還是比較簡單,我們可以直接看代碼渗常,下面我們直接通過代碼來介紹這個控件的使用吧
里面都有詳細的注釋壮不,相信都可以看得懂。

/**
 * 自由設(shè)置view的viewSwitcher
 * Created by Administrator on 2017/5/13.
 */
public class CarouselView extends ViewSwitcher {

    private int mCutItem;
    private int loopTime;//循環(huán)時間
    private MyHandler myHandler;
    private ArrayList<String> listString;

    public CarouselView(Context context) {
        this(context, null);
    }

    public CarouselView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initData();
        initAnimation();
    }

    /**
     * 初始化一些變量
     */
    private void initData(){
       listString = new ArrayList<>();
        myHandler = new MyHandler(this);
    }

    /**
     * 給viewSwitch添加顯示的view皱碘,可以自由設(shè)置询一,外部調(diào)用
     * @param layoutId 自定義view的布局id
     */
    public void addView(final int layoutId){
        setFactory(new ViewFactory(){
            @Override
            public View makeView() {
                return LayoutInflater.from(getContext()).inflate(layoutId,null);
            }
        });
    }

    /**
     * 初始化進入和出去動畫
     */
    private void initAnimation(){
        setInAnimation(AnimationUtils.loadAnimation(getContext(),R.anim.translate_in));
        setOutAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.translate_out));
    }

    /**
     * 設(shè)置數(shù)據(jù)源并展示view,外部調(diào)用
     * @param mList
     * @param time
     */
    public void upDataListAndView(ArrayList<String> mList,int time){
         mCutItem = 0;
        loopTime = time;
        if (null == mList) {
           return;
        }
        listString.clear();
        listString.addAll(mList);
        updataView(mList.get(0),getCurrentView(),mCutItem);
    }

    /**
     *展示下一條廣告
     */
    public void showNextView() {
        if (null == listString || listString.size() < 2) {
          return;
        }
        mCutItem = mCutItem == listString.size() - 1 ? 0 : mCutItem + 1;
        updataView(listString.get(mCutItem), getNextView(),mCutItem);
        showNext();
    }

    /**
     * 啟動輪播
     */
    public void startLooping() {
        if (null == listString || listString.size() < 2 ) {
           return;
        }
        myHandler.removeMessages(0);
        myHandler.sendEmptyMessageDelayed(0, loopTime);
    }

    /**
     * 停止輪播
     */
    public void stopLooping(){
        myHandler.removeMessages(0);
    }

    /**
     * 在當前view上設(shè)置數(shù)據(jù)
     * @param text
     * @param view
     */
    private void updataView(String text,View view, final int mCutItem){
        TextView textView = (TextView) view.findViewById(R.id.tv_carouse_text);
        textView.setText(text);
        textView.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (null != onClickItemListener) {
                    onClickItemListener.onClick(mCutItem);
                }
                //Toast.makeText(getContext(), "你點擊了第" + position + "條廣告", Toast.LENGTH_SHORT).show();
            }
        });
    }

    /**
     * @description 主線程Handler
     * @note 因為存在定時任務(wù),并且TextSwitcherView持有Activity的引用
     * 所以這里采用弱引用健蕊,主要針對內(nèi)存回收的時候Activity泄露
     **/
    private static class MyHandler extends Handler {

        private WeakReference<CarouselView> mRef;
        public MyHandler(CarouselView view){
            mRef = new WeakReference<CarouselView>(view);
        }
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            CarouselView mView = this.mRef.get();
            mView.showNextView();//展示下一條廣告菱阵,會調(diào)用shownext方法展示下一條廣告
            mView.startLooping();//啟動輪播,間隔后展示下一條
        }
    }

    OnClickItemListener onClickItemListener;

    /**
     * 定義一個接口回調(diào)缩功,響應(yīng)廣告點擊
     */
    interface OnClickItemListener{
        void onClick(int position);
    }

    public void setOnClickListener(OnClickItemListener onClickListener){
        this.onClickItemListener = onClickListener;
    }
}

看完了代碼之后晴及,接著我們來看一下外部的使用方法

外部使用方法

  • 外部調(diào)用
    carouselView.addView(R.layout.itemview);   
    carouselView.upDataListAndView(mList, 3000); 
    carouselView.setOnClickListener(new CarouselView.OnClickItemListener() {       
       @Override         
       public void onClick(int position) {        
          Toast.makeText(mContext, "你點擊了第" + position + "條廣告",Toast.LENGTH_SHORT).show();     
      }    
   });
  • itemview的布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal" 
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
    <ImageView
        android:layout_width="25dp"
        android:layout_height="25dp"
        android:layout_marginLeft="10dp"
        android:src="@mipmap/ic_launcher"/>
    <TextView
        android:id="@+id/tv_carouse_text"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:layout_weight="1"
        android:gravity="center"
        android:text="111"/>
</LinearLayout>
  • 設(shè)置進入動畫
    translate_in.xml
<?xml version="1.0" encoding="utf-8"?>
<set  xmlns:android="http://schemas.android.com/apk/res/android"    
            android:interpolator="@android:anim/linear_interpolator"    
            android:duration="2000"  >    
<translate   
     android:fromXDelta="0%"     
     android:fromYDelta="100%"   
     android:toXDelta="0%"   
     android:toYDelta="0%"/>
</set>
  • 設(shè)置出去動畫
    translate_out.xml
 <?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"    
           android:interpolator="@android:interpolator/linear"    
           android:duration="1000">  
  <translate        
    android:fromXDelta="0%"      
    android:fromYDelta="0%"       
    android:toXDelta="0%"     
    android:toYDelta="-100%"/>
</set>

結(jié)語

實現(xiàn)就是這樣子的,外部設(shè)置view布局嫡锌,不過給view布局里面的控件設(shè)置數(shù)據(jù)需要在里面調(diào)用看虑稼,具體看你設(shè)置怎么樣的布局,這種可以根據(jù)布局在里面靈活控制一下势木。動畫也是在外邊自由設(shè)置蛛倦。就寫到這里啦,enjoy it~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末跟压,一起剝皮案震驚了整個濱河市胰蝠,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌震蒋,老刑警劉巖茸塞,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異查剖,居然都是意外死亡钾虐,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進店門笋庄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來效扫,“玉大人,你說我怎么就攤上這事直砂【剩” “怎么了?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵静暂,是天一觀的道長济丘。 經(jīng)常有香客問我,道長洽蛀,這世上最難降的妖魔是什么摹迷? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮郊供,結(jié)果婚禮上峡碉,老公的妹妹穿的比我還像新娘。我一直安慰自己驮审,他們只是感情好鲫寄,可當我...
    茶點故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布吉执。 她就那樣靜靜地躺著,像睡著了一般塔拳。 火紅的嫁衣襯著肌膚如雪鼠证。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天靠抑,我揣著相機與錄音量九,去河邊找鬼。 笑死颂碧,一個胖子當著我的面吹牛荠列,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播载城,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼肌似,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了诉瓦?” 一聲冷哼從身側(cè)響起川队,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎睬澡,沒想到半個月后固额,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡煞聪,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年斗躏,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片昔脯。...
    茶點故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡啄糙,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出云稚,到底是詐尸還是另有隱情隧饼,我是刑警寧澤,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布静陈,位于F島的核電站燕雁,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏窿给。R本人自食惡果不足惜贵白,卻給世界環(huán)境...
    茶點故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一率拒、第九天 我趴在偏房一處隱蔽的房頂上張望崩泡。 院中可真熱鬧,春花似錦猬膨、人聲如沸角撞。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽谒所。三九已至热康,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間劣领,已是汗流浹背姐军。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留尖淘,地道東北人奕锌。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像村生,于是被迫代替她去往敵國和親惊暴。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,592評論 2 353

推薦閱讀更多精彩內(nèi)容