当前位置: 移动技术网 > 移动技术>移动开发>Android > Android组件banner实现左右滑屏效果

Android组件banner实现左右滑屏效果

2019年07月24日  | 移动技术网移动技术  | 我要评论

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

1.原理
参见下图。整个组件是一个framelayout,里面有两个view,第一个是linearlayout,承载了4个(或多个)可以滑动的view,见图中绿色背景的部分;第二个是一个relativelayout,在其底部放置了一个linearlayout,在linearlayout的内部放置了若干个小圆点,用来指示当前屏幕的索引。手势检测用了gesturedetector,并实现了ongesturelistener接口。为了能控制滑动速度,采用了scroller弹性滑动对象。
为什么组件继承framelayout,是因为用于指示的小圆点是出现在view上面的,一个view叠在另一个view上面,这就是framelayout的特性

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.bannerinfohandler 
{ 
 
 private 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 = 0; 
 
 public static final int message_auto_scroll = 1; 
 
 public static final int message_fetch_banner_success = 2; 
 
 public 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 = 5000; 
 
 private 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); 
   if( mbannerbitmaps != null ) 
   { 
   mbannerbitmaps.set( i, bitmap ); 
   setbannerimages(i); 
   } 
   break; 
  } 
  } 
  
 }; 
 
 }; 
 
 public scrollbanner(context context) 
 { 
 this(context, null); 
 } 
 
 public scrollbanner(context context, attributeset attrs) 
 { 
 super(context, attrs); 
 mcontext = context; 
 } 
 
 public scrollbanner(context context, attributeset attrs, int defstyle) 
 { 
 super(context, attrs, defstyle); 
 mcontext = context; 
 } 
 
 /** 
 * 
 * @param context activity实例 
 * @param width banner的宽度 单位px 
 * @param height banner的高度 单位dip,-1表示根据图片比例自适应高度 
 * @param bannerclicklistener 单击banner的回调接口 
 */ 
 public scrollbanner(context context, final int width, final int height, onbannerclicklistener bannerclicklistener) 
 { 
 this(context, null); 
 
 int activityid = ( (baseactivity)context ).activityid(); 
 if(activityid == baseactivity.account_id)//位置3 
  mlocation = 3; 
 else if(activityid == baseactivity.gamezone_id)//位置2 
 { 
  mlocation = 2; 
 } 
  
 //初始化时不显示banner 
 this.show(false); 
 setresolution(width, height); 
 setonbannerclicklistener(bannerclicklistener); 
 setdefaultbannerimages(); 
 fetchbannerinfo(); 
 } 
 
 /** 
 * 通过xml方式加载banner,必须调用此方法才能显示 
 */ 
 public void showbanner() 
 { 
 int activityid = ( (baseactivity)mcontext ).activityid(); 
 if(activityid == baseactivity.account_id)//位置3 
  mlocation = 3; 
 else if(activityid == baseactivity.gamezone_id)//位置2 
 { 
  mlocation = 2; 
 } 
  
 setdefaultbannerimages(); 
 fetchbannerinfo(); 
 } 
 
 /** 
 * 暂停滚动 
 */ 
 public void pausescroll() 
 { 
 mtimerresume = false; 
 } 
 
 /** 
 * 恢复滚动 
 */ 
 public void resumescroll() 
 { 
 mtimerresume = true; 
 } 
 
 /** 
 * 设置回调接口 
 * @param callback 单击banner的回调接口 
 */ 
 public void setonbannerclicklistener(onbannerclicklistener bannerclicklistener) 
 { 
 mbannerclicklistener = (bannerclicklistener != null ? bannerclicklistener : scrollbanner.this); 
 } 
 
 /** 
 * 设置banner的解析度 
 * @param width banner的宽度 
 * @param height banner的高度 
 */ 
 public void setresolution(final int width, final int height) 
 { 
 int heightinpx = height; 
  
 if(height == -1) 
  heightinpx = (int)(ratio * width) ; 
 else 
 { 
  resources resources = getresources(); 
  heightinpx = math.round( typedvalue.applydimension( 
   typedvalue.complex_unit_dip, height, resources.getdisplaymetrics()) ); 
 } 
  
 mscreenwidth = width; 
 mscreenheight = heightinpx; 
 setlayoutparams(new layoutparams(width, heightinpx)); 
 
 initscrollview(); 
 } 
 
 /** 
 * 获取banner的高度 
 * @return banner的高度 单位:px 
 */ 
 public int getheightpixels() 
 { 
 return mscreenheight; 
 } 
 
 /** 
 * 设置banner是否可以弹性滑出边界 
 * @param canoverscroll true表示可以滑出边界,false不能 
 */ 
 public void setoverscrollmode(boolean canoverscroll) 
 { 
 moverscrollmode = canoverscroll; 
 if(canoverscroll == false) 
  moverscrolldistance = 0; 
 } 
 
 /** 
 * 向后台获取banner的各种信息 
 */ 
 private void fetchbannerinfo() 
 { 
 networkmanager netmanager = (networkmanager) appengine.getinstance().getmanager( 
  imanager.network_id); 
 netmanager.getbannerinfo( string.valueof(mlocation), scrollbanner.this ); 
 } 
 
 /** 
 * 获取banner的滑屏图像 
 */ 
 private void setdefaultbannerimages() 
 { 
 //为banner设置默认bitmap 
 bitmapfactory.options bitmapfactoryoptions = new bitmapfactory.options(); 
 bitmapfactoryoptions.injustdecodebounds = false; 
 bitmapfactoryoptions.insamplesize = 2; 
 
 resources res=mcontext.getresources(); 
 mdefaultbitmap = bitmapfactory.decoderesource(res, r.drawable.banner_image_default, bitmapfactoryoptions); 
  
 for(int i = 0; i < page_count; i++) 
  mbannerbitmaps.add(i, mdefaultbitmap); 
 
 //初始化banneritem对象 
 for (int i = 0; i < page_count; i++) 
  mbanneritemslist.add(i, null); 
 
 setbannerimages(-1); 
 } 
 
 private void fetchbannerimages() 
 { 
 //表示已经执行了ondetachedfromwindow,banner已经被销毁了 
 if( mbanneritemslist == null ) 
  return; 
  
 //imagemanager 根据url向其获取bitmap 
 imagemanager imagemanager = (imagemanager)appengine.getinstance(). 
  getmanager(imanager.image_id); 
 
 banneritem item = null; 
 for(int i = 0; i < page_count; i++) 
 { 
  try 
  { 
  item = mbanneritemslist.get(i); 
  } 
  catch (indexoutofboundsexception e) 
  { 
  logger.e(tag, "fetchbannerimages error: " + e); 
  } 
  catch (exception e) 
  { 
  logger.e(tag, "fetchbannerimages error: " + e); 
  } 
  //imagemanager为多线程,采用常见的三级cache策略(内存、文件、网络) 
  if( item != null && item.imgurl != null ) 
  imagemanager.loadbitmap( item.imgurl, mbitmaphandler ); 
 } 
 } 
 
 /** 
 * 设置banner的滑屏图像 
 * @param position 如果position=-1,则表示设置全部bitmap 
 */ 
 private void setbannerimages(final int position) 
 { 
 int size = mbannerbitmaps.size(); 
 if (size < page_count || mlinearlayoutscreens == null) 
 { 
  return; 
 } 
 if(position >=0 && position < page_count ) 
 { 
  drawable drawable = mlinearlayoutscreens.get(position).getbackground(); 
  mlinearlayoutscreens.get(position).setbackgrounddrawable 
  (new bitmapdrawable( mbannerbitmaps.get(position) ) ); 
  drawable.setcallback(null); 
  drawable = null; 
  
  return; 
 } 
 
 for(int i = 0; i < page_count; i++) 
 { 
  mlinearlayoutscreens.get(i).setbackgrounddrawable(new bitmapdrawable(mbannerbitmaps.get(i))); 
 } 
 } 
 
 /** 
 * 是否显示banner 
 * @param isshow true显示 false不显示 
 */ 
 public void show(boolean isshow) 
 { 
 if(isshow) 
 { 
  this.setvisibility(view.visible); 
  mtimerresume = true; 
 } 
 else 
 { 
  this.setvisibility(view.gone); 
  mtimerresume = false; 
 } 
 } 
 
 /** 
 * 切换到指定屏幕 
 * @param which 屏幕索引 
 */ 
 public void switchtoscreen(final int which) 
 { 
 mhorizontalscrollviewex.switchview(which); 
 } 
 
 /** 
 * 设置屏幕的数量 (此函数暂不开放) 
 * @param count 屏幕数量 
 */ 
 protected void setscreencount(final int count) 
 { 
 page_count = count; 
 } 
 
 /** 
 * 设置偏移的距离 如果moverscrollmode为false,则此设置无效 (此函数暂不开放) 
 * @param distance 
 */ 
 protected void setoverscrolldistance(int distance) 
 { 
 if(distance < 0) 
  distance = 0; 
 
 moverscrolldistance = moverscrollmode ? distance : 0; 
 } 
 
 /** 
 * 切换小圆点 
 * @param position current screen index 
 */ 
 private void switchscreenposition(final int position) 
 { 
 if( mpageindicator == null || mpageindicatorfocused == null ) 
  return; 
  
 int length = 0; 
 if(mimageviewlist != null) 
  length = mimageviewlist.size(); 
 if (position >= length || position < 0 || length <= 0) 
 { 
  return; 
 } 
 
 for(int i = 0; i < length; i++) 
 { 
  mimageviewlist.get(i).setimagedrawable(mpageindicator); 
 } 
  
 mimageviewlist.get(position).setimagedrawable(mpageindicatorfocused); 
 } 
 
 /** 
 * 初始化整个framelayout视图组 
 */ 
 private void initscrollview() 
 { 
 setlayoutparams(new layoutparams(mscreenwidth, mscreenheight )); 
 
 linearlayoutscrollayout = new linearlayout(mcontext); 
 linearlayoutscrollayout.setbackgroundcolor(color.white); 
 linearlayoutscrollayout.setorientation(linearlayout.horizontal); 
  
 int mversioncode = 8; 
 try 
 { 
  mversioncode = integer.valueof(android.os.build.version.sdk); 
  logger.d(tag, "sdk version=" + mversioncode); 
 } 
 catch (exception e) 
 { 
  e.printstacktrace(); 
 } 
 //针对android1.6及以下的特殊处理 此为android的低版本bug 
 if(mversioncode <= 5) 
 { 
  linearlayoutscrollayout.setbaselinealigned(false); 
 } 
  
 //初始化四个滑动view 
 for(int i = 0; i < page_count; i++) 
 { 
  linearlayout linearlayoutscreen = new linearlayout(mcontext); 
  linearlayoutscreen.setorientation(linearlayout.vertical); 
  linearlayoutscrollayout.addview(linearlayoutscreen, new layoutparams( 
   mscreenwidth, 
   layoutparams.fill_parent)); 
 
  mlinearlayoutscreens.add(i, linearlayoutscreen); 
 } 
 
 //初始化小圆点视图 
 relativelayout relativelayout = new relativelayout(mcontext); 
 relativelayout.setlayoutparams(new layoutparams( 
  layoutparams.fill_parent, layoutparams.wrap_content)); 
 
 //linearlayoutfordot为小圆点视图 
 linearlayoutfordot =new linearlayout(mcontext); 
 android.widget.relativelayout.layoutparams layoutparams = 
  new android.widget.relativelayout.layoutparams(layoutparams.wrap_content, 
   layoutparams.wrap_content); 
 //小圆点距底部的距离 单位:px 
 layoutparams.bottommargin = margin_bottom; 
 layoutparams.rightmargin = margin_bottom; 
 layoutparams.addrule(android.widget.relativelayout.align_parent_bottom); 
 layoutparams.addrule(android.widget.relativelayout.center_horizontal); 
 linearlayoutfordot.setlayoutparams(layoutparams); 
 linearlayoutfordot.setorientation(linearlayout.horizontal); 
 linearlayoutfordot.sethorizontalgravity(gravity.center); 
 linearlayoutfordot.setverticalgravity(gravity.center); 
 //下面两句实现圆角半透明效果 不采用 
 // linearlayoutfordot.setbackgroundresource(r.drawable.round_corner_bg); 
 // linearlayoutfordot.getbackground().setalpha(100); 
 
 //初始化4个小圆点 
 mpageindicator = getresources().getdrawable(r.drawable.page_indicator); 
 mpageindicatorfocused = getresources().getdrawable(r.drawable.page_indicator_focused); 
 for(int i = 0; i < page_count; i++) 
 { 
  imageview imageview = new imageview(mcontext); 
  imageview.setimagedrawable(mpageindicator); 
  mimageviewlist.add(i, imageview); 
  linearlayout.layoutparams layoutparamsfordot = 
   new linearlayout.layoutparams(layoutparams.wrap_content, 
    layoutparams.wrap_content); 
  layoutparamsfordot.rightmargin = 5; 
 
  linearlayoutfordot.addview(imageview, layoutparamsfordot); 
 } 
 mimageviewlist.get(0).setimagedrawable(mpageindicatorfocused); 
 relativelayout.addview(linearlayoutfordot); 
 
 mhorizontalscrollviewex = new horizontalscrollviewex(mcontext, null, mbannerclicklistener); 
 mhorizontalscrollviewex.setlayoutparams(new layoutparams( 
  mscreenwidth * page_count, 
  layoutparams.fill_parent)); 
 mhorizontalscrollviewex.addview(linearlayoutscrollayout, new layoutparams( 
  layoutparams.fill_parent, 
  layoutparams.fill_parent)); 
 
 mhorizontalscrollviewex.sethorizontalscrollbarenabled(false); 
 mhorizontalscrollviewex.sethorizontalfadingedgeenabled(false); 
 
 addview(mhorizontalscrollviewex); 
 addview(relativelayout); 
 
 //自动滑屏 5秒一次 
 timer.schedule(mtimertask, 5000, timer_duration); 
 } 
 
 /** 
 * 加一个banner页面 todo此函数写的不好 
 */ 
 private void addbanneritem() 
 { 
 //表示已经执行了ondetachedfromwindow,banner已经被销毁了 
 if( mbannerbitmaps == null || mlinearlayoutscreens == null || 
  mimageviewlist == null || mcontext == null ) 
  return; 
  
 //调整屏幕数量和总宽度 
 page_count += 1; 
 mhorizontalscrollviewex.getlayoutparams().width = mscreenwidth * page_count; 
   
 //加载默认图片资源 
 if(mdefaultbitmap == null) 
 { 
  bitmapfactory.options bitmapfactoryoptions = new bitmapfactory.options(); 
  bitmapfactoryoptions.injustdecodebounds = false; 
  bitmapfactoryoptions.insamplesize = 2; 
  resources res=mcontext.getresources(); 
  mdefaultbitmap = bitmapfactory.decoderesource(res, r.drawable.banner_image_default, bitmapfactoryoptions); 
 } 
 mbannerbitmaps.add(mdefaultbitmap); 
 mbanneritemslist.add(null); 
 //加一个屏幕 
 linearlayout linearlayoutscreen = new linearlayout(mcontext); 
 linearlayoutscreen.setorientation(linearlayout.vertical); 
 linearlayoutscreen.setbackgrounddrawable(new bitmapdrawable( mbannerbitmaps.get(page_count - 1) )); 
 linearlayoutscrollayout.addview(linearlayoutscreen, new layoutparams( 
  mscreenwidth, 
  layoutparams.fill_parent)); 
 mlinearlayoutscreens.add(linearlayoutscreen); 
  
 //加一个小圆点 
 imageview imageview = new imageview(mcontext); 
 imageview.setimagedrawable(mpageindicator); 
 mimageviewlist.add(imageview); 
 linearlayout.layoutparams layoutparamsfordot = 
  new linearlayout.layoutparams(layoutparams.wrap_content, 
   layoutparams.wrap_content); 
 layoutparamsfordot.rightmargin = 5; 
 linearlayoutfordot.addview(imageview, layoutparamsfordot); 
 } 
 
 private class horizontalscrollviewex extends viewgroup implements 
 ongesturelistener 
 { 
 
 private gesturedetector mgesturedetector; 
 private int mwhichscreen; 
 
 public horizontalscrollviewex(context context, attributeset attrs, onbannerclicklistener bannerclicklistener) 
 { 
  super(context, attrs); 
  
  mgesturedetector = new gesturedetector(this); 
  //解决长按屏幕后无法拖动的现象 
  mgesturedetector.setislongpressenabled(false); 
 
  //构造弹性滑动对象 
  mscroller = new scroller(context); 
 } 
 
 /** 
  * 切换到指定屏幕 
  * @param whichscreen 屏幕index 
  */ 
 public void switchview(int whichscreen) 
 { 
  if(mlinearlayoutscreens == null) 
  return; 
  
  // 防止非法参数 
  if (whichscreen < 0) 
  whichscreen = 0; 
  else if(whichscreen >= page_count) 
  whichscreen = page_count - 1; 
 
  logger.i(tag, "switch view to " + whichscreen); 
 
  int delta = whichscreen * mscreenwidth - horizontalscrollviewex.this.getscrollx(); 
 
  //缓慢滚动到指定位置 
  mscroller.startscroll(getscrollx(), 0, delta, 0, math.abs(delta) * 3); 
 
  // refresh 
  invalidate(); 
 
  //delta>0 stands for user scroll view to right 
  if (delta > 0) 
  mscrolltoright = true; 
  else 
  { 
  mscrolltoright = false; 
  } 
 
  mwhichscreen = whichscreen; 
  mwhich = whichscreen; 
  //切换小圆点 
  switchscreenposition(mwhichscreen); 
 } 
 
 /** 
  * 用户轻触触摸屏,由1个motionevent action_down触发 
  */ 
 @override 
 public boolean ondown(motionevent e) 
 { 
  logger.i("mygesture", "ondown"); 
  
  mscrollx = horizontalscrollviewex.this.getscrollx(); 
 
  return true; 
 } 
 
 /** 
  * 用户轻触触摸屏,尚未松开或拖动,由一个1个motionevent action_down触发 
  * 注意和ondown()的区别,强调的是没有松开或者拖动的状态 
  */ 
 public void onshowpress(motionevent e) 
 { 
  logger.i("mygesture", "onshowpress"); 
 } 
 
 /** 
  * 用户(轻触触摸屏后)松开,由一个1个motionevent action_up触发 
  */ 
 public boolean onsingletapup(motionevent e) 
 { 
  logger.i("mygesture", "onsingletapup"); 
  if(mbanneritemslist == null || mbanneritemslist.size() <= mwhichscreen) 
  return false; 
  
  banneritem banneritem = mbanneritemslist.get(mwhichscreen); 
 
  if(banneritem != null) 
  { 
  bannermotionevent bannermotionevent = 
   new bannermotionevent(mwhichscreen, banneritem.action, banneritem.url, 
    banneritem.gameid, banneritem.gametype, banneritem.title); 
  mbannerclicklistener.onbannerclick(bannermotionevent); 
  } 
 
  return false; 
 } 
 
 /** 用户按下触摸屏、快速移动后松开,由1个motionevent action_down, 多个action_move, 
  * 1个action_up触发 
  */ 
 public boolean onfling(motionevent e1, motionevent e2, float velocityx, 
  float velocityy) 
 { 
  logger.i("mygesture", "onfling velocityx=" + velocityx); 
 
  mwhichscreen = velocityx > 0 ? 
   mwhichscreen - 1 
   : mwhichscreen + 1; 
  switchview(mwhichscreen); 
 
  return true; 
 } 
 
 /** 
  * 用户按下触摸屏,并拖动,由1个motionevent action_down, 多个action_move触发 
  */ 
 public boolean onscroll(motionevent e1, motionevent e2, float distancex, 
  float distancey) 
 { 
  logger.i("mygesture", "onscroll"); 
 
  //禁止弹性滚动 
  if (moverscrollmode == false) 
  { 
  float x1 = e1.getx(); 
  float x2 = e2.getx(); 
  if(mwhichscreen == 0 && x1 < x2) 
   return false; 
  else if(mwhichscreen == page_count - 1 && x1 > x2) 
   return false; 
  } 
  
//  int distance = math.abs(getscrollx() - mwhichscreen * mscreenwidth); 
//  if ((mwhichscreen ==0 || mwhichscreen == page_count -1) && distance > moverscrolldistance) 
//  return false; 
  
  this.scrollby((int)distancex, 0); 
 
  return true; 
 } 
 
 /** 
  * 用户长按触摸屏,由多个motionevent action_down触发 
  */ 
 public void onlongpress(motionevent e) 
 { 
  logger.i("mygesture", "onlongpress"); 
 } 
 
 @override 
 public boolean ontouchevent(motionevent event) 
 { 
  if(event.getaction() == motionevent.action_down) 
  { 
  mtimerresume = false; 
  if ( !mscroller.isfinished() ) 
   mscroller.abortanimation(); 
  } 
  else if(event.getaction() == motionevent.action_up) 
  { 
  //开始自动滑屏 
  mtimerresume = true; 
  mbyuseraction = true; 
  } 
 
  boolean consume = mgesturedetector.ontouchevent(event); 
 
  if (consume == false && event.getaction() == motionevent.action_up) 
  { 
  int curscrollx = horizontalscrollviewex.this.getscrollx(); 
  int mwhichscreen = (curscrollx + mscreenwidth / 2) /mscreenwidth; 
 
  switchview(mwhichscreen); 
  } 
 
  return consume; 
 } 
 
 @override 
 public void computescroll() 
 { 
  if (mscroller.computescrolloffset()) 
  { 
  scrollto(mscroller.getcurrx(), mscroller.getcurry()); 
  postinvalidate(); 
  } 
 } 
 
 @override 
 protected void onlayout(boolean changed, int l, int t, int r, int b) 
 { 
  if (changed) 
  { 
  int childleft = 0; 
  final int childcount = getchildcount(); 
 
  for (int i=0; i<childcount; i++) 
  { 
   final view childview = getchildat(i); 
   if (childview.getvisibility() != view.gone) 
   { 
   final int childwidth = childview.getmeasuredwidth(); 
   childview.layout(childleft, 0, 
    childleft+childwidth, childview.getmeasuredheight()); 
   childleft += childwidth; 
   } 
  } 
  } 
 } 
 
 @override 
 protected void onmeasure(int widthmeasurespec, int heightmeasurespec) 
 { 
  super.onmeasure(widthmeasurespec, heightmeasurespec); 
 
  final int width = measurespec.getsize(widthmeasurespec); 
  final int count = getchildcount(); 
  
  for (int i = 0; i < count; i++) 
  { 
  getchildat(i).measure(widthmeasurespec, heightmeasurespec); 
  } 
  scrollto(mwhich * mscreenwidth, 0); 
 } 
 
 } 
 
 /** 
 * override此函数,防止其修改构造方法所定义的宽和高<br/> 
 * 注意:在这里,设置宽和高将不起作用 
 */ 
 @override 
 public void setlayoutparams(android.view.viewgroup.layoutparams params) 
 { 
 params.width = mscreenwidth; 
 params.height = mscreenheight; 
 
 super.setlayoutparams(params); 
 } 
 
 //标志view attachedtowindow 
 @override 
 protected void onattachedtowindow() 
 { 
 super.onattachedtowindow(); 
 mtimerresume = true; 
 } 
 
 //标志view已经脱离window,典型的情形是view被销毁了,此时取消timer 
 @override 
 protected void ondetachedfromwindow() 
 { 
 super.ondetachedfromwindow(); 
 logger.d(tag, "ondetachedfromwindow"); 
  
 mtimerresume = false; 
 int activityid = ( (baseactivity)mcontext ).activityid(); 
 //如果是账号管理页面 则释放内存 
 if(activityid == baseactivity.account_id) 
 { 
  destroy(); 
 } 
 } 
 
 /** 
 * 销毁banner 
 */ 
 public void destroy() 
 { 
 mtimertask.cancel(); 
 timer.cancel(); 
 //去除各种bitmap对activity的引用关系 
 destorybitmaps(); 
 system.gc(); 
 } 
 
 /** 
 * 去除各种bitmap对activity的引用关系 
 */ 
 private void destorybitmaps() 
 {  
 for (view view : mlinearlayoutscreens) 
 { 
  drawable drawable = view.getbackground(); 
  bitmapdrawable bitmapdrawable = null; 
  if(drawable instanceof bitmapdrawable) 
  bitmapdrawable = (bitmapdrawable)drawable; 
  
  if(bitmapdrawable != null) 
  { 
  //解除drawable对view的引用 
  bitmapdrawable.setcallback(null); 
  bitmapdrawable = null; 
  } 
 } 
  
 for (imageview imageview : mimageviewlist) 
 { 
  drawable drawable = imageview.getdrawable(); 
  if(drawable != null) 
  { 
  drawable.setcallback(null); 
  drawable = null; 
  } 
 } 
  
 mpageindicator.setcallback(null); 
 mpageindicator = null; 
 mpageindicatorfocused.setcallback(null); 
 mpageindicatorfocused = null; 
  
 mlinearlayoutscreens.clear(); 
 mlinearlayoutscreens = null; 
  
 mbannerbitmaps.clear(); 
 mbannerbitmaps = null; 
  
 mimageviewlist.clear(); 
 mimageviewlist = null; 
  
 mbanneritemslist.clear(); 
 mbanneritemslist = null; 
 } 
 
 //单击事件 
 @override 
 public void onbannerclick( bannermotionevent bannermotionevent ) 
 { 
 final int position = bannermotionevent.index; 
 if(mcontext == null) 
  return; 
  
 notificationinfo notificationinfo = new notificationinfo(); 
 notificationinfo.msgtype = bannermotionevent.getaction(); 
 int action = bannermotionevent.getaction(); 
 if(action == notificationinfo.notification_singlegame_msg) //单个游戏消息,直接启动该游戏 
 { 
  try 
  { 
  notificationinfo.gameid = integer.parseint( bannermotionevent.getgameid() ); 
  notificationinfo.gametype = integer.parseint( bannermotionevent.getgametype() ); 
  } 
  catch (numberformatexception e) 
  { 
  logger.e(tag, e.tostring()); 
  return; 
  } 
 } 
 else if(action == notificationinfo.notification_gamepage_msg) //游戏主页消息,通过客户端展示游戏主页 
 { 
  try 
  { 
  notificationinfo.gameid = integer.parseint( bannermotionevent.getgameid() ); 
  } 
  catch (numberformatexception e) 
  { 
  logger.e(tag, e.tostring()); 
  return; 
  } 
  notificationinfo.issuetitle = bannermotionevent.gettitle(); 
 } 
 else if(action == notificationinfo.notification_show_webview_msg) //交叉推广消息,通过一个webview展示 
 { 
  notificationinfo.issuetitle = bannermotionevent.gettitle(); 
  notificationinfo.openurl = bannermotionevent.getresponseurl(); 
 } 
 else //reserved 
 { 
  return; 
 } 
  
 intent intent = notificationinfo.generateintent(mcontext); 
 if(intent != null) 
  mcontext.startactivity(intent); 
 } 
 
 /** 
 * scrollbanner所关联的banner项 可以为多个 一个为一屏 
 */ 
 public static class banneritem extends object 
 { 
 public static final string action = "action"; 
 public static final string url = "url"; 
 public static final string imgurl = "imgurl"; 
 public static final string gameid = "gameid"; 
 public static final string gametype = "gametype"; 
 public static final string title = "title"; 
 
 public int index = -1; 
 public int action = -1; 
 public string url = ""; 
 public string imgurl = ""; 
 public string gameid = ""; 
 public string gametype = ""; 
 public string title = ""; 
 
 public banneritem(){} 
 } 
 
 /** 
 * bannermotionevent:单击banner所产生的事件对象<br/> 
 *getaction()来获取动作类别<br/> 
 *getresponseurl()来获取响应url<br/> 
 *... 
 */ 
 public static class bannermotionevent extends object 
 { 
 /** 
  * action_play_flash: 播放游戏 
  */ 
 public static final int action_play = 2; 
 /** 
  * action_homepage:打开官网 
  */ 
 public static final int action_homepage = 3; 
 /** 
  * action_open_url:打开指定url 
  */ 
 public static final int action_open_url = 4; 
 
 //banner中屏幕的index 
 private int index = -1; 
 //响应url 
 private string responseurl = ""; 
 //动作种类 
 private int action = -1; 
 //gameid 
 private string gameid = ""; 
 //gametype flash游戏(0) or h5游戏(1) 
 private string gametype = ""; 
 //webview的标题 
 private string title = ""; 
  
 public bannermotionevent(int index, int action, string responseurl, 
  string gameid, string gametype, string title) 
 { 
  bannermotionevent.this.index = index; 
  bannermotionevent.this.action = action; 
  bannermotionevent.this.responseurl = responseurl; 
  bannermotionevent.this.gameid = gameid; 
  bannermotionevent.this.gametype = gametype; 
  bannermotionevent.this.title = title; 
 } 
 
 /** 
  * 获取当前bannermotionevent事件对象的动作种类 
  * @return 动作种类:action_play等 
  */ 
 public int getaction() 
 { 
  return action; 
 } 
 
 /** 
  * 获取当前bannermotionevent事件对象的title 
  * @return title webview的标题 
  */ 
 public string gettitle() 
 { 
  return title; 
 } 
  
 /** 
  * 获取当前bannermotionevent事件对象的gameid 
  * @return gameid 
  */ 
 public string getgameid() 
 { 
  return gameid; 
 } 
  
 /** 
  * 获取当前bannermotionevent事件对象的gametype 
  * @return gametype 0 or 1 
  */ 
 public string getgametype() 
 { 
  return gametype; 
 } 
  
 /** 
  * 获取当前bannermotionevent事件对象的响应url 
  * @return 响应url 
  */ 
 public string getresponseurl() 
 { 
  return responseurl; 
 } 
 
 @suppresslint("defaultlocale") 
 @override 
 public string tostring() 
 { 
  return string.format("bannermotionevent { index=%d, action=%d, responseurl=%s, gameid=%s, gametype=%s, title=%s }", 
   index, action, responseurl, gameid, gametype, title); 
 } 
 } 
 
 @override 
 public void onbannerinfosuccess(list<banneritem> items) 
 { 
 logger.d(tag, "onbannerinfosuccess"); 
 mbanneritemslist = items; 
 mhandler.sendemptymessage(message_fetch_banner_success); 
 } 
 
 @override 
 public void onbannerinfofailed() 
 { 
 logger.e(tag, "onbannerinfofailed"); 
 } 
 
} 

componentcallback.java

public interface componentcallback 
{ 
 
 public static interface onbannerclicklistener 
 { 
 /** 
  * banner单击事件 
  * @param bannermotionevent 单击事件对象,包含所需的响应信息 
  * 参见 {@link bannermotionevent} 
  */ 
 public abstract void onbannerclick( bannermotionevent bannermotionevent ); 
 } 
 
} 

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网