标签:
该banner功能有自动切换图片,点击图片可以自定义事件,手动滑动切换,异步加载图片
代码说话:
布局文件:
<!-- 广告位 --> <FrameLayout android:id="@+id/new_recommend" android:layout_width="fill_parent" android:layout_height="wrap_content" > <com.cyou.cmall.ui.HorizontalViewPager android:id="@+id/viewpager" android:layout_width="fill_parent" android:layout_height="fill_parent" /> <LinearLayout android:id="@+id/ll_indicator" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom" android:orientation="horizontal" android:paddingBottom="8dp" android:paddingLeft="26dip" /> </FrameLayout>
布局文件中我自定义了一个HorizontalViewPager,它是在viewpager的基础上做了一些修改,之所以这样做是因为,项目中使用到了下拉刷新控件,该布局最外层还有一个scrollview,会导致scrollview将手势事件拦截,而viewpager得不到滑动手势
下面是HorizontalViewPager的代码,如果不需要处理滑动手势,完全可以使用系统的viewpager控件
/** * 复写该控件是因为在PullToRefreshScrollView中,viewpager无法水平滑动 * * @author wangwei_cs */ public class HorizontalViewPager extends ViewPager { private GestureDetector mGestureDetector; public HorizontalViewPager(Context context, AttributeSet attrs) { super(context, attrs); init(context); } public HorizontalViewPager(Context context) { super(context); init(context); } private void init(Context context) { mGestureDetector = new GestureDetector(context, new YScrollDetector()); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { boolean dispatchTouchEvent = super.dispatchTouchEvent(ev); if (dispatchTouchEvent) { if (mGestureDetector.onTouchEvent(ev)) { //请求父类放弃事件的处理 requestDisallowInterceptTouchEvent(true); } } return dispatchTouchEvent; } class YScrollDetector extends SimpleOnGestureListener { @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { // 如果我们滚动更接近水平方向,返回true,自己处理,否则,让出处理权限 return (Math.abs(distanceX) > Math.abs(distanceY)); } } } </span>
言归正传:在程序oncreate方法中调用一下方法
/** * 初始化推荐广告专区 */ private void initRecommendAd() { HorizontalViewPager mViewPager = (HorizontalViewPager) findViewById(R.id.viewpager); mIndicatorLayout = (LinearLayout) findViewById(R.id.ll_indicator); FrameLayout.LayoutParams params = new FrameLayout.LayoutParams( android.widget.FrameLayout.LayoutParams.MATCH_PARENT, height * 24 / 100); mViewPager.setLayoutParams(params); AdImagePagerAdapter mPagerAdapter = new AdImagePagerAdapter(mCxt, imageUrls, new ViewPagerItemClickListener() { @Override public void OnViewPagerItemClick(int position) { if (imageUrls.size() > 0) { if (imageUrls.size() == 1) { boolean enable = urlEnable(imageUrls.get(0)); if (enable) { handleClickEvent(position); } } else { handleClickEvent(position); } } } }); List<String> lastAdUrls = getLastAdUrls(); if (lastAdUrls == null || lastAdUrls.size() == 0) { // 没有记录上一次广告url信息,添加一个无效url路径 imageUrls.add(Constants.INVALID_URL); LogHelper.e(TAG, "no last ad record"); } else { LogHelper.e(TAG, "show last ad record"); imageUrls.addAll(lastAdUrls); } mAdComponent = new RecommendAdComponent(mCxt, mViewPager, mPagerAdapter, imageUrls, 5000, mIndicatorLayout); mAdComponent.startUpAdComponent(); mPagerAdapter.notifyDataSetChanged(); }
下面是AdImagePagerAdapter的源码
import java.util.List; import android.content.Context; import android.graphics.Bitmap; import android.support.v4.view.PagerAdapter; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.Toast; import com.nostra13.universalimageloader.core.DisplayImageOptions; import com.nostra13.universalimageloader.core.ImageLoader; import com.nostra13.universalimageloader.core.assist.FailReason; import com.nostra13.universalimageloader.core.assist.ImageScaleType; import com.nostra13.universalimageloader.core.assist.SimpleImageLoadingListener; import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer; /** * 无限循环adapter * * @author wangwei_cs */ public class AdImagePagerAdapter extends PagerAdapter { protected static final String TAG = "AdImagePagerAdapter"; private List<String> imageUrls; private LayoutInflater inflater; private Context mCxt; private ViewPagerItemClickListener mListener; protected ImageLoader imageLoader; private DisplayImageOptions options; public AdImagePagerAdapter(Context context, List<String> imageUrls, ViewPagerItemClickListener listener) { this.imageUrls = imageUrls; this.mCxt = context; inflater = LayoutInflater.from(context); this.mListener = listener; imageLoader = ImageLoader.getInstance(); options = new DisplayImageOptions.Builder() .showImageForEmptyUri(R.drawable.ad_default) .showImageOnFail(R.drawable.ad_default) .showImageOnLoading(R.drawable.ad_default) .resetViewBeforeLoading(true) .cacheOnDisc(true) .imageScaleType(ImageScaleType.EXACTLY) .bitmapConfig(Bitmap.Config.RGB_565) .considerExifParams(true) .displayer(new FadeInBitmapDisplayer(300)) .build(); } @Override public int getCount() { if (imageUrls.size() < 2) { return imageUrls.size(); } return Integer.MAX_VALUE; } @Override public boolean isViewFromObject(View arg0, Object arg1) { return arg0 == arg1; } @Override public Object instantiateItem(ViewGroup container, int position) { final int index = position % imageUrls.size(); View view = inflater.inflate(R.layout.item_pager_image, container, false); assert view != null; ImageView imageView = (ImageView) view.findViewById(R.id.image); final ProgressBar spinner = (ProgressBar) view.findViewById(R.id.img_loading); imageLoader.displayImage(imageUrls.get(index), imageView, options, new SimpleImageLoadingListener() { @Override public void onLoadingStarted(String imageUri, View view) { spinner.setVisibility(View.VISIBLE); } @Override public void onLoadingFailed(String imageUri, View view, FailReason failReason) { String message = null; switch (failReason.getType()) { case IO_ERROR: message = "Input/Output error"; break; case DECODING_ERROR: message = "Image can‘t be decoded"; break; case NETWORK_DENIED: message = "Downloads are denied"; break; case OUT_OF_MEMORY: message = "Out Of Memory error"; break; case UNKNOWN: message = "Unknown error"; break; } LogHelper.e(TAG, message); spinner.setVisibility(View.GONE); } @Override public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) { spinner.setVisibility(View.GONE); } }); view.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (mListener !=null) { mListener.OnViewPagerItemClick(index); } } }); container.addView(view); return view; } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView((View) object); } }
下面是重点的RecommendAdComponent自定义的广告推荐组件
import android.annotation.SuppressLint; import android.content.Context; import android.os.Handler; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager.OnPageChangeListener; import android.support.v4.view.ViewPager.PageTransformer; import android.view.View; import android.view.ViewGroup.LayoutParams; import android.view.animation.AnimationUtils; import android.widget.ImageView; import android.widget.LinearLayout; import java.util.List; import java.util.Timer; import java.util.TimerTask; /** * 展示广告轮转的组件 * * @author wangwei_cs */ public class RecommendAdComponent { /** * 无效的图片切换时间,如果为0 表示不自动切换 */ public static final int SWITCH_TIME_INVALID = 0; private Context mCxt; // 图片url集合 private List<String> mImgUrls; // 图片切换时间 private int mSwitchTime; //自动滚动的定时器 private Timer mTimer; // 显示圆点指示器的布局 private LinearLayout mIndicatorLayout; private ViewPager mViewPager; private PagerAdapter mPagerAdapter; private int currentIndex; // 当前页面,在0和getSize()直接 private int pagerCurrent;//在viewpager中,的当前页面,取值在0和Integer.MAX_VALUE之间 private boolean timeRunning; /** * @param context * @param viewpager viewPager组件 * @param pagerAdapter * @param adUrls 装有图片url的集合 * @param switchTime 图片切换时间(ms) {@link RecommendAdComponent#SWITCH_TIME_INVALID}:不自动切换 * @param indicatorLayout 显示圆点指示器的布局 */ public RecommendAdComponent(Context context, ViewPager viewpager, PagerAdapter pagerAdapter, List<String> adUrls, int switchTime, LinearLayout indicatorLayout) { this.mCxt = context; this.mViewPager = viewpager; this.mPagerAdapter = pagerAdapter; this.mImgUrls = adUrls; this.mSwitchTime = switchTime; this.mIndicatorLayout = indicatorLayout; initIndicatorLayout(); mViewPager.setOnPageChangeListener(new MyOnPageChangeListener()); // setViewpagerAnimator(); } /** * 初始化指示器 */ private void initIndicatorLayout() { ImageView iv = null; if (mIndicatorLayout != null && getSize() < 2) { // 如果只有一第图时不显示圆点容器 mIndicatorLayout.setVisibility(View.INVISIBLE); } else if (mIndicatorLayout != null) { mIndicatorLayout.setVisibility(View.VISIBLE); for (int i = 0; i < getSize(); i++) { iv = new ImageView(mCxt); iv.setTag(i); int padding = mCxt.getResources().getDimensionPixelSize(R.dimen.indicator_padding); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); params.setMargins(padding, 0, padding, 0); mIndicatorLayout.addView(iv, params); } } } private void resetIndicatorLayout() { mIndicatorLayout.removeAllViews(); initIndicatorLayout(); } /** * 给viewPager设置动画 */ private void setViewpagerAnimator(){ if (mViewPager !=null) { PageTransformer pageTransformer=new PageTransformer() { @Override public void transformPage(View view, float arg1) { // view.setAnimation(AnimationUtils.loadAnimation(mCxt, android.R.anim.slide_out_right)); view.setAnimation(AnimationUtils.loadAnimation(mCxt, R.anim.right_in)); } }; mViewPager.setPageTransformer(true, pageTransformer); } } /** * 获取图片集合的size * * @return */ private int getSize() { return (mImgUrls == null ? 0 : mImgUrls.size()); } public boolean isEmpty() { return (mImgUrls == null); } /** * 开启组件 */ public void startUpAdComponent() { currentIndex = 0; pagerCurrent = 0; mViewPager.setAdapter(mPagerAdapter); mViewPager.setCurrentItem(currentIndex); updateIndicator(currentIndex); startTimer(); } /** * 更新组件中adapter数据 */ public void updateAdComponent() { stopTimer(); resetIndicatorLayout(); mPagerAdapter.notifyDataSetChanged(); startUpAdComponent(); } /** * 在页面销毁的时候调用该方法 */ public void stopAdComponent() { stopTimer(); } /** * 停止自动滚动的任务 */ public void stopTimer() { timeRunning = false; if (mTimer != null) { mTimer.cancel(); mTimer = null; } } /** * 开始自动滚动的任务,注意,只有图片个数大于1的时候才会自动滚动 */ public void startTimer() { timeRunning = true; if (mTimer == null && getSize() > 1 && mSwitchTime > 0) { mTimer = new Timer(); mTimer.schedule(new PagerTimerTask(), mSwitchTime, mSwitchTime); } } private class PagerTimerTask extends TimerTask { @Override public void run() { currentIndex++; pagerCurrent++; mHandler.sendEmptyMessage(0); } } private class MyOnPageChangeListener implements OnPageChangeListener { @Override public void onPageScrollStateChanged(int arg0) { } @Override public void onPageScrolled(int arg0, float arg1, int arg2) { } @Override public void onPageSelected(int position) { pagerCurrent = position; currentIndex = position % getSize();// 更新当前页面 updateIndicator(currentIndex); } } /** * 更新圆点指示器 */ private void updateIndicator(int position) { if (!isEmpty() && position < getSize()) { if (getSize() > 1) { resetAllIndicator(getSize());// 重置所有的指示器为为选择状态 View v = mIndicatorLayout.findViewWithTag(position); if (v != null) { v.setBackgroundResource(R.drawable.circle_indicator_selected);// 点亮 } } } } /** * 重置所有的指示器 */ private void resetAllIndicator(int size) { if (mIndicatorLayout != null) { for (int i = 0; i < size; i++) { View v = mIndicatorLayout.findViewWithTag(i); if (v != null) { v.setBackgroundResource(R.drawable.circle_indicator_normal); } } } } @SuppressLint("HandlerLeak") private Handler mHandler = new Handler() { public void handleMessage(android.os.Message msg) { mViewPager.setCurrentItem(pagerCurrent); }; }; }
当网络加载图片url列表成功之后,只需调用mAdComponent.updateAdComponent();即可
例如我的代码
private void updateAdSources(List<HomeBannerDTO> list) { imageUrls.clear(); for (HomeBannerDTO dto : list) { imageUrls.add(dto.getUrl()); } mBannerList.clear(); mBannerList.addAll(list); //更新banner组件 mAdComponent.updateAdComponent(); LogHelper.d(TAG, "updateAdComponent ....."); SettingsMgr.setLastRecommendAdList(mCxt, mBannerList); }
广告banner:手动滑动切换,自动切换,点击跳转,异步加载网络图片
标签:
原文地址:http://www.cnblogs.com/xgjblog/p/4226972.html