Android循环广告位的实现

时间:2022-07-01 03:19:45

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;
}

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