android中左右滑屏的实现(广告位banner组件)

               
  1. 原理

参见下图。整个组件是一个FrameLayout,里面有两个view,第一个是LinearLayout,承载了4个(或多个)可以滑动的view,见图中绿色背景的部分;第二个是一个RelativeLayout,在其底部放置了一个LinearLayout,在LinearLayout的内部放置了若干个小圆点,用来指示当前屏幕的索引。手势检测用了GestureDetector,并实现了OnGestureListener接口。为了能控制滑动速度,采用了Scroller弹性滑动对象。

为什么组件继承FrameLayout,是因为用于指示的小圆点是出现在view上面的,一个view叠在另一个view上面,这就是FrameLayout的特性

什么是banner组件?在许多android应用上,比如爱奇艺客户端、百度美拍、应用宝等上面,都有一个可以手动滑动的小广告条,这就是banner,实际应用中的banner,其信息(图片和点击行为)是后台可配置的,是需要通过网络从后台拉取的。网上有许多手动滑屏的例子,但是一般只是个demo,无法在实际中使用,因为其一般没有考虑如下几类问题:图片缓存、OOM问题、是否可灵活配置、是否预留外部接口以及是否封装良好。没有良好的封装,手动滑屏加在代码中,会使得代码变得很烂很脆弱。

 

        2.     功能、效果

  • banner属性可动态设置,默认数量为4,可以调整默认的数量
  • banner信息从后台获取,banner的条数就是屏幕的数量
  • 可自动滑动也能手动滑动
  • 图片下载为多线程,并采用常见的三级cache策略(内存、文件、网络),节省流量,并处理了OOM异常
  • 内部处理点击事件,同时预留出了接口函数
  • banner封装成一个ViewGroup类,使用起来简单,最少只需要两行代码

 

        3.    代码

 

代码注释写的比较详细,应该很好理解。分为2个文件,一个是banner的类,另一个是接口声明。

ScrollBanner.java

/** * ScrollBanner 支持滑屏效果的FrameLayout子类,可设置屏幕数量,尺寸。<br/> * 典型的用法:<br/> *   ScrollBanner scrollBanner = new ScrollBanner(this, mScreenWidth, 100, this);<br/> *  linearLayout.addView(scrollBanner);<br/> *注意事项:<br/> *1.如果重新设置ScrollBanner的LayoutParams,则参数中的宽和高属性将被忽略,仍然采用对象实例化的宽和高<br/> *2.点击事件的回调如果设为null,则采用默认的事件回调<br/> *3.通过setOverScrollMode来设置 banner是否能够滑出屏幕的边界<br/> *4通过xml方式加载banner,需要进行如下调用:<br/> *  setResolution(width, height);<br/>  setOnBannerClickListener(bannerClickListener);<br/>  showBanner()<br/> * @author singwhatiwanna * @version 2013.3.4 * */public class ScrollBanner extends FrameLayout implements ComponentCallBack.OnBannerClickListener, ResponseHandler.BannerInfoHandlerprivate static final String TAG = "ScrollBanner"private HorizontalScrollViewEx mHorizontalScrollViewEx;  //ScrollBanner的子view private LinearLayout linearLayoutScrolLayout;  //linearLayoutScrolLayout的子view,用于放置若干个小圆点 private LinearLayout linearLayoutForDot;  private Scroller mScroller;  private Context mContext; private OnBannerClickListener mBannerClickListener; //屏幕及其bitmap private List<View> mLinearLayoutScreens = new ArrayList<View>(); private List<Bitmap> mBannerBitmaps = new ArrayList<Bitmap>(); //banner信息 private List<BannerItem> mBannerItemsList = new ArrayList<BannerItem>(); //小圆点 private List<ImageView> mImageViewList = new ArrayList<ImageView>(); private Drawable mPageIndicator; private Drawable mPageIndicatorFocused;  //banner默认图片 private Bitmap mDefaultBitmap; private int mScreenWidth; private int mScreenHeight; private int mScrollX; //current screen index private int mWhich = 0public static final int MESSAGE_AUTO_SCROLL = 1public static final int MESSAGE_FETCH_BANNER_SUCCESS = 2public static final int MARGIN_BOTTOM = 2;  //480*150 banner的图片尺寸 150.0/480=0.3125f public static final float ratio = 0.3125f//banner的位置 private int mLocation = -1//banner分为几屏 private int PAGE_COUNT = 4//滑动方向 是否向右滑动 private boolean mScrollToRight = true//是否自动滑屏 private boolean mTimerResume = true//标志用户是否手动滑动了屏幕 private boolean mByUserAction = false//标志banner是否可以滑出边界 private boolean mOverScrollMode = false//标志banner可以滑出边界多少像素 private int mOverScrollDistance = 0//定时器 用于banner的自动播放 final Timer timer = new Timer(); //定时器的时间间隔 单位:ms public static final int TIMER_DURATION = 5000private TimerTask mTimerTask = new TimerTask() {  @Override  public void run()   {   if (mTimerResume && !mByUserAction)    {    mHandler.sendEmptyMessage(MESSAGE_AUTO_SCROLL);   }   mByUserAction = false;  } }; //ScrollBanner私有handler 用于处理内部逻辑 private Handler mHandler = new Handler() {  public void handleMessage(Message msg)  {   //表示已经执行了onDetachedFromWindow,banner已经被销毁了   if( mBannerBitmaps == null || mLinearLayoutScreens == null ||      mImageViewList == null || mBannerItemsList == null || mContext == null )    return;      switch (msg.what)   {   case MESSAGE_AUTO_SCROLL:    if (mWhich == PAGE_COUNT - 1)     mScrollToRight = false;    else if(mWhich == 0)    {     mScrollToRight = true;    }    if (mScrollToRight)      mWhich++;    else     {     mWhich--;    }    mHorizontalScrollViewEx.switchView(mWhich);    break;   case MESSAGE_FETCH_BANNER_SUCCESS:    int more = 0;    if(mBannerItemsList != null)     more = mBannerItemsList.size() - PAGE_COUNT;    if(mBannerItemsList.size() > 0)    {     //如果有banner 显示它     ScrollBanner.this.show(true);    }    //如果后台返回的banneritem的数量大于预设值4    if(more > 0)    {     for (int i = 0; i < more; i++)      addBannerItem();    }    fetchBannerImages();    break;   default:    break;   }  }; }; //用于获取bitmap private Handler  mBitmapHandler = new Handler() {  public void handleMessage(Message msg)  {   //表示已经执行了onDetachedFromWindow,banner已经被销毁了   if( mBannerBitmaps == null || mLinearLayoutScreens == null ||      mImageViewList == null || mBannerItemsList == null || mContext == null )    return;      Bitmap bitmap = (Bitmap)msg.obj;   String urlString = msg.getData().getString("url");   Logger.d(TAG, "url=" + urlString);   if (urlString == null || bitmap == null || mBannerItemsList == null)   {    Logger.w(TAG, "bitmap=null imgurl=" + urlString);    return;   }   for( int i = 0; i < mBannerItemsList.size(); i++ )   {    BannerItem item = mBannerItemsList.get(i);    if(item != null && urlString.equals(item.imgUrl) )    {     Logger.d(TAG, "find " + i + urlString);     
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值