广告banner:手动滑动切换,自动切换,点击跳转,异步加载网络图片
效果图:
该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:手动滑动切换,自动切换,点击跳转,异步加载网络图片的更多相关文章
- Ztree异步加载自动展开节点
在Ztree的官网Demo中,有自动展开的例子,是通过设置节点属性open:true来实现自动展开的,但是在异步加载中,这个属性设置为true也不会自动展开,因为open:true是指在有子节点的情况 ...
- ionic UI Component Slides使用:手动滑动后自动滑动失效解决
在使用ionic的UI组件Slides时,发现手动滑动后,自动滑动失效 然后历经一点点的艰辛查找后找到方法,如下: 页面代码使用 <ion-slides pager loop="tru ...
- iScroll.js 向上滑动异步加载数据回弹问题
iScroll是一款用于移动设备web开发的一款插件.像缩放.下拉刷新.滑动切换等移动应用上常见的一些效果都可以轻松实现. 现在最新版本是5.X,官网这里:http://iscrolljs.com/ ...
- 解决ListView滑动时卡的问题,实现异步加载图片解决
ListView是最为常见的空间之一,现在的应用的呈现形式大多数都需要用到ListView来呈现,以列表的方式最直观最便于操作. 那么在使用的过程中大家一定使用adapter适配器来匹配这个ListV ...
- 关于使用Iscroll.js异步加载数据后不能滑动到最底端的问题解决方案
关于使用Iscroll.js异步加载数据后不能滑动到最底端,拉到最下边又弹回去的问题困扰了我老半天,相信很多朋友都遇到了.我刚好不小心解决了,和大家分享一下.由于各种忙,下边就直接上代码吧. (前提是 ...
- easyui datagrid 异步加载数据时滚动条有时会自动滚到最底部的问题
在使用easyui 的datagrid异步加载数据时发现滚动条有时会自动滚到最底部.经测试发现,如果加载数据前没有选中行则不会出现这个问题.这样我们可以在重新异步加载数据前取消选中行就可以避免这个问题 ...
- 高仿优酷Android客户端图片左右滑动(自动切换)
本例是用ViewPager去做的实现,支持自动滑动和手动滑动,不仅优酷网,实际上有很多商城和门户网站都有类似的实现: 具体思路: 1. 工程中需要添加android-support-v4.jar,才能 ...
- springboot+layui实现PC端用户的增删改查 & 整合mui实现app端的自动登录和用户的上拉加载 & HBuilder打包app并在手机端下载安装
springboot整合web开发的各个组件在前面已经有详细的介绍,下面是用springboot整合layui实现了基本的增删改查. 同时在学习mui开发app,也就用mui实现了一个简单的自动登录和 ...
- tab切换-自动、点击、内容变换
<div class="tab"> <ul class="pics"> ...
随机推荐
- pat 甲级 1010. Radix (25)
1010. Radix (25) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue Given a pair of ...
- pat 甲级 1009. Product of Polynomials (25)
1009. Product of Polynomials (25) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yu ...
- Python之Django框架
1.Django简介 Python下有多款不同的 Web 框架,Django是最有代表性的一种.许多成功的网站和APP都基于Django. Django是一个开源的Web应用框架,由Python写成. ...
- 【HDOJ5555】Immortality of Frog(状压DP)
题意:给你一个NxN的网格,第N行的每一列都有个青蛙,这些青蛙只会往上走, 上帝会在每个膜中随机等概率放一个长生不老的药, 一共有N个膜,每个膜覆盖一些区间,如果这个区间恰好为N那么就是好膜,否则是坏 ...
- *LOJ#2085. 「NOI2016」循环之美
$n \leq 1e9,m \leq 1e9,k \leq 2000$,求$k$进制下$\frac{x}{y}$有多少种不同的纯循环数取值,$1 \leq x \leq n,1 \leq y \leq ...
- Android启动过程深入解析【转】
转自:http://www.open-open.com/lib/view/open1403250347934.html 当按下Android设备电源键时究竟发生了什么? Android的启动过程是怎么 ...
- 记录: 百度webuploader 分片文件上传java服务器端(spring mvc)示例的优化
最近项目上用到文件分片上传,于是找到了百度的一个开源前端控件webuploader. 于是尝试使用. 下载下来后,它提供的服务器端示例代码是php版的,那么Java版的呢? 其实,上传文件都是按照rf ...
- Fresco使用之OOM问题记录
最近友盟上5.0以上系统报出很多OOM异常,看下日志看到facebook的时候就知道一定是Fresco使用不当导致了OOM. java.lang.OutOfMemoryError: Failed to ...
- Codeforces 371B Fox Dividing Cheese(简单数论)
题目链接 Fox Dividing Cheese 思路:求出两个数a和b的最大公约数g,然后求出a/g,b/g,分别记为c和d. 然后考虑c和d,若c或d中存在不为2,3,5的质因子,则直接输出-1( ...
- Kali Linux 2017中Scapy运行bug解决
Kali Linux 2017中Scapy运行bug解决 Scapy是一款强大的网络数据包构建工具.在Kali Linux 2017中,当在scapy的命令行中,运行res.graph()生成图形 ...