Android循环广告位的实现

本文介绍了如何在Android中实现一个通用且简单的循环广告位,利用ViewPager和CirclePageIndicator创建滑动广告,并提供了一个自定义控件的实现方式。通过设置适配器和调用startScroller()方法,可以轻松实现广告轮播。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Android循环广告位是很常用的一个功能,很大一部分APP中都会使用到,之前看到过网上一些,要么实现起来很复杂,要么通用性不强,于是,决心自己写一个通用性强并且简单的,以后项目中用到直接拿过来即可!

在这里我们主要会用到ViewPager,谷歌在v4包中提供了这个类,这个类可以用于做一些页面滑动的UI,比如说APP第一次安装时的滑动翻页介绍,应用的导航功能等等。

这里还用到了第三方的一个开源控件,CirclePageIndicator,我们这里主要是用于实现广告下方的小圆点。

这里我把广告位做成了一个自定义的控件,以后可以在布局中使用,然后在代码中调用即可,非常方便!

如何自定义控件,不在这次的讨论范围之内,如果对这一方面还不了解的朋友,建议先去看看Android是如何自定义控件的。

这里先上代码:


public class CarouselView extends LinearLayout{
   public CarouselView(Context context) {
      super(context);
      init(context);
   }
   public CarouselView(Context context, AttributeSet attrs) {
      super(context, attrs);
      init(context);
   }
   @SuppressLint("NewApi")
   public CarouselView(Context context, AttributeSet attrs, int defStyleAttr) {
      super(context, attrs, defStyleAttr);
      init(context);
   }
   @SuppressLint("NewApi")
   public CarouselView(Context context, AttributeSet attrs, int defStyleAttr,
         int defStyleRes) {
      super(context, attrs, defStyleAttr, defStyleRes);
      init(context);
   }

   private ViewPager carouselpager;
   private CirclePageIndicator indicator ;
   private ScheduledExecutorService scheduledExecutorService;
   
   private void init(Context context) {
      scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
      LayoutInflater.from(context).inflate(R.layout.carouselview_layout, this,true);
      carouselpager = (ViewPager) findViewById(R.id.carouselpager);
      indicator = (CirclePageIndicator) findViewById(R.id.indicator);
   }
   /**
    * 停止切换
    */
   public void stopScroller() {
      if (scheduledExecutorService != null
            && !scheduledExecutorService.isShutdown()) {
         scheduledExecutorService.shutdownNow();
      }
   }
   public void startScroller() {
      if (scheduledExecutorService != null
            && !scheduledExecutorService.isShutdown()) {
         scheduledExecutorService.shutdownNow();
         scheduledExecutorService = null;
      }
      scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
      if (!scheduledExecutorService.isShutdown()) {
         scheduledExecutorService.scheduleAtFixedRate(
               new ScrollBannerTask(), 6, 6, TimeUnit.SECONDS);
      }
   }
   /** 当前轮播图的索引 */
   private int currentItem = 0;
    
   private IPageOnPageChangeListener listener;
   private List<View> viewLists = null;
   
   public void setAdapter(BasePageAdapter<View> adapter) {
      carouselpager.setAdapter(adapter);
      this.viewLists = adapter.getList();
      indicator.setViewPager(carouselpager);
      indicator.notifyDataSetChanged();
      indicator.setOnPageChangeListener(new PageChangeListener());
   }
   private class PageChangeListener implements OnPageChangeListener {
      @Override
      public void onPageScrollStateChanged(int arg0) {
         if (listener != null) {
            listener.onPageScrollStateChanged(arg0);
         }
      }

      @Override
      public void onPageScrolled(int arg0, float arg1, int arg2) {
         if (listener != null) {
            listener.onPageScrolled(arg0, arg1, arg2);
         }
      }

      @Override
      public void onPageSelected(int arg0) {
         currentItem = arg0;
         if (listener != null) {
            listener.onPageSelected(arg0);
         }
      }
   }

   public interface IPageOnPageChangeListener {
      public void onPageScrollStateChanged(int arg0);

      public void onPageScrolled(int arg0, float arg1, int arg2);

      public void onPageSelected(int arg0);
   }
   
   private class ScrollBannerTask implements Runnable {
      public void run() {
         synchronized (carouselpager) {
            currentItem = (currentItem + 1) % viewLists.size();
            currHandler.sendEmptyMessage(25);
         }
      }
   }
   private Handler currHandler = new Handler() {
      public void handleMessage(Message msg) {
         switch (msg.what) {
         case 25:
            carouselpager.setCurrentItem(currentItem);
            break;
         default:
            break;
         }
      };
   };

这里先初始化一个线程调度器,用于轮询,以切换要展示的视图。

代码中对外公开了几个方法,下面逐一讲解

startScroller ()看名字即可知道,这是开始轮询的方法,在activity或者fragment中,装载完数据,调用这个方法,视图就开始轮询了。

stopScroller() 停止视图的轮询

setAdapter() 设置适配器,给广告位设置适配器,这里我们的类型是BasePageAdapter<View>,传这个参数的目的,是为了通用,不仅仅局限于图片。



接下来我们看一下在activity或者fragment中如何去使用这个类。

public class MainActivity  extends Activity {

    @ViewInject(R.id.carouseview)
    private CarouselView carouseview;

    private ArrayList<View> viewLists = new ArrayList<View>();


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        //装载数据
        ImageView image = new ImageView(this);
        image.setImageResource(R.drawable.img1);

        ImageView image2 = new ImageView(this);
        image2.setImageResource(R.drawable.img2);

        ImageView image3 = new ImageView(this);
        image3.setImageResource(R.drawable.img3);

        viewLists.add(image);
        viewLists.add(image2);
        viewLists.add(image3);
        
        BannerAdapter adapter = new BannerAdapter();
        adapter.appendToList(viewLists);
        carouseview.setAdapter(adapter);
        carouseview.startScroller();
    }

    public class BannerAdapter extends BasePageAdapter<View> {}

这个类非常的简单,这里以图片为例,当然也可以是其他的视图,先初始化一些图片资源,然后把图片资源放到一个集合中,接着给我们的适配器装载数据,接下来给广告控件设置适配器,最后调用适配器的startScroller()方法,广告位就可以轮询了。



布局也是很简单的,我们来看一下

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/bg_dark"
    android:clipToPadding="false"
    android:fitsSystemWindows="true"
    android:orientation="vertical" >
   <com.czlong.commonview.CarouselView
                android:id="@+id/carouseview"
                android:layout_width="match_parent"
                android:layout_height="146dp" />

</LinearLayout>

这里,直接引用广告位空间即可,非常简单。

最后,还有适配器跟一个布局的代码,下面给出。

carouselview_layout

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="146dp"
    android:background="#00000000" >

    <android.support.v4.view.ViewPager
        android:id="@+id/carouselpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:focusable="true" />

    <com.viewpagerindicator.CirclePageIndicator
        android:id="@+id/indicator"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:gravity="center"
        android:padding="10dp"
        app:fillColor="#FF818F"
        app:pageColor="#EE4854"
        app:radius="3dp"
        app:strokeColor="@color/goldenrod"
        app:strokeWidth="0.1dp" />

</RelativeLayout>

BasePageAdapter,这里写得比较通用,其中可能有一些这里用不到的方法,就不逐一删除了。

public abstract class BasePageAdapter<T extends View> extends PagerAdapter
       {

   private List<T> mList = new LinkedList<T>();

   private List<String> titles;

   @Override
   public int getCount() {
      return mList == null ? 0 : mList.size();
   }

   @Override
   public Object instantiateItem(ViewGroup container, int position) {
      container.addView(mList.get(position), 0);
      return mList.get(position);
   }

   @Override
   public boolean isViewFromObject(View arg0, Object arg1) {
      return arg0 == arg1;
   }

   @Override
   public void destroyItem(ViewGroup container, int position, Object object) {
      container.removeView(mList.get(position));
   }

   /**
    * 获取数据集合
    * 
    * @return
    */
   public List<T> getList() {
      return mList;
   }

   /**
    * 追加list数据集合 默认像末端追加
    * 
    * @param list
    */
   public void appendToList(List<T> list) {
      if (list == null) {
         return;
      }
      mList.addAll(list);
      notifyDataSetChanged();
   }

   /**
    * 追加到头部
    * 
    * @param list
    */
   public void appendToTopList(List<T> list) {
      if (list == null) {
         return;
      }
      appendToList(list, 0);
      notifyDataSetChanged();
   }

   /**
    * 追加到制定位置
    * 
    * @param list
    * @param postion
    */
   public void appendToList(List<T> list, int postion) {
      if (postion < 0 || postion > list.size()) {
         throw new RuntimeException("illegal postion");
      }
      mList.addAll(postion, list);
   }

   /**
    * 清空数据源
    */
   public void clear() {
      mList.clear();
      notifyDataSetChanged();
   }

   /**
    * @return the mList
    */
   public List<T> getmList() {
      return mList;
   }

   /**
    * @param mList
    *            the mList to set
    */
   public void setmList(List<T> mList) {
      this.mList = mList;
   }

   /**
    * @return the titles
    */
   public List<String> getTitles() {
      return titles;
   }

   /**
    * @param titles
    *            the titles to set
    */
   public void setTitles(List<String> titles) {
      this.titles = titles;
   }

到这里,广告控件就写完了,只需几行代码就可以用起来了,需要的朋友可以拿去集成到项目中。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值