您的位置:首页 > 移动开发 > Android开发

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

2016-03-02 16:22 716 查看


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

标签: android滑屏滑动launcher控件
2013-05-02 13:21 18811人阅读 评论(164) 收藏 举报


分类:

Android高手进阶(50)


版权声明:本文为博主原创文章,未经博主允许不得转载。

原理

参见下图。整个组件是一个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

[java] view
plain copy

/**

* 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

[java] view
plain copy

public interface ComponentCallBack

{

public static interface OnBannerClickListener

{

/**

* banner单击事件

* @param bannerMotionEvent 单击事件对象,包含所需的响应信息

* 参见 {@link BannerMotionEvent}

*/

public abstract void onBannerClick( BannerMotionEvent bannerMotionEvent );

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: