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

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

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

       自定义类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("https://img-my.csdn.net/uploads/201312/14/1386989803_3335.PNG"
				, "http://blog.csdn.net/u011638883/article/details/17302293"
				, "双向搜索");
		Advertising ad2 = new Advertising("https://img-my.csdn.net/uploads/201312/14/1386989613_6900.jpg"
				, "http://blog.csdn.net/u011638883/article/details/17245371"
				, "创意设计");
		Advertising ad3 = new Advertising("https://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库:http://download.csdn.net/detail/u011638883/6726339

       好了,就这样,,

       谢谢!!

      

       update(2013-12-17):补上项目中的Afinal框架代码,之前上传了5、6次都失败,,

 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值