摘要:项目要求做一个广告页,实现几秒更换一次广告页,下方还有指示第几张广告页,同样也支持手动左滑或右滑。

  1.准备好粘贴5个有关广告页的类。

    ①BaseViewPager==>自定义高度的ViewPager

 public class BaseViewPager extends ViewPager {
private boolean scrollable = true; public BaseViewPager(Context context) {
super(context);
} public BaseViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
} /**
* 设置viewpager是否可以滚动
*
* @param enable
*/
public void setScrollable(boolean enable) {
scrollable = enable;
} @Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (scrollable) {
return super.onInterceptTouchEvent(event);
} else {
return false;
}
}
}

    ②CycleViewPager==>实现可循环、可轮播的viewPager

 @SuppressLint("NewApi")
public class CycleViewPager extends Fragment implements OnPageChangeListener { private List<ImageView> imageViews = new ArrayList<ImageView>();
private ImageView[] indicators;
private FrameLayout viewPagerFragmentLayout;
private LinearLayout indicatorLayout; // 指示器
private BaseViewPager viewPager;
private BaseViewPager parentViewPager;
private ViewPagerAdapter adapter;
private CycleViewPagerHandler handler;
private int time = ; // 默认轮播时间
private int currentPosition = ; // 轮播当前位置
private boolean isScrolling = false; // 滚动框是否滚动着
private boolean isCycle = false; // 是否循环
private boolean isWheel = false; // 是否轮播
private long releaseTime = ; // 手指松开、页面不滚动时间,防止手机松开后短时间进行切换
private int WHEEL = ; // 转动
private int WHEEL_WAIT = ; // 等待
private ImageCycleViewListener mImageCycleViewListener;
private List<MyImage> infos; @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = LayoutInflater.from(getActivity()).inflate(
R.layout.view_cycle_viewpager_contet, null); viewPager = (BaseViewPager) view.findViewById(R.id.viewPager);
indicatorLayout = (LinearLayout) view.findViewById(R.id.layout_viewpager_indicator);//就是那个白点吧
viewPagerFragmentLayout = (FrameLayout) view.findViewById(R.id.layout_viewager_content); handler = new CycleViewPagerHandler(getActivity()) { @Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == WHEEL && imageViews.size() != ) {
if (!isScrolling) {
int max = imageViews.size() + ;
int position = (currentPosition + ) % imageViews.size();
viewPager.setCurrentItem(position, true);
if (position == max) { // 最后一页时回到第一页
viewPager.setCurrentItem(, false);
}
} releaseTime = System.currentTimeMillis();
handler.removeCallbacks(runnable);
handler.postDelayed(runnable, time);
return;
}
if (msg.what == WHEEL_WAIT && imageViews.size() != ) {
handler.removeCallbacks(runnable);
handler.postDelayed(runnable, time);
}
}
}; return view;
} public void setData(List<ImageView> views, List<MyImage> list, ImageCycleViewListener listener) {
setData(views, list, listener, );
} /**
* 初始化viewpager
*
* @param views
* 要显示的views
* @param showPosition
* 默认显示位置
*/
public void setData(List<ImageView> views, List<MyImage> list, ImageCycleViewListener listener, int showPosition) {
mImageCycleViewListener = listener;
infos = list;
this.imageViews.clear(); if (views.size() == ) {
viewPagerFragmentLayout.setVisibility(View.GONE);
return;
} for (ImageView item : views) {
this.imageViews.add(item);
} int ivSize = views.size(); // 设置指示器
indicators = new ImageView[ivSize];
if (isCycle)
indicators = new ImageView[ivSize - ];
indicatorLayout.removeAllViews();
for (int i = ; i < indicators.length; i++) {
View view = LayoutInflater.from(getActivity()).inflate(
R.layout.view_cycle_viewpager_indicator, null);
indicators[i] = (ImageView) view.findViewById(R.id.image_indicator);
indicatorLayout.addView(view);
} adapter = new ViewPagerAdapter(); // 默认指向第一项,下方viewPager.setCurrentItem将触发重新计算指示器指向
setIndicator(); viewPager.setOffscreenPageLimit();
viewPager.setOnPageChangeListener(this);
viewPager.setAdapter(adapter);
if (showPosition < || showPosition >= views.size())
showPosition = ;
if (isCycle) {
showPosition = showPosition + ;
}
viewPager.setCurrentItem(showPosition); } /**
* 设置指示器居中,默认指示器在右方
*/
public void setIndicatorCenter() {
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
params.addRule(RelativeLayout.CENTER_HORIZONTAL);
indicatorLayout.setLayoutParams(params);
}
/**
* 是否循环,默认不开启,开启前,请将views的最前面与最后面各加入一个视图,用于循环
*
* @param isCycle
* 是否循环
*/
public void setCycle(boolean isCycle) {
this.isCycle = isCycle;
} /**
* 是否处于循环状态
*
* @return
*/
public boolean isCycle() {
return isCycle;
} /**
* 设置是否轮播,默认不轮播,轮播一定是循环的
*
* @param isWheel
*/
public void setWheel(boolean isWheel) {
this.isWheel = isWheel;
isCycle = true;
if (isWheel) {
handler.postDelayed(runnable, time);
}
} /**
* 是否处于轮播状态
*
* @return
*/
public boolean isWheel() {
return isWheel;
} final Runnable runnable = new Runnable() { @Override
public void run() {
if (getActivity() != null && !getActivity().isFinishing()
&& isWheel) {
long now = System.currentTimeMillis();
// 检测上一次滑动时间与本次之间是否有触击(手滑动)操作,有的话等待下次轮播
if (now - releaseTime > time - ) {
handler.sendEmptyMessage(WHEEL);
} else {
handler.sendEmptyMessage(WHEEL_WAIT);
}
}
}
}; /**
* 释放指示器高度,可能由于之前指示器被限制了高度,此处释放
*/
public void releaseHeight() {
getView().getLayoutParams().height = RelativeLayout.LayoutParams.MATCH_PARENT;
refreshData();
} /**
* 设置轮播暂停时间,即没多少秒切换到下一张视图.默认5000ms
*
* @param time
* 毫秒为单位
*/
public void setTime(int time) {
this.time = time;
} /**
* 刷新数据,当外部视图更新后,通知刷新数据
*/
public void refreshData() {
if (adapter != null)
adapter.notifyDataSetChanged();
} /**
* 隐藏CycleViewPager
*/
public void hide() {
viewPagerFragmentLayout.setVisibility(View.GONE);
} /**
* 返回内置的viewpager
*
* @return viewPager
*/
public BaseViewPager getViewPager() {
return viewPager;
} /**
* 页面适配器 返回对应的view
*
* @author Yuedong Li
*
*/
private class ViewPagerAdapter extends PagerAdapter { @Override
public int getCount() {
return imageViews.size();
} @Override
public boolean isViewFromObject(View arg0, Object arg1) {
return arg0 == arg1;
} @Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
} @Override
public View instantiateItem(ViewGroup container, final int position) {
ImageView v = imageViews.get(position);
if (mImageCycleViewListener != null) {
v.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
mImageCycleViewListener.onImageClick(infos.get(currentPosition - ), currentPosition, v);
}
});
}
container.addView(v);
return v;
} @Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
} @Override
public void onPageScrollStateChanged(int arg0) {
if (arg0 == ) { // viewPager在滚动
isScrolling = true;
return;
} else if (arg0 == ) { // viewPager滚动结束
if (parentViewPager != null)
parentViewPager.setScrollable(true); releaseTime = System.currentTimeMillis(); viewPager.setCurrentItem(currentPosition, false); }
isScrolling = false;
} @Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
} @Override
public void onPageSelected(int arg0) {
int max = imageViews.size() - ;
int position = arg0;
currentPosition = arg0;
if (isCycle) {
if (arg0 == ) {
currentPosition = max - ;
} else if (arg0 == max) {
currentPosition = ;
}
position = currentPosition - ;
}
setIndicator(position);
} /**
* 设置viewpager是否可以滚动
*
* @param enable
*/
public void setScrollable(boolean enable) {
viewPager.setScrollable(enable);
} /**
* 返回当前位置,循环时需要注意返回的position包含之前在views最前方与最后方加入的视图,即当前页面试图在views集合的位置
*
* @return
*/
public int getCurrentPostion() {
return currentPosition;
} /**
* 设置指示器
*
* @param selectedPosition
* 默认指示器位置
*/
private void setIndicator(int selectedPosition) {
for (int i = ; i < indicators.length; i++) {
indicators[i].setBackgroundResource(R.mipmap.icon_point);
}
if (indicators.length > selectedPosition)
indicators[selectedPosition].setBackgroundResource(R.mipmap.icon_point_pre);
} /**
* 如果当前页面嵌套在另一个viewPager中,为了在进行滚动时阻断父ViewPager滚动,可以 阻止父ViewPager滑动事件
* 父ViewPager需要实现ParentViewPager中的setScrollable方法
*/
public void disableParentViewPagerTouchEvent(BaseViewPager parentViewPager) {
if (parentViewPager != null)
parentViewPager.setScrollable(false);
} /**
* 轮播控件的监听事件
*
* @author minking
*/
public static interface ImageCycleViewListener { /**
* 单击图片事件
*
* @param position
* @param imageView
*/
public void onImageClick(MyImage info, int postion, View imageView);
}
}

       ③CycleViewPagerHandler==>为了防止内存泄漏,定义外部类,防止内部类对外部类的引用

 public class CycleViewPagerHandler extends Handler {
Context context; public CycleViewPagerHandler(Context context) {
this.context = context;
}
}

        ④ViewFactory==>创建ImageView工厂,获取ImageView视图的同时加载显示url

 public class ViewFactory {

     /**
* 获取ImageView视图的同时加载显示url
*
* @param
* @return
*/
public static ImageView getImageView(Context context, String url) {
ImageView imageView = (ImageView)LayoutInflater.from(context).inflate(
R.layout.view_banner, null);
ImageLoader.getInstance().displayImage(url, imageView);//最核心的部分
return imageView;
}
}

         ⑤MyImage==>这是广告页的bean类

 class MyImage {

     var link: String? = null
var image:String?=null
var title:String?=null constructor():super()
constructor(image: String) : super() {
this.image = image
}
constructor(image:String,link:String,title:String){
this.image=image
this.link=link
this.title=title
} override fun toString(): String {
return "MyImage[link=$link,image=$image,title=$title]"
}
}

   

   2.从服务器中拿到图片的链接地址,一般广告页都是从服务器拿到的数据。本地的也可以,而且更加简单了。我就拿前者举例吧。

    下面的代码是我自己的一个请求,里面有很多东西都是自己定义的东西。 

    如:LogUtils.d_debugprint()是自己封装好的一个日志输出的类。

      Constant也是自己封装好的常量。

      HttpUtil.httpPost也是自己封装的网络请求的类。

      JsonUtil.get_key_string也是自己封装Json解析的类。

      MyImage是自己定义的一个Bean类。

      Toasty是引用的第三方库toast的类,用来提示用户。

      initialize()是自己初始化广告页,后面第三步就是写这个函数了。

    

      解释清楚之后,请求的函数如下:

  private fun getADfromServer() {
var urlPath = ""
var sign = ""
val encode = Constant.ENCODE
val school = Constant.SCHOOLDEFULT
if (LogUtils.APP_IS_DEBUG) {
urlPath = Constant.BASEURLFORTEST + Constant.School_AD
sign = MD5Util.md5(Constant.SALTFORTEST)
} else {
urlPath = Constant.BASEURLFORRELEASE + Constant.School_AD
sign = MD5Util.md5(Constant.SALTFORRELEASE)
}
val params = mapOf<String, Any?>("school" to school,"sign" to sign)
LogUtils.d_debugprint(TAG, Constant.TOSERVER + urlPath + "\n提交的map=" + params.toString())
Thread(Runnable {
getAdfromServer= HttpUtil.httpPost(urlPath,params,encode)
// LogUtils.d_debugprint(TAG,Constant.GETDATAFROMSERVER+getAdfromServer)
val getCode:String
var msg:String?=null
var result:String
var getData:List<Map<String,Any?>>
getCode= JsonUtil.get_key_string(Constant.Server_Code,getAdfromServer!!)
if(Constant.RIGHTCODE.equals(getCode)) {
handler_result1.post {
msg = JsonUtil.get_key_string(Constant.Server_Msg, getAdfromServer!!)
result = JsonUtil.get_key_string(Constant.Server_Result, getAdfromServer!!)
getData = JsonUtil.getListMap("data", result)//=====这里可能发生异常
LogUtils.d_debugprint(TAG, "json解析出来的对象是=" + getData.toString())
if (getData != null&&getData.size>) {
for (i in getData.indices) {
val myImage=MyImage()
if(getData[i].getValue("link").toString()!=null&&getData[i].getValue("image").toString()!=null&&getData[i].getValue("title").toString()!=null) {
myImage.link = getData[i].getValue("link").toString()
myImage.image = getData[i].getValue("image").toString()
myImage.title = getData[i].getValue("title").toString()
myImageList.add(myImage)//=====这里保存了所有广告信息
}else{
Toasty.error(context,Constant.SERVERBROKEN).show()
}
}
initialize() //初始化顶部导航栏
}else{
val myImage=MyImage()
myImage.link=""
myImage.image=""
myImage.title=""
myImageList.add(myImage)
//Toasty.error(context,Constant.SERVERBROKEN).show()
}
}
}
}).start()
}

   3.然后就是initialize()函数了

    说明一下==>>

    myImageOverAD是覆盖在广告页上的一张默认图片,如果没有网,或者请求失败的时候,将显示这张图片。

    cycleViewPager是广告栏中的一个叫fragment的布局。

    views是广告栏的一个ArrayList<ImageView>(),可以动态添加ImageView

    mAdCycleViewListener是广告页点击的监听器,第四步会详细讲。

  @SuppressLint("NewApi")
private fun initialize() {
myImageOverAD!!.visibility=View.GONE
cycleViewPager = activity.fragmentManager.findFragmentById(R.id.oneFm_fragment_cycle_viewpager_content) as CycleViewPager views.add(ViewFactory.getImageView(context, myImageList[myImageList.size - ].image)) // 将最后一个ImageView添加进来
for (i in myImageList.indices) {
views.add(ViewFactory.getImageView(context, myImageList[i].image))
}
views.add(ViewFactory.getImageView(context, myImageList[].image)) // 将第一个ImageView添加进来
cycleViewPager!!.isCycle = true // 设置循环,在调用setData方法前调用
cycleViewPager!!.setData(views, myImageList, mAdCycleViewListener) // 在加载数据前设置是否循环
cycleViewPager!!.isWheel = true //设置轮播
cycleViewPager!!.setTime() // 设置轮播时间,默认5000ms
cycleViewPager!!.setIndicatorCenter() //设置圆点指示图标组居中显示,默认靠右
}

   4.然后是mAdCycleViewListener监听器的实现了。

    说明一下==>>

    ADWebView是点击广告页要调整的webView。

    R.anim.slide_left_out是一个从左边出去的动画。

    源码如下:

 private val mAdCycleViewListener = CycleViewPager.ImageCycleViewListener { info, position, imageView ->
var position = position
if (cycleViewPager!!.isCycle) {
position = position -
//Toasty.info(context,"标题:"+info.title+ "\n链接:" + info.link).show() val bundle=Bundle()
bundle.putString("title",info.title)
bundle.putString("link",info.link)
val intent:Intent=Intent(context,ADWebView::class.java)
intent.putExtras(bundle)
startActivity(intent)
activity.overridePendingTransition(,R.anim.slide_left_out)
}
}

   5.广告页的布局代码差点忘记了。

      说明一下==>>

    这里的fragment才是主角,下方的ImageView是覆盖在广告页上的一张默认图片,在没有网获取没有成功请求到服务器的时候显示的图片。

  <RelativeLayout
android:layout_width="match_parent"
android:layout_height="350pt"> <fragment
android:id="@+id/oneFm_fragment_cycle_viewpager_content"
android:name="com.guangdamiao.www.mew_android_debug.banner.CycleViewPager"
android:layout_width="match_parent"
android:layout_height="350pt"
/> <ImageView
android:id="@+id/oneFm_fragment_cycle_viewpager_content_over"
android:layout_width="match_parent"
android:layout_height="360pt"
android:src="@drawable/one_overad"
android:visibility="visible"
android:scaleType="centerCrop"
/> </RelativeLayout>

  效果如下:

  

  

Android广告页循环播放的更多相关文章

  1. android 自定义无限循环播放的viewPager。轮播ViewPager。实现循环播放 广告,主题内容,活动,新闻内容时。

    前言 实际项目需要一个 播放广告的控件,可能有多个广告图片.每个一段时间更换该图片.简单来说,就是一个 “循环播放图片”的控件. 间隔时间更换图片 一般来说,图片切换时需要有动画效果 需要支持手势,用 ...

  2. php广告图片循环播放 幻灯片效果

    <!DOCTYPE> <html> <head> <meta http-equiv="content-type" content=&quo ...

  3. Android实现Banner界面广告图片循环轮播(包括实现手动滑动循环)

    前言:经常会看到有一些app的banner界面可以实现循环播放多个广告图片和手动滑动循环.本以为单纯的ViewPager就可以实现这些功能.但是蛋疼的事情来了,ViewPager并不支持循环翻页.所以 ...

  4. android 随手记 videoview循环播放网络视频 和mediaplayer+sufaceview播放网络视频

    1:videoview循环播放视频 1>xml <RelativeLayout xmlns:android="http://schemas.android.com/apk/res ...

  5. Android videoview循环播放视频

    如何在一个activity里实现videoview对一个文件夹下的所有视频文件顺序循环播放,当切换界面时暂停, 切换回来继续原来的视频播放呢.所谓的 自动循环播放就是监听到视频播放结束之后继续重新播放 ...

  6. 深入理解MVC C#+HtmlAgilityPack+Dapper走一波爬虫 StackExchange.Redis 二次封装 C# WPF 用MediaElement控件实现视频循环播放 net 异步与同步

    深入理解MVC   MVC无人不知,可很多程序员对MVC的概念的理解似乎有误,换言之他们一直在错用MVC,尽管即使如此软件也能被写出来,然而软件内部代码的组织方式却是不科学的,这会影响到软件的可维护性 ...

  7. 5. apktool 给XX手机卫士加广告页

    一. 编写广告页 写一个广告页面,并调用其他页面的demo (1) 设计界面如下 (2) 编写代码如下 public class SplashActivity extends Activity {   ...

  8. android中无限循环滑动的gallery实例

    android中无限循环滑动的gallery实例 1.点击图片有变暗的效果,使用imageview.setAlpha(),并且添加ontouchListener public void init() ...

  9. Android实现简单音乐播放器(MediaPlayer)

    Android实现简单音乐播放器(MediaPlayer) 开发工具:Andorid Studio 1.3 运行环境:Android 4.4 KitKat 工程内容 实现一个简单的音乐播放器,要求功能 ...

随机推荐

  1. jQuery动态添加元素,并提交json格式数据到后台

    参考:https://www.cnblogs.com/shj-com/p/7878727.html 下载 下载该插件的地址是:http://www.bootcdn.cn/jquery.serializ ...

  2. ifream页面弹出框遮盖层覆盖父页面

    1.首先找到子页面上遮罩层的id, 2.然后再父页面编写个js方法 function shade() { $(".layui-layer-shade").height($(wind ...

  3. Diary

    2019.1.16 233333333 2018.12.5 猜猜我写了什么? 2018.12.3 maya真是越来粤菜了.. 突然发现cf其实有中文 2018.12.1 说好的今天出成绩呢?.. 咕咕 ...

  4. 如何使用VS将项目生成一个安装包?

    VS2010项目的部署与安装winform程序,我想进行安装.1.在解决方案中 ——点击右键——添加 2.然后选择 安装和部署 ——安装向导 可以更改名称 3.点击 下一步 4.然后选择上那3个 5. ...

  5. Python之自定义封装一个简单的Log类

    参考:http://www.jb51.net/article/42626.htm 参考:http://blog.csdn.net/u011541946/article/details/70198676 ...

  6. WebUploader实现采集图片的功能

    项目最开始用百度团队的文件上传组件做了个物料照片采集的功能,后来做员工头像采集时竟然不知道怎么使用了. 参照官方Demo: http://fex.baidu.com/webuploader/getti ...

  7. SQLSERVER编译与重编译

    SQLSERVER编译与重编译 编译的含义 当SQLSERVER收到任何一个指令,包括查询(query).批处理(batch).存储过程.触发器(trigger) .预编译指令(prepared st ...

  8. hdu-1556 Color the ball---树状数组+区间修改单点查询

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1556 题目大意: Problem Description N个气球排成一排,从左到右依次编号为1,2 ...

  9. 关于SIGSEGV错误及处理方法

    http://blog.csdn.net/brace/article/details/1102422 今天编程遇到了SIGSEGV错误,比较困惑,所以找了些资料,总结一下: (1)官方说法是: SIG ...

  10. 2018.7.2 如何用js实现点击图片切换为另一图片,再次点击恢复到原图片

    <!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8&quo ...