首页 > 代码库 > 开源项目:滑动广告栏
开源项目:滑动广告栏
最近在开发一款android APP,项目中采用了推送广告的方案,即在手机屏幕上方空出一块区域,加载来自服务器的广告图片,形成banner广告的效果。
开发过程中,百度出了好多种解决方案,其中以ViewPager的方案和重写Gallery的方案居多,学生党的我比较倾向于后者。在编写定制Gallery的过程中参考了ZAKER 5.0.4源代码中的ScrollGallery类(反编译得到的),优化了Gallery向两边滑动到头自动跳转的问题,详细的代码如下:
1 package org.warnier.zhang.support.v1.widget; 2 3 import java.util.Timer; 4 5 import android.content.Context; 6 import android.util.AttributeSet; 7 import android.view.MotionEvent; 8 import android.widget.Gallery; 9 10 public class AdsGallery extends Gallery {11 12 public Context context;13 14 public AdsGallery(Context context) {15 super(context);16 this.context = context;17 }18 19 public AdsGallery(Context context, AttributeSet attrs) {20 super(context, attrs);21 this.context = context;22 }23 24 public AdsGallery(Context context, AttributeSet attrs, int defStyleAttr) {25 super(context, attrs, defStyleAttr);26 this.context = context;27 }28 29 public AdsGallery(Context context, AttributeSet attrs, int defStyleAttr,30 int defStyleRes) {31 super(context, attrs, defStyleAttr, defStyleRes);32 this.context = context;33 }34 35 @Override36 public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,37 float velocityY) {38 if (isScrollingLeft(e1, e2)) {39 playPrevious();40 }41 for (;;) {42 playNext();43 return true;44 }45 }46 47 private boolean isScrollingLeft(MotionEvent paramMotionEvent1,48 MotionEvent paramMotionEvent2) {49 return paramMotionEvent2.getX() > paramMotionEvent1.getX();50 }51 52 public boolean playNext() {53 int i = getSelectedItemPosition();54 int j = computeHorizontalScrollRange();55 if ((j > 0) && (i < j - 1)) {56 onKeyDown(22, null);57 return true;58 }59 return false;60 }61 62 public boolean playPrevious() {63 int i = getSelectedItemPosition();64 if ((computeHorizontalScrollRange() > 0) && (i > 0)) {65 onKeyDown(21, null);66 return true;67 }68 return false;69 }70 }
滑动广告栏核心类有AdsGallery 和 AdsAdapter,核心类只是优化了滑动体验效果。在org.warnier.zhang.sample包的Demo中,AdsAdapter直接加载了本地的图片,在实际的APP中需要打开新的网络线程从服务器上读取图片资源。滑动广告栏具体功能的实现在org.warnier.zhang.sample包的MainActivity中。在MainActivity的onCreate()方法中初始化AdsGallery ,显示当前广告获得焦点的布局,和计时器;利用Timer和Handler之间进行线程间通信,在Handler中更新AdsGallery当前项。详细的代码如下:
1 package org.warnier.zhang.sample; 2 3 import java.util.Timer; 4 import java.util.TimerTask; 5 6 import org.warnier.zhang.support.v1.widget.AdsAdapter; 7 import org.warnier.zhang.support.v1.widget.AdsGallery; 8 9 import android.util.Log;10 import android.view.View;11 import android.widget.ImageView;12 import android.widget.LinearLayout;13 import android.app.Activity;14 import android.graphics.Color;15 import android.os.Bundle;16 import android.os.Handler;17 import android.os.Message;18 19 public class MainActivity extends Activity {20 21 private AdsGallery adsGallery;22 private LinearLayout linearLayout;23 private int delay = 2500;24 private int period = 2500;25 26 @Override27 protected void onCreate(Bundle savedInstanceState) {28 super.onCreate(savedInstanceState);29 setContentView(R.layout.activity_main);30 // 初始化广告栏控件;31 adsGallery = (AdsGallery) this.findViewById(R.id.myAdsGallery);32 adsGallery.setAdapter(new AdsAdapter(this));33 34 // 初始化广告焦点指示器;35 linearLayout = (LinearLayout) this.findViewById(R.id.myAdsIndicator);36 linearLayout.setBackgroundColor(Color.argb(200, 135, 135, 152));37 for (int i = 0; i < 4; i++) {38 ImageView imageView = new ImageView(this);39 if (i == 0) {40 imageView.setBackgroundResource(R.drawable.feature_point_cur);41 } else42 imageView.setBackgroundResource(R.drawable.feature_point);43 linearLayout.addView(imageView);44 }45 46 // 初始化计时器和计时器任务;47 new Timer().schedule(new TimerTask() {48 49 @Override50 public void run() {51 int position = adsGallery.getSelectedItemPosition() + 1;52 53 // 存放广告栏的当前项;54 Bundle bundle = new Bundle();55 bundle.putInt("position", position);56 Message msg = new Message();57 58 // 设置当前的消息标识符;59 msg.what = 1;60 msg.setData(bundle);61 handler.sendMessage(msg);62 }63 }, delay, period);64 }65 66 // 初始化Handler,供UI主线程与计时器线程交换数据;67 private Handler handler = new Handler() {68 @Override69 public void handleMessage(android.os.Message msg) {70 super.handleMessage(msg);71 switch (msg.what) {72 case 1:73 Bundle bundle = msg.getData();74 int position = bundle.getInt("position");75 Log.i("指示器", "" + position);76 adsGallery.setSelection(position);77 refreshIndicator(position);78 break;79 80 default:81 Log.i("msg.what", "消息标识符错误!");82 break;83 }84 };85 };86 87 // 刷新广告栏焦点88 public void refreshIndicator(int position) {89 LinearLayout layout = (LinearLayout) findViewById(R.id.myAdsIndicator);90 View v = layout.getChildAt(position % 4);91 View p = layout.getChildAt((position - 1) % 4);92 ((ImageView) p).setImageResource(R.drawable.feature_point);93 ((ImageView) v).setImageResource(R.drawable.feature_point_cur);94 }95 }
当然项目中还存在如下问题,欢迎读者交流指正!
(1)广告焦点指示器的第一个圆形图标出现一圈红色背景;
(2)当手动滑动广告栏的过程中,计时器继续运行,广告焦点指示器不止一个出现红色;
(3)能否定制一个能够自动运行的AdsGallery,而不是在Activity中控制运行;
上述问题已经在开发的过程中得到解决,但还是期待读者能够拿出新颖的方案,交流一下!展示和分享的代码是早期的原型Demo,不是项目的实际代码,大家如果采用的话需要根据自己的实际情况加以更改。完整的Eclipse工程下载访问链接: http://pan.baidu.com/s/1dDH7nSd 密码: ah8p。
参考文献:
[1] Android开发权威指南,李宁著,2013-09,北京,人民邮电出版社。
本文历史:
- 2015-01-30 初稿完成。
开源项目:滑动广告栏