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("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库:
好了,就这样,,
谢谢!!
>更多相关文章
首页推荐
佛山市东联科技有限公司一直秉承“一切以用户价值为依归
- 01-11全球最受赞誉公司揭晓:苹果连续九年第一
- 12-09罗伯特·莫里斯:让黑客真正变黑
- 12-09谁闯入了中国网络?揭秘美国绝密黑客小组TA
- 12-09警示:iOS6 惊现“闪退”BUG
- 05-06TCL科技:预计大尺寸面板价格上涨动能有望延
- 05-06新加坡电信Optus任命新首席执行官以重建品牌
- 05-06微软宣布为消费级用户账户提供安全密钥支持
- 05-06当好大数据产业“守门员”(筑梦现代化 共绘
- 04-29通用智能人“通通”亮相中关村论坛
相关文章
24小时热门资讯
24小时回复排行
热门推荐
最新资讯
操作系统
黑客防御