可以说广告栏是应用中必不可少的部分,有不少应用的广告栏中的图片以及点击图片后的逻辑是固定的,等待下一次升级后才会变化,这种模式不但对用户还是对应用经营者来说体验都是比较差的,当然还有大部分应用的广告栏是动态的,所谓动态,有以下几点概念:
1.图片(地址)是有服务端返回;
2.图片个数根据服务端返回的url个数决定;
3.点击图片逻辑由服务端返回;
4.支持自动切换;
动态广告栏需满足1.2.3点,第4点则属于附加条件。那么如何实现这三点呢?首先想到的便是ViewPaper,好,接下来我们先实现一个静态的,假如只有三张图片:
先看布局文件:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<FrameLayout
android:id="@+id/fl_ad"
android:layout_width="fill_parent"
android:layout_height="160dip" >
<android.support.v4.view.ViewPager
android:id="@+id/vp"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="30dip"
android:layout_gravity="bottom"
android:background="#20000000"
android:gravity="center_vertical"
android:orientation="vertical" >
<LinearLayout
android:id="@+id/ll_dots"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:layout_marginRight="10dp"
android:layout_marginTop="3dip"
android:gravity="center" >
<View
android:id="@+id/v_dot0"
style="@style/dot_style"
android:background="@drawable/ic_dot_selected" />
<View
android:id="@+id/v_dot1"
style="@style/dot_style" />
<View
android:id="@+id/v_dot2"
style="@style/dot_style" />
</LinearLayout>
</LinearLayout>
</FrameLayout>
</RelativeLayout>
布局很简单是不是,外层FrameLayout,然后指示器(白点三个)覆盖在viewpaper上部,调整好位置。
再看主代码:
public class MainActivity extends Activity {
private LayoutInflater mInflater;
private List<View> imageViews; // 滑动的图片集合
private View v_dot0,v_dot1,v_dot2;
private ViewPager vp;
private MyAdapter myAdapter;
private List<View> dots; // 图片标题正文的那些点
private int currentItem = 0; // 当前图片的索引号
private Timer adTimer = null;
// 切换当前显示的图片
@SuppressLint("HandlerLeak")
private Handler handler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
vp.setCurrentItem(currentItem);// 切换当前显示的图片
break;
}
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mInflater = LayoutInflater.from(this);
initView();
initViewPaper();
adTimer=new Timer();
adTimer.schedule(new ScrollTask(), 5*1000, 3* 1000);
}
private void initView() {
vp=(ViewPager) findViewById(R.id.vp);
//白点
v_dot0=(View) findViewById(R.id.v_dot0);
v_dot1=(View) findViewById(R.id.v_dot1);
v_dot2=(View) findViewById(R.id.v_dot2);
}
private void initViewPaper() {
imageViews = new ArrayList<View>();
//初始化图片上层切换白点
dots=new ArrayList<View>();
dots.add(v_dot0);
dots.add(v_dot1);
dots.add(v_dot2);
// 初始化图片资源
for (int i = 0; i <3; i++) {
View view = mInflater.inflate(R.layout.activity_personal_ad_img, null);
ImageView imageView = (ImageView) view.findViewById(R.id.img);
switch (i) {
case 0:
imageView.setImageResource(R.drawable.ic_launcher);//第一张图片
//设置广告点击事件
view.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
Toast.makeText(getApplicationContext(), "点击了1", Toast.LENGTH_LONG).show();
}
});
break;
case 1:
imageView.setImageResource(R.drawable.ic_launcher);//第二张图片
//设置广告点击事件
view.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
Toast.makeText(getApplicationContext(), "点击了2", Toast.LENGTH_LONG).show();
}
});
break;
case 2:
imageView.setImageResource(R.drawable.ic_launcher);//第三张图片
//设置广告点击事件
view.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
Toast.makeText(getApplicationContext(), "点击了3", Toast.LENGTH_LONG).show();
}
});
break;
}
imageViews.add(view);
}
myAdapter= new MyAdapter();
vp.setAdapter(myAdapter);// 设置填充ViewPager页面的适配器
// 设置一个监听器,当ViewPager中的页面改变时调用
vp.setOnPageChangeListener(new MyPageChangeListener());
}
/**
* 换行切换任务
*
* @author byl
*
*/
private class ScrollTask extends TimerTask {
public void run() {
if(imageViews!=null&&imageViews.size()>0){
currentItem = (currentItem + 1) % imageViews.size();
handler.sendEmptyMessage(1); // 通过Handler切换图片
}
}
}
/**
* 当ViewPager中页面的状态发生改变时调用
*
* @author byl
*
*/
private class MyPageChangeListener implements OnPageChangeListener {
private int oldPosition = 0;
public void onPageSelected(int position) {
currentItem = position;
dots.get(oldPosition).setBackgroundResource(R.drawable.ic_dot_nor);
dots.get(position).setBackgroundResource(R.drawable.ic_dot_selected);
oldPosition = position;
}
public void onPageScrollStateChanged(int arg0) {
}
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
}
/**
* 填充ViewPager页面的适配器
*
* @author byl
*
*/
private class MyAdapter extends PagerAdapter {
@Override
public int getCount() {
return imageViews.size();
}
@Override
public Object instantiateItem(View arg0, int arg1) {
((ViewPager) arg0).addView(imageViews.get(arg1));
return imageViews.get(arg1);
}
@Override
public void destroyItem(View arg0, int arg1, Object arg2) {
((ViewPager) arg0).removeView((View) arg2);
}
@Override
public boolean isViewFromObject(View arg0, Object arg1) {
return arg0 == arg1;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if(adTimer!=null){
adTimer.cancel();
adTimer=null;
}
}
initViewPaper()中将三张广告图片(动态设置后)依次添加进imageViews(List<View>)中,并将三个小白点依次添加进dots
(List<View>)中,设置Adapter,然后注册vp滑动监听vp.setOnPageChangeListener(new MyPageChangeListener());并在onPageSelected中去改变白点的状态。
自动切换则需要用到一个定时器:
adTimer=new Timer();
adTimer.schedule(new ScrollTask(), 5*1000, 3* 1000);
/**
* 换行切换任务
*
* @author byl
*
*/
private class ScrollTask extends TimerTask {
public void run() {
if(imageViews!=null&&imageViews.size()>0){
currentItem = (currentItem + 1) % imageViews.size();
handler.sendEmptyMessage(1); // 通过Handler切换图片
}
}
}
// 切换当前显示的图片
@SuppressLint("HandlerLeak")
private Handler handler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
vp.setCurrentItem(currentItem);// 切换当前显示的图片
break;
}
};
};
效果如图:
是不是很简单,我们知道了静态广告栏的实现,那么动态广告栏其实只要稍作修改即可,无非是多了几步:
1.获取服务端返回的数据;
2.根据返回的数据确定imageViews个数;
3.根据返回的数据确定每个image的点击事件;
由于广告广告栏个数一般在3-6个,再多其实也没有什么意义,所以我这里设定了最高7张广告,实现方法是先把指示器设定为7个并全部隐藏,然后根据服务端返回的图片数量来确定要显示几个指示器;
首先,将广告的属性提取为一个对象:
1.图片URL;
2.图片点击类型;(可能是网页链接,也可能是应用中的某个Activity)
3.目标链接;(即点击后要跳转的链接)
public class Adv {
private String img_url;
private String type;
private String target_url;
public String getImg_url() {
return img_url;
}
public void setImg_url(String img_url) {
this.img_url = img_url;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getTarget_url() {
return target_url;
}
public void setTarget_url(String target_url) {
this.target_url = target_url;
}
}
具体属性可根据自己业务来定,网络图片加载本人用的是afinal开源控件,首先来模拟一下服务端返回的数据:
private void initAD() {
imageResUrl=new ArrayList<Adv>();
Adv adv=new Adv();
adv.setImg_url("http://media.appshooting.com.tw/wp-content/uploads/2014/03/71eTnHBdXKL-640x312.jpg");
adv.setTarget_url("www.baidu.com");
adv.setType("1");
imageResUrl.add(adv);
adv=new Adv();
adv.setImg_url("http://s.siliconimg.com/kb/content_images/2013/03/25/125164/1364177162_901.jpg");
adv.setTarget_url("www.baidu.com");
adv.setType("1");
imageResUrl.add(adv);
adv=new Adv();
adv.setImg_url("http://www.ubergizmo.com/wp-content/uploads/2011/02/doubletwist-640x312.jpg");
adv.setTarget_url("www.baidu.com");
adv.setType("1");
imageResUrl.add(adv);
adv=new Adv();
adv.setImg_url("http://cdn.arstechnica.net/wp-content/uploads/2013/09/google-plus-services-640x312.jpg");
adv.setTarget_url("www.baidu.com");
adv.setType("2");
imageResUrl.add(adv);
}
初始化ViewPaper:
private void initViewPaper() {
//首先将白点全部隐藏,再根据获取的图片数量显示
v_dot0.setVisibility(View.GONE);
v_dot1.setVisibility(View.GONE);
v_dot2.setVisibility(View.GONE);
v_dot3.setVisibility(View.GONE);
v_dot4.setVisibility(View.GONE);
v_dot5.setVisibility(View.GONE);
v_dot6.setVisibility(View.GONE);
imageViews = new ArrayList<View>();
//初始化图片上层切换白点
dots = new ArrayList<View>();
// 初始化图片资源
for (int i = 0; i < imageResUrl.size(); i++) {
final Adv adv=imageResUrl.get(i);
View view = mInflater.inflate(R.layout.activity_personal_ad_img, null);
ImageView imageView = (ImageView) view.findViewById(R.id.img);
finalImageLoader.display(imageView,adv.getImg_url());
//设置广告点击事件
view.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
switch (Integer.parseInt(adv.getType())) {
case 1://连接类型
Intent it = new Intent(Intent.ACTION_VIEW, Uri.parse(adv.getTarget_url()));
it.setClassName("com.android.browser", "com.android.browser.BrowserActivity");
startActivity(it);
break;
case 2:
Toast.makeText(getApplicationContext(), "点击了", Toast.LENGTH_LONG).show();
break;
}
}
});
imageViews.add(view);
switch (i) {
case 0:
v_dot0.setVisibility(View.VISIBLE);
dots.add(v_dot0);
break;
case 1:
v_dot1.setVisibility(View.VISIBLE);
dots.add(v_dot1);
break;
case 2:
v_dot2.setVisibility(View.VISIBLE);
dots.add(v_dot2);
break;
case 3:
v_dot3.setVisibility(View.VISIBLE);
dots.add(v_dot3);
break;
case 4:
v_dot4.setVisibility(View.VISIBLE);
dots.add(v_dot4);
break;
case 5:
v_dot5.setVisibility(View.VISIBLE);
dots.add(v_dot5);
break;
case 6:
v_dot6.setVisibility(View.VISIBLE);
dots.add(v_dot6);
break;
}
}
if( imageResUrl.size()<=1){
v_dot0.setVisibility(View.GONE);
}else{
for(int i=0;i<dots.size();i++){
if(i==0){
dots.get(i).setBackgroundResource(R.drawable.ic_dot_selected);
}else{
dots.get(i).setBackgroundResource(R.drawable.ic_dot_nor);
}
}
}
myAdapter= new MyAdapter();
vp.setAdapter(myAdapter);// 设置填充ViewPager页面的适配器
// 设置一个监听器,当ViewPager中的页面改变时调用
vp.setOnPageChangeListener(new MyPageChangeListener());
}
在使用的过程中发现,从其他界面切换回本界面时,时不时的会出现广告栏白屏的现象,因此不能像静态广告栏那样,一直让广告图片自动切换,所以本人在onResume方法中启动自动切换,而在onPause方法中停止:
@Override
protected void onResume() {
super.onResume();
currentItem=0;
initViewPaper();
adTimer=new Timer();
adTimer.schedule(new ScrollTask(), 5*1000, 3* 1000);
}
@Override
protected void onPause() {
super.onPause();
if(adTimer!=null){
adTimer.cancel();
adTimer=null;
}
}
效果如图:
如果再加上一些动画效果就跟好了:
是不是感觉棒棒哒!