首页 > 系统 > Android > 正文

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

2019-12-12 05:04:48
字体:
来源:转载
供稿:网友

什么是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 );  }  } 

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

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表