Android无限循环轮转广告页组件实现

浏览:
字体:
发布时间:2013-12-17 09:37:33
来源:

新项目一个,不过又是首页广告栏组件,第三次写这个组件了。虽然也可以拷贝以前的代码整理一下完成任务,但还是打算封装一下,重构一下代码,也算是自己近段时间学习的一个检验吧。不错不错~~

先上效果图(其中第三幅图是单击后的跳转页面,也是本人的博客,做下广告哈!大笑):

///

自定义类AdGallery,继承自Gallery:

package com.wly.android.widget;import java.util.Timer;import java.util.TimerTask;import com.wly.android.widget.AdGalleryHelper.OnGallerySwitchListener;import net.tsz.afinal.FinalBitmap;import android.content.Context;import android.content.Intent;import android.os.Handler;import android.os.Message;import android.util.AttributeSet;import android.view.KeyEvent;import android.view.LayoutInflater;import android.view.MotionEvent;import android.view.View;import android.view.View.OnTouchListener;import android.view.ViewGroup;import android.widget.AdapterView;import android.widget.BaseAdapter;import android.widget.Gallery;import android.widget.ImageView;/** * 无限滚动广告栏组件 持有自身容器布局引用,可以操作滚动指示器RadioGroup和标题TextView *  * @author wly * @date 2013-12-13 */public class AdGallery extends Gallery implements		android.widget.AdapterView.OnItemClickListener,		android.widget.AdapterView.OnItemSelectedListener, OnTouchListener {	private Context mContext;	private int mSwitchTime; // 图片切换时间	private boolean runflag = false;	private Timer mTimer; // 自动滚动的定时器	private OnGallerySwitchListener mGallerySwitchListener;	private Advertising[] mAds;	private Handler handler = new Handler() {		@Override		public void handleMessage(Message msg) {			super.handleMessage(msg);			int position = getSelectedItemPosition();			if (position >= (getCount() - 1)) {				setSelection(getCount() / 2, true); // 跳转到第二张图片,在向左滑动一张就到了第一张图片				onKeyDown(KeyEvent.KEYCODE_DPAD_LEFT, null);			} else {				onKeyDown(KeyEvent.KEYCODE_DPAD_RIGHT, null);			}		}	};	public AdGallery(Context context, AttributeSet attrs, int defStyle) {		super(context, attrs, defStyle);		this.mContext = context;		mTimer = new Timer();	}	public AdGallery(Context context) {		super(context);		this.mContext = context;		mTimer = new Timer();	}	public AdGallery(Context context, AttributeSet attrs) {		super(context, attrs);		this.mContext = context;		mTimer = new Timer();	}	class ViewHolder {		ImageView imageview;	}	/**	 * 初始化配置参数	 * 	 * @param ads	 *            图片数据数组	 * @param switchTime	 *            图片切换间隔	 * @param l_margin_p	 *            图片到距离屏幕左边界距离占屏幕的"比例"	 * @param t_margin_p	 *            图片到距离屏幕上边界距离占屏幕的"比例"	 * @param w_percent	 *            图片占屏幕的宽度"比例"	 * @param h_percent	 *            图片占屏幕的高度"比例"	 */	public void init(Advertising[] ads, int switchTime,			OnGallerySwitchListener gallerySwitchListener) {		this.mSwitchTime = switchTime;		this.mGallerySwitchListener = gallerySwitchListener;		this.mAds = ads;		setAdapter(new AdAdapter());		this.setOnItemClickListener(this);		this.setOnTouchListener(this);		this.setOnItemSelectedListener(this);		this.setSoundEffectsEnabled(false);		// setSpacing(10); //不能包含spacing,否则会导致onKeyDown()失效!!!		setSelection(getCount() / 2); // 默认选中中间位置为起始位置		setFocusableInTouchMode(true);	}	class AdAdapter extends BaseAdapter {		@Override		public int getCount() {			return mAds.length * (Integer.MAX_VALUE / mAds.length);		}		@Override		public Object getItem(int position) {			return null;		}		@Override		public long getItemId(int position) {			return position;		}		@Override		public View getView(int position, View convertView, ViewGroup parent) {			ViewHolder viewHolder;			if (convertView == null) {				convertView = LayoutInflater.from(mContext).inflate(						R.layout.adgallery_image, null);				Gallery.LayoutParams params = new Gallery.LayoutParams(						Gallery.LayoutParams.FILL_PARENT,						Gallery.LayoutParams.WRAP_CONTENT);				convertView.setLayoutParams(params);				viewHolder = new ViewHolder();				viewHolder.imageview = (ImageView) convertView						.findViewById(R.id.gallery_image);				convertView.setTag(viewHolder);			} else {				viewHolder = (ViewHolder) convertView.getTag();			}			FinalBitmap.create(mContext).display(viewHolder.imageview,					mAds[position % mAds.length].getPicURL(),					viewHolder.imageview.getWidth(),					viewHolder.imageview.getHeight(), null, null);			return convertView;		}	}	public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,			float velocityY) {		int kEvent;		if (isScrollingLeft(e1, e2)) { // 检查是否往左滑动			kEvent = KeyEvent.KEYCODE_DPAD_LEFT;		} else { // 检查是否往右滑动			kEvent = KeyEvent.KEYCODE_DPAD_RIGHT;		}		onKeyDown(kEvent, null);		return true;	}	private boolean isScrollingLeft(MotionEvent e1, MotionEvent e2) {		return e2.getX() > (e1.getX() + 50);	}	@Override	public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,			float distanceY) {		return super.onScroll(e1, e2, distanceX, distanceY);	}	/**	 * 开始自动滚动	 */	public void startAutoScroll() {		mTimer.schedule(new TimerTask() {			public void run() {				if (runflag) {					Message msg = new Message();					if (getSelectedItemPosition() < (getCount() - 1)) {						msg.what = getSelectedItemPosition() + 1;					} else {						msg.what = 0;					}					handler.sendMessage(msg);				}			}		}, mSwitchTime, mSwitchTime);	}	public void setRunFlag(boolean flag) {		runflag = flag;	}	public boolean isAutoScrolling() {		if (mTimer == null) {			return false;		} else {			return true;		}	}	@Override	public boolean onTouch(View v, MotionEvent event) {		if (MotionEvent.ACTION_UP == event.getAction()				|| MotionEvent.ACTION_CANCEL == event.getAction()) {			// 重置自动滚动任务			setRunFlag(true);		} else {			// 停止自动滚动任务			setRunFlag(false);		}		return false;	}	@Override	public void onItemSelected(AdapterView arg0, View arg1, int position,			long arg3) {		mGallerySwitchListener.onGallerySwitch(position % (mAds.length));	}	@Override	public void onNothingSelected(AdapterView arg0) {	}	@Override	public void onItemClick(AdapterView arg0, View arg1, int position,			long arg3) {		Intent i = new Intent();		i.setClass(mContext, MyWebViewActivity.class);		i.putExtra("url", mAds[position % mAds.length].getLinkURL());		mContext.startActivity(i);	}}

以上代码核心就是用一个定时器Timer不断的发送Message个一个Handler,在Handler的handleMessage()方法中手动的切换Gallery组件,有两点需要注意:
1、gallery不能包含spacing属性,即使将该属性设置为0dp也不行,否则会导致onKeyDown()事件失效。另外不要使用setSelection(),因为使用setSelection()只是实现的切换,但没有动画效果。

2、广告栏下方标题必须指定最大长度为一个固定值,否则会在自动切换时发生抖动,这是笔者遇到的一个问题。

再对其进行一个简单的封装(添加一个标题TextView和RadioGroup),新建类AdGalleryHelper:

package com.wly.android.widget;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.view.LayoutInflater;import android.widget.RadioButton;import android.widget.RadioGroup;import android.widget.RelativeLayout;import android.widget.TextView;import android.widget.RelativeLayout.LayoutParams;/** * 对自定义组件AdGallery进行了一次封装 * 包含对图片标题和当前位置指示器(RadioGroup)的操作 * @author wly * */public class AdGalleryHelper {	private AdGallery mAdGallery; //无限滚动Gallery	private TextView mPicTitle; //广告图片标题	private RadioGroup mRadioGroup; //滚动标记组件		private Context mContext;	private LayoutInflater mInflater;		RelativeLayout galleryLayout;		public AdGalleryHelper(Context context,final Advertising[] ads,int switchTime) {				this.mContext = context;		mInflater = LayoutInflater.from(context);		galleryLayout = (RelativeLayout)mInflater.inflate(R.layout.adgallery_hellper, null);		mRadioGroup = (RadioGroup)galleryLayout.findViewById(R.id.home_pop_gallery_mark);				//添加RadioButton		Bitmap b = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.point_1);		LayoutParams params = new LayoutParams(				Util.dpToPx(mContext, b.getWidth()), 				Util.dpToPx(mContext, b.getHeight()));		for (int i = 0; i < ads.length; i++) {			RadioButton _rb = new RadioButton(mContext);			_rb.setId(0x1234 + i);			_rb.setButtonDrawable(mContext.getResources().getDrawable(					R.drawable.gallery_selector));			mRadioGroup.addView(_rb, params);		}						mPicTitle = (TextView)galleryLayout.findViewById(R.id.news_gallery_text);		mAdGallery = (AdGallery)galleryLayout.findViewById(R.id.gallerypop);		mAdGallery.init(ads, switchTime,new OnGallerySwitchListener() {						@Override			public void onGallerySwitch(int position) {				if (mRadioGroup != null) {					mRadioGroup.check(mRadioGroup.getChildAt(							position).getId());				}				if(mPicTitle != null) {					mPicTitle.setText(ads[position].getTitle());				}			}		});			}		/**	 * 向外开放布局对象,使得可以将布局对象添加到外部的布局中去	 * @return	 */	public RelativeLayout getLayout() {		return galleryLayout;	}		/**	 * 开始自动循环切换	 */	public void startAutoSwitch() {		mAdGallery.setRunFlag(true);		mAdGallery.startAutoScroll();	}	public void stopAutoSwitch() {		mAdGallery.setRunFlag(true);	}		/**	 * 图片切换回调接口	 * @author wly	 *	 */	interface OnGallerySwitchListener {		public void onGallerySwitch(int position);	}}

实体类Advertising:

package com.wly.android.widget;/** * 广告实体类 * @author wly * */public class Advertising {	private String picURL; //图片地址	private String linkURL; //单击跳转地址	private String title; //标题		public Advertising(String picURL, String linkURL, String title) {		super();		this.picURL = picURL;		this.linkURL = linkURL;		this.title = title;	}		public String getPicURL() {		return picURL;	}	public void setPicURL(String picURL) {		this.picURL = picURL;	}	public String getLinkURL() {		return linkURL;	}	public void setLinkURL(String linkURL) {		this.linkURL = linkURL;	}	public String getTitle() {		return title;	}	public void setTitle(String title) {		this.title = title;	}}

Activity界面类MainActivity:

package com.wly.android.widget;import java.io.File;import net.tsz.afinal.FinalBitmap;import android.os.Bundle;import android.os.Environment;import android.app.Activity;import android.content.Context;import android.util.AttributeSet;import android.view.LayoutInflater;import android.view.Menu;import android.view.Window;import android.view.WindowManager;import android.widget.RelativeLayout;import android.widget.RelativeLayout.LayoutParams;public class MainActivity extends Activity {	RelativeLayout galleryContainer; //滚动广告组件的容器	LayoutInflater inflater;	AdGalleryHelper mGalleryHelper;		@Override	protected void onCreate(Bundle savedInstanceState) {		super.onCreate(savedInstanceState);		getWindow().requestFeature(Window.FEATURE_NO_TITLE);		setContentView(R.layout.activity_main);		//============初始化缓存路径,以及AfinalBitmap的初始化,可以忽略		String cacheDir;		if (android.os.Environment.getExternalStorageState().equals(				android.os.Environment.MEDIA_MOUNTED)) {			File f = this.getApplicationContext().getExternalCacheDir();			if (null == f) {				cacheDir = Environment.getExternalStorageDirectory().getPath()						+ File.separator + this.getApplicationContext().getPackageName()						+ File.separator + "cache";			} else {				cacheDir = f.getPath();			}		} else {			File f = this.getApplicationContext().getCacheDir();			cacheDir = f.getPath();		}		FinalBitmap.create(this, cacheDir + File.separator				+ "images" + File.separator,				0.3f, 1024 * 1024 * 10,				 10);		//==================				//构造测试数据		Advertising ad1 = new Advertising("http://img.my.csdn.net/uploads/201312/14/1386989803_3335.PNG"				, "http://blog.csdn.net/u011638883/article/details/17302293"				, "双向搜索");		Advertising ad2 = new Advertising("http://img.my.csdn.net/uploads/201312/14/1386989613_6900.jpg"				, "http://blog.csdn.net/u011638883/article/details/17245371"				, "创意设计");		Advertising ad3 = new Advertising("http://img.my.csdn.net/uploads/201312/14/1386989802_7236.PNG"				, "http://blog.csdn.net/u011638883/article/details/17248135"				, "Artificial Intelligence");		Advertising[] ads = {ad1,ad2,ad3};				//将AdGalleryHelper添加到布局文件中		galleryContainer = (RelativeLayout) this				.findViewById(R.id.home_gallery);		mGalleryHelper = new AdGalleryHelper(this, ads, 5000);		galleryContainer.addView(mGalleryHelper.getLayout());				//开始自动切换			mGalleryHelper.startAutoSwitch(); 	}	@Override	protected void onDestroy() {		super.onDestroy();		mGalleryHelper.stopAutoSwitch();	}}

注意,代码中异步加载图片使用的Afinal框架的FinalBitmap。读者可以根据自己项目加以替换。

代码工程:http://download.csdn.net/detail/u011638883/6713923

用到的Afinal库:

好了,就这样,,

谢谢!!

>更多相关文章
24小时热门资讯
24小时回复排行
资讯 | QQ | 安全 | 编程 | 数据库 | 系统 | 网络 | 考试 | 站长 | 关于东联 | 安全雇佣 | 搞笑视频大全 | 微信学院 | 视频课程 |
关于我们 | 联系我们 | 广告服务 | 免责申明 | 作品发布 | 网站地图 | 官方微博 | 技术培训
Copyright © 2007 - 2024 Vm888.Com. All Rights Reserved
粤公网安备 44060402001498号 粤ICP备19097316号 请遵循相关法律法规
');})();