zoukankan      html  css  js  c++  java
  • Android广告页循环播放

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

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

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

     1 public class BaseViewPager extends ViewPager {
     2     private boolean scrollable = true;
     3 
     4     public BaseViewPager(Context context) {
     5         super(context);
     6     }
     7 
     8     public BaseViewPager(Context context, AttributeSet attrs) {
     9         super(context, attrs);
    10     }
    11 
    12     /**
    13      * 设置viewpager是否可以滚动
    14      * 
    15      * @param enable
    16      */
    17     public void setScrollable(boolean enable) {
    18         scrollable = enable;
    19     }
    20 
    21     @Override
    22     public boolean onInterceptTouchEvent(MotionEvent event) {
    23         if (scrollable) {
    24             return super.onInterceptTouchEvent(event);
    25         } else {
    26             return false;
    27         }
    28     }
    29 }
    View Code

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

      1 @SuppressLint("NewApi")
      2 public class CycleViewPager extends Fragment implements OnPageChangeListener {
      3     
      4     private List<ImageView> imageViews = new ArrayList<ImageView>();
      5     private ImageView[] indicators;
      6     private FrameLayout viewPagerFragmentLayout;
      7     private LinearLayout indicatorLayout; // 指示器
      8     private BaseViewPager viewPager;
      9     private BaseViewPager parentViewPager;
     10     private ViewPagerAdapter adapter;
     11     private CycleViewPagerHandler handler;
     12     private int time = 5000; // 默认轮播时间
     13     private int currentPosition = 0; // 轮播当前位置
     14     private boolean isScrolling = false; // 滚动框是否滚动着
     15     private boolean isCycle = false; // 是否循环
     16     private boolean isWheel = false; // 是否轮播
     17     private long releaseTime = 0; // 手指松开、页面不滚动时间,防止手机松开后短时间进行切换
     18     private int  WHEEL = 100; // 转动
     19     private int WHEEL_WAIT = 101; // 等待
     20     private ImageCycleViewListener mImageCycleViewListener;
     21     private List<MyImage> infos;
     22 
     23     @Override
     24     public View onCreateView(LayoutInflater inflater, ViewGroup container,
     25             Bundle savedInstanceState) {
     26         View view = LayoutInflater.from(getActivity()).inflate(
     27                 R.layout.view_cycle_viewpager_contet, null);
     28 
     29         viewPager = (BaseViewPager) view.findViewById(R.id.viewPager);
     30         indicatorLayout = (LinearLayout) view.findViewById(R.id.layout_viewpager_indicator);//就是那个白点吧
     31         viewPagerFragmentLayout = (FrameLayout) view.findViewById(R.id.layout_viewager_content);
     32 
     33         handler = new CycleViewPagerHandler(getActivity()) {
     34 
     35             @Override
     36             public void handleMessage(Message msg) {
     37                 super.handleMessage(msg);
     38                 if (msg.what == WHEEL && imageViews.size() != 0) {
     39                     if (!isScrolling) {
     40                         int max = imageViews.size() + 1;
     41                         int position = (currentPosition + 1) % imageViews.size();
     42                         viewPager.setCurrentItem(position, true);
     43                         if (position == max) { // 最后一页时回到第一页
     44                             viewPager.setCurrentItem(1, false);
     45                         }
     46                     }
     47 
     48                     releaseTime = System.currentTimeMillis();
     49                     handler.removeCallbacks(runnable);
     50                     handler.postDelayed(runnable, time);
     51                     return;
     52                 }
     53                 if (msg.what == WHEEL_WAIT && imageViews.size() != 0) {
     54                     handler.removeCallbacks(runnable);
     55                     handler.postDelayed(runnable, time);
     56                 }
     57             }
     58         };
     59 
     60         return view;
     61     }
     62 
     63     public void setData(List<ImageView> views, List<MyImage> list, ImageCycleViewListener listener) {
     64         setData(views, list, listener, 0);
     65     }
     66 
     67     /**
     68      * 初始化viewpager
     69      * 
     70      * @param views
     71      *            要显示的views
     72      * @param showPosition
     73      *            默认显示位置
     74      */
     75     public void setData(List<ImageView> views, List<MyImage> list, ImageCycleViewListener listener, int showPosition) {
     76         mImageCycleViewListener = listener;
     77         infos = list;
     78         this.imageViews.clear();
     79 
     80         if (views.size() == 0) {
     81             viewPagerFragmentLayout.setVisibility(View.GONE);
     82             return;
     83         }
     84 
     85         for (ImageView item : views) {
     86             this.imageViews.add(item);
     87         }
     88 
     89         int ivSize = views.size();
     90 
     91         // 设置指示器
     92         indicators = new ImageView[ivSize];
     93         if (isCycle)
     94             indicators = new ImageView[ivSize - 2];
     95         indicatorLayout.removeAllViews();
     96         for (int i = 0; i < indicators.length; i++) {
     97             View view = LayoutInflater.from(getActivity()).inflate(
     98                     R.layout.view_cycle_viewpager_indicator, null);
     99             indicators[i] = (ImageView) view.findViewById(R.id.image_indicator);
    100             indicatorLayout.addView(view);
    101         }
    102 
    103         adapter = new ViewPagerAdapter();
    104 
    105         // 默认指向第一项,下方viewPager.setCurrentItem将触发重新计算指示器指向
    106         setIndicator(0);
    107 
    108         viewPager.setOffscreenPageLimit(3);
    109         viewPager.setOnPageChangeListener(this);
    110         viewPager.setAdapter(adapter);
    111         if (showPosition < 0 || showPosition >= views.size())
    112             showPosition = 0;
    113         if (isCycle) {
    114             showPosition = showPosition + 1;
    115         }
    116         viewPager.setCurrentItem(showPosition);
    117 
    118     }
    119 
    120     /**
    121      * 设置指示器居中,默认指示器在右方
    122      */
    123     public void setIndicatorCenter() {
    124         RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
    125                 RelativeLayout.LayoutParams.WRAP_CONTENT,
    126                 RelativeLayout.LayoutParams.WRAP_CONTENT);
    127         params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
    128         params.addRule(RelativeLayout.CENTER_HORIZONTAL);
    129         indicatorLayout.setLayoutParams(params);
    130     }
    131     /**
    132      * 是否循环,默认不开启,开启前,请将views的最前面与最后面各加入一个视图,用于循环
    133      * 
    134      * @param isCycle
    135      *            是否循环
    136      */
    137     public void setCycle(boolean isCycle) {
    138         this.isCycle = isCycle;
    139     }
    140 
    141     /**
    142      * 是否处于循环状态
    143      * 
    144      * @return
    145      */
    146     public boolean isCycle() {
    147         return isCycle;
    148     }
    149 
    150     /**
    151      * 设置是否轮播,默认不轮播,轮播一定是循环的
    152      * 
    153      * @param isWheel
    154      */
    155     public void setWheel(boolean isWheel) {
    156         this.isWheel = isWheel;
    157         isCycle = true;
    158         if (isWheel) {
    159             handler.postDelayed(runnable, time);
    160         }
    161     }
    162 
    163     /**
    164      * 是否处于轮播状态
    165      * 
    166      * @return
    167      */
    168     public boolean isWheel() {
    169         return isWheel;
    170     }
    171 
    172     final Runnable runnable = new Runnable() {
    173 
    174         @Override
    175         public void run() {
    176             if (getActivity() != null && !getActivity().isFinishing()
    177                     && isWheel) {
    178                 long now = System.currentTimeMillis();
    179                 // 检测上一次滑动时间与本次之间是否有触击(手滑动)操作,有的话等待下次轮播
    180                 if (now - releaseTime > time - 500) {
    181                     handler.sendEmptyMessage(WHEEL);
    182                 } else {
    183                     handler.sendEmptyMessage(WHEEL_WAIT);
    184                 }
    185             }
    186         }
    187     };
    188 
    189     /**
    190      * 释放指示器高度,可能由于之前指示器被限制了高度,此处释放
    191      */
    192     public void releaseHeight() {
    193         getView().getLayoutParams().height = RelativeLayout.LayoutParams.MATCH_PARENT;
    194         refreshData();
    195     }
    196 
    197     /**
    198      * 设置轮播暂停时间,即没多少秒切换到下一张视图.默认5000ms
    199      * 
    200      * @param time
    201      *            毫秒为单位
    202      */
    203     public void setTime(int time) {
    204         this.time = time;
    205     }
    206 
    207     /**
    208      * 刷新数据,当外部视图更新后,通知刷新数据
    209      */
    210     public void refreshData() {
    211         if (adapter != null)
    212             adapter.notifyDataSetChanged();
    213     }
    214 
    215     /**
    216      * 隐藏CycleViewPager
    217      */
    218     public void hide() {
    219         viewPagerFragmentLayout.setVisibility(View.GONE);
    220     }
    221 
    222     /**
    223      * 返回内置的viewpager
    224      * 
    225      * @return viewPager
    226      */
    227     public BaseViewPager getViewPager() {
    228         return viewPager;
    229     }
    230 
    231     /**
    232      * 页面适配器 返回对应的view
    233      * 
    234      * @author Yuedong Li
    235      * 
    236      */
    237     private class ViewPagerAdapter extends PagerAdapter {
    238 
    239         @Override
    240         public int getCount() {
    241             return imageViews.size();
    242         }
    243 
    244         @Override
    245         public boolean isViewFromObject(View arg0, Object arg1) {
    246             return arg0 == arg1;
    247         }
    248 
    249         @Override
    250         public void destroyItem(ViewGroup container, int position, Object object) {
    251             container.removeView((View) object);
    252         }
    253 
    254         @Override
    255         public View instantiateItem(ViewGroup container, final int position) {
    256             ImageView v = imageViews.get(position);
    257             if (mImageCycleViewListener != null) {
    258                 v.setOnClickListener(new OnClickListener() {
    259                     
    260                     @Override
    261                     public void onClick(View v) {
    262                         mImageCycleViewListener.onImageClick(infos.get(currentPosition - 1), currentPosition, v);
    263                     }
    264                 });
    265             }
    266             container.addView(v);
    267             return v;
    268         }
    269 
    270         @Override
    271         public int getItemPosition(Object object) {
    272             return POSITION_NONE;
    273         }
    274     }
    275 
    276     @Override
    277     public void onPageScrollStateChanged(int arg0) {
    278         if (arg0 == 1) { // viewPager在滚动
    279             isScrolling = true;
    280             return;
    281         } else if (arg0 == 0) { // viewPager滚动结束
    282             if (parentViewPager != null)
    283                 parentViewPager.setScrollable(true);
    284 
    285             releaseTime = System.currentTimeMillis();
    286 
    287             viewPager.setCurrentItem(currentPosition, false);
    288             
    289         }
    290         isScrolling = false;
    291     }
    292 
    293     @Override
    294     public void onPageScrolled(int arg0, float arg1, int arg2) {
    295     }
    296 
    297     @Override
    298     public void onPageSelected(int arg0) {
    299         int max = imageViews.size() - 1;
    300         int position = arg0;
    301         currentPosition = arg0;
    302         if (isCycle) {
    303             if (arg0 == 0) {
    304                 currentPosition = max - 1;
    305             } else if (arg0 == max) {
    306                 currentPosition = 1;
    307             }
    308             position = currentPosition - 1;
    309         }
    310         setIndicator(position);
    311     }
    312 
    313     /**
    314      * 设置viewpager是否可以滚动
    315      * 
    316      * @param enable
    317      */
    318     public void setScrollable(boolean enable) {
    319         viewPager.setScrollable(enable);
    320     }
    321 
    322     /**
    323      * 返回当前位置,循环时需要注意返回的position包含之前在views最前方与最后方加入的视图,即当前页面试图在views集合的位置
    324      * 
    325      * @return
    326      */
    327     public int getCurrentPostion() {
    328         return currentPosition;
    329     }
    330 
    331     /**
    332      * 设置指示器
    333      * 
    334      * @param selectedPosition
    335      *            默认指示器位置
    336      */
    337     private void setIndicator(int selectedPosition) {
    338         for (int i = 0; i < indicators.length; i++) {
    339             indicators[i].setBackgroundResource(R.mipmap.icon_point);
    340         }
    341         if (indicators.length > selectedPosition)
    342             indicators[selectedPosition].setBackgroundResource(R.mipmap.icon_point_pre);
    343     }
    344 
    345     /**
    346      * 如果当前页面嵌套在另一个viewPager中,为了在进行滚动时阻断父ViewPager滚动,可以 阻止父ViewPager滑动事件
    347      * 父ViewPager需要实现ParentViewPager中的setScrollable方法
    348      */
    349     public void disableParentViewPagerTouchEvent(BaseViewPager parentViewPager) {
    350         if (parentViewPager != null)
    351             parentViewPager.setScrollable(false);
    352     }
    353 
    354     
    355     /**
    356      * 轮播控件的监听事件
    357      * 
    358      * @author minking
    359      */
    360     public static interface ImageCycleViewListener {
    361 
    362         /**
    363          * 单击图片事件
    364          * 
    365          * @param position
    366          * @param imageView
    367          */
    368         public void onImageClick(MyImage info, int postion, View imageView);
    369     }
    370 }
    View Code

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

    1 public class CycleViewPagerHandler extends Handler {
    2      Context context;
    3 
    4     public CycleViewPagerHandler(Context context) {
    5         this.context = context;
    6     }
    7 }
    View Code

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

     1 public class ViewFactory {
     2 
     3     /**
     4      * 获取ImageView视图的同时加载显示url
     5      * 
     6      * @param
     7      * @return
     8      */
     9     public static ImageView getImageView(Context context, String url) {
    10         ImageView imageView = (ImageView)LayoutInflater.from(context).inflate(
    11                 R.layout.view_banner, null);
    12         ImageLoader.getInstance().displayImage(url, imageView);//最核心的部分
    13         return imageView;
    14     }
    15 }
    View Code

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

     1 class MyImage {
     2 
     3     var link: String? = null
     4     var image:String?=null
     5     var title:String?=null
     6 
     7     constructor():super()
     8     constructor(image: String) : super() {
     9         this.image = image
    10     }
    11     constructor(image:String,link:String,title:String){
    12         this.image=image
    13         this.link=link
    14         this.title=title
    15     }
    16 
    17     override fun toString(): String {
    18         return "MyImage[link=$link,image=$image,title=$title]"
    19     }
    20 }
    View Code

       

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

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

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

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

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

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

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

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

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

        

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

     1  private fun getADfromServer() {
     2         var urlPath = ""
     3         var sign = ""
     4         val encode = Constant.ENCODE
     5         val school = Constant.SCHOOLDEFULT
     6         if (LogUtils.APP_IS_DEBUG) {
     7             urlPath = Constant.BASEURLFORTEST + Constant.School_AD
     8             sign = MD5Util.md5(Constant.SALTFORTEST)
     9         } else {
    10             urlPath = Constant.BASEURLFORRELEASE + Constant.School_AD
    11             sign = MD5Util.md5(Constant.SALTFORRELEASE)
    12         }
    13         val params = mapOf<String, Any?>("school" to school,"sign" to sign)
    14         LogUtils.d_debugprint(TAG, Constant.TOSERVER + urlPath + "
    提交的map=" + params.toString())
    15         Thread(Runnable {
    16             getAdfromServer= HttpUtil.httpPost(urlPath,params,encode)
    17            // LogUtils.d_debugprint(TAG,Constant.GETDATAFROMSERVER+getAdfromServer)
    18             val getCode:String
    19             var msg:String?=null
    20             var result:String
    21             var getData:List<Map<String,Any?>>
    22             getCode= JsonUtil.get_key_string(Constant.Server_Code,getAdfromServer!!)
    23             if(Constant.RIGHTCODE.equals(getCode)) {
    24                 handler_result1.post {
    25                     msg = JsonUtil.get_key_string(Constant.Server_Msg, getAdfromServer!!)
    26                     result = JsonUtil.get_key_string(Constant.Server_Result, getAdfromServer!!)
    27                     getData = JsonUtil.getListMap("data", result)//=====这里可能发生异常
    28                     LogUtils.d_debugprint(TAG, "json解析出来的对象是=" + getData.toString())
    29                     if (getData != null&&getData.size>0) {
    30                         for (i in getData.indices) {
    31                             val myImage=MyImage()
    32                             if(getData[i].getValue("link").toString()!=null&&getData[i].getValue("image").toString()!=null&&getData[i].getValue("title").toString()!=null) {
    33                                 myImage.link = getData[i].getValue("link").toString()
    34                                 myImage.image = getData[i].getValue("image").toString()
    35                                 myImage.title = getData[i].getValue("title").toString()
    36                                 myImageList.add(myImage)//=====这里保存了所有广告信息
    37                             }else{
    38                                 Toasty.error(context,Constant.SERVERBROKEN).show()
    39                             }
    40                         }
    41                         initialize() //初始化顶部导航栏
    42                     }else{
    43                         val myImage=MyImage()
    44                         myImage.link=""
    45                         myImage.image=""
    46                         myImage.title=""
    47                         myImageList.add(myImage)
    48                         //Toasty.error(context,Constant.SERVERBROKEN).show()
    49                     }
    50                 }
    51             }
    52         }).start()
    53     }
    View Code

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

        说明一下==>>

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

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

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

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

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

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

        说明一下==>>

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

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

        源码如下:

     1 private val mAdCycleViewListener = CycleViewPager.ImageCycleViewListener { info, position, imageView ->
     2         var position = position
     3         if (cycleViewPager!!.isCycle) {
     4             position = position - 1
     5             //Toasty.info(context,"标题:"+info.title+ "
    链接:" + info.link).show()
     6 
     7             val bundle=Bundle()
     8             bundle.putString("title",info.title)
     9             bundle.putString("link",info.link)
    10             val intent:Intent=Intent(context,ADWebView::class.java)
    11             intent.putExtras(bundle)
    12             startActivity(intent)
    13             activity.overridePendingTransition(0,R.anim.slide_left_out)
    14         }
    15     }
    View Code

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

          说明一下==>>

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

     1  <RelativeLayout
     2        android:layout_width="match_parent"
     3        android:layout_height="350pt">
     4 
     5     <fragment
     6         android:id="@+id/oneFm_fragment_cycle_viewpager_content"
     7         android:name="com.guangdamiao.www.mew_android_debug.banner.CycleViewPager"
     8         android:layout_width="match_parent"
     9         android:layout_height="350pt"
    10         />
    11 
    12     <ImageView
    13         android:id="@+id/oneFm_fragment_cycle_viewpager_content_over"
    14         android:layout_width="match_parent"
    15         android:layout_height="360pt"
    16         android:src="@drawable/one_overad"
    17         android:visibility="visible"
    18         android:scaleType="centerCrop"
    19         />
    20 
    21    </RelativeLayout>
    View Code

      效果如下:

      

      

    既然选择了,便不顾风雨兼程。Just follow yourself.
  • 相关阅读:
    收集座右铭
    Yii2查询语句使用不等于号
    使用jQuery获取Bootstrap Switch的值
    wamp 提示 Directive allow_call_time_pass_reference is no longer avaiable in PHP
    解决GitHub添加sshkey仍然无法访问clone远程仓库的问题
    异常-User class threw exception: java.lang.IllegalStateException: Cannot call methods on a stopped SparkContext.
    CDH5.16.1升级kafka0.10到1.0.1
    MacOs桌面自动被打乱的原因
    彻底解决MacOS上应用程序快捷键冲突的问题,自定义快捷键设置
    CDH5.16.1的maven依赖版本查询地址
  • 原文地址:https://www.cnblogs.com/Jason-Jan/p/7691809.html
Copyright © 2011-2022 走看看