在许多项目之中,首页的activity或者fragment都会一般有广告条的效果,我们来自定义实现一下广告条。
整体运行效果:
布局文件activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" > <android.support.v4.view.ViewPager android:id="@+id/viewpager" android:layout_width="wrap_content" android:layout_height="200dp" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignBottom="@id/viewpager" android:background="#44000000" android:gravity="center_horizontal" android:orientation="vertical" > <TextView android:id="@+id/tv_msg" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center_horizontal" android:text="三只火枪手" android:textColor="#ffffff" android:textSize="18sp" /> <LinearLayout android:id="@+id/ll_point_groups" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" android:padding="3dp" /> </LinearLayout> </RelativeLayout>实例化ViewPager和关联其源码:
public class MainActivity extends Activity { private ViewPager viewpager; private LinearLayout ll_point_group; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); viewpager = (ViewPager) findViewById(R.id.viewpager); ll_point_group = (LinearLayout) findViewById(R.id.ll_point_group); } }
关联源代码:
1.删除工程里面的Android Depandencies,删除后会报错,不要理会。看下面
2.添加libs目录下的Android-support-v4.jar包
选中-->右键-->build path-->add to build path
3.关联源代码
目录:C:\android\adt-bundle-windows-x86_64-20130219\sdk\extras\android\support\v4\src\java
点击ViewPager类,出现图标;
大家对于v4包都已经很熟悉了,现在在新建android项目时,v4包是默认导入的。v7包出来没多长时间,用的人也不多,主要对3.0以下版本提供 ActionBar支持,以及SearchView,PopupMenu等控件的支持。因为一些开源框架已经实现对3.0以下版本ActionBar的支 持,所以v7包的使用意义也不是很大。
知识拓展:
如果jar包导入错误,怎么修改呢?
右键工程---->properties---->Java Build Path --->Libraries-->选择android-support-v4.jar展开---->Editor--->External Folder
4.ViewPager的原理
能显示很多页面,这些页面可以是图片也可以是布局文件。
设置图片资源ID和图片标题集合和准备ImageView列表数据// 图片资源ID private final int[] imageIds = { R.drawable.a, R.drawable.b, R.drawable.c, R.drawable.d, R.drawable.e }; // 图片标题集合 private final String[] imageDescriptions = { "巩俐不低俗,我就不能低俗", "扑树又回来啦!再唱经典老歌引万人大合唱", "揭秘北京电影如何升级", "乐视网TV版大派送", "热血屌丝的反杀" }; //准备数据 imageList = new ArrayList<ImageView>(); for(int i=0;i<imageIds.length;i++){ <span style="white-space:pre"> ImageView imageView = new ImageView(this); imageView.setBackgroundResource(imageIds[i]); imageList.add(imageView);</span> }为ViewPager设置适配器:
private class MyPagerAdapter extends PagerAdapter { @Override public int getCount() { // 页面或者图片的总数 return imageList.size(); } /** * 功能:给ViewPager添加指定的view * container 就是ViewPager,其实就是容器。 * position 具体页面或者图片的位置 */ @Override public Object instantiateItem(ViewGroup container, int position) { System.out.println("instantiateItem=="+position); View view = imageList.get(position); container.addView(view); //返回的值,不一定是View ,也可以是和View有关系的任意的Object //return super.instantiateItem(container, position); return view; } /** * 判断某个page和object的关系 * object 是 instantiateItem的返回值 */ @Override public boolean isViewFromObject(View view, Object object) { //if(view ==object){ // return true; //}else{ // return false; //} return view ==object; } /** * 销毁指定位置上的View或者object */ @Override public void destroyItem(ViewGroup container, int position, Object object) { System.out.println("destroyItem=="+position); container.removeView((View) object); //super.destroyItem(container, position, object); } }解决运行时错误:
选中项目--->右键--->Java Build Path --->
order and export--->勾选android-support-v4.jar--->千万不要忘了clean
viewpager.setOnPageChangeListener(new OnPageChangeListener() { /** * 当页面被选择了回调 * position 当前被显示的页面的位置:从0开始 */ @Override public void onPageSelected(int position) { tv_image_desc.setText(imageDescriptions[position]); } /** * 当页面滑动了调用该方法 */ @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } /** * 当页面状态发送变化的调用防方法 * 静止--滑动 * 滑动-静止 * */ @Override public void onPageScrollStateChanged(int state) { } });2.用shape资源定义点和背景:
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval"> <size android:height="5dp" android:width="5dp"/> <solid android:color="#55000000"/> </shape>point_focused.xml
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval"> <size android:height="5dp" android:width="5dp"/> <solid android:color="#88ffffff"/> </shape>point_selector.xml
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android" > <item android:drawable="@drawable/point_normal" android:state_enabled="false"/> <item android:drawable="@drawable/point_focused" android:state_enabled="true"/> </selector>3.代码里面添加指示点:
for(int i=0;i<imageIds.length;i++){ ImageView imageView = new ImageView(this); imageView.setBackgroundResource(imageIds[i]); imageViews.add(imageView); //添加指示点 ImageView point = new ImageView(this); point.setBackgroundResource(R.drawable.point_selsetor); ll_point_group.addView(point); //默认情况下,第一个小点enable为true if(i ==0){ point.setEnabled(true); }else{ point.setEnabled(false); } }4.设置改变指示点的状态:
/** * 上次的位置 */ private int lastPointIndex; viewpager.setOnPageChangeListener(new OnPageChangeListener() { /** * 当页面被选择了回调 * position 当前被显示的页面的位置:从0开始 */ @Override public void onPageSelected(int position) { System.out.println("onPageSelected="+position); tv_image_desc.setText(imageDescriptions[position]); //设置指示点的状态 enable 的状态为true或者为false; ll_point_group.getChildAt(position).setEnabled(true); ll_point_group.getChildAt(lastPointIndex).setEnabled(false); lastPointIndex = position; } /** * 当页面滑动了调用该方法 */ @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } /** * 但页面状态发送变化的调用防方法 * 静止--滑动 * 滑动-静止 * */ @Override public void onPageScrollStateChanged(int state) { System.out.println("onPageScrollStateChanged===state=="+state); } });5.设置指示点的间距:
for(int i=0;i<imageIds.length;i++){ ImageView imageView = new ImageView(this); imageView.setBackgroundResource(imageIds[i]); imageViews.add(imageView); //添加指示点 ImageView point = new ImageView(this); LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, -2); params.leftMargin = 15; point.setLayoutParams(params); point.setBackgroundResource(R.drawable.point_selsetor); ll_point_group.addView(point); //默认情况下,第一个小点enable为true if(i ==0){ point.setEnabled(true); }else{ point.setEnabled(false); } }
注意导入包的时候,当前控件放入什么布局就导入谁的LayoutParams的。
6.设置可以循环滚动:viewpager.setOnPageChangeListener(new OnPageChangeListener() { /** * 当页面被选择了回调 * position 当前被显示的页面的位置:从0开始 */ @Override public void onPageSelected(int position) { int myIndex = position % imageViews.size(); System.out.println("onPageSelected="+position); tv_image_desc.setText(imageDescriptions[myIndex]); //设置指示点的状态 enable 的状态为true或者为false; ll_point_group.getChildAt(myIndex).setEnabled(true); ll_point_group.getChildAt(lastPointIndex).setEnabled(false); lastPointIndex = myIndex; } //.............................. }); } private class MyPagerAdapter extends PagerAdapter { @Override public int getCount() { //得到数据的总数 //return imageViews.size(); return Integer.MAX_VALUE; } /** * 给ViewPager添加指定的View * container 是ViewPage,他是一个容器 * position 要实例化的view的位置 */ @Override public Object instantiateItem(ViewGroup container, int position) { //System.out.println("instantiateItem=="+position); //实例化View View view = imageViews.get(position%imageViews.size()); container.addView(view); //返回值,不一定要是View对象,也可以是和View有关系的任意object //return super.instantiateItem(container, position); return view; } //......................7.解决左滑没有效果问题:
//要求刚好是imageViews.size()的整数倍 int item = Integer.MAX_VALUE/2-Integer.MAX_VALUE/2%imageViews.size(); //让ViewPager跳转到指定的位置,应该保证是imageView.size()的整数倍 viewpager.setCurrentItem(item ); //11 和 101
实现方式有多种方案:
1.定时器 timer + Handler
2.while true 循环 sleep + Handler;
3,ClockManger + Handler ;
4,Handler
我们采用常用的方式Handler
/** * 是否自定滑动运行中 */ private boolean isRunning = false; private Handler handler = new Handler(){ public void handleMessage(android.os.Message msg) { viewpager.setCurrentItem(viewpager.getCurrentItem()+1); if(isRunning){ handler.sendEmptyMessageDelayed(0, 4000); } }; };
在onCreate中写上
isRunning = true; handler.sendEmptyMessageDelayed(0, 2000);
package com.xbmu.adviewpager; import java.util.ArrayList; import java.util.List; import android.app.Activity; import android.os.Bundle; 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.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import android.widget.LinearLayout.LayoutParams; public class MainActivity extends Activity { private ViewPager viewPager; private TextView tv_msg; private LinearLayout ll_point_groups; private List<ImageView> imageViews; // 图片标题集合 private final String[] imageDescriptions = { "巩俐不低俗,我就不能低俗", "朴树又回来啦!再唱经典老歌引万人大合唱", "揭秘北京电影如何升级", "乐视网TV版大派送", "热血屌丝的反杀" }; private int[] ids = { R.drawable.a, R.drawable.b, R.drawable.c, R.drawable.d, R.drawable.e }; /** * 记录上次被高亮的位置 */ private int lastIndex = 0; /** * true:自动滑动 * false:停止自动滑动 */ private boolean isRuning = false; private Handler handler = new Handler(){ public void handleMessage(android.os.Message msg) { if(isRuning){ //自动滑动 viewPager.setCurrentItem(viewPager.getCurrentItem()+1); handler.sendEmptyMessageDelayed(0, 2000); } }; }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 1.初始化控件 viewPager = (ViewPager) findViewById(R.id.viewpager); tv_msg = (TextView) findViewById(R.id.tv_msg); ll_point_groups = (LinearLayout) findViewById(R.id.ll_point_groups); // 2.准备数据,实例化广告图片 imageViews = new ArrayList<ImageView>(); for (int i = 0; i < ids.length; i++) { ImageView view = new ImageView(this); // 设置背景 view.setBackgroundResource(ids[i]); // 把图片添加到列表中 imageViews.add(view); // 2.1实例化指示点或者下标点 ImageView point = new ImageView(this); point.setImageResource(R.drawable.point_selector); // View的父亲(LinearLayout布局)是什么布局文件,就导入它的包 LayoutParams params = new LayoutParams(10, 10); params.leftMargin = 15; point.setLayoutParams(params); // 把点添加到线性布局 ll_point_groups.addView(point); // 默认设置第一个高亮显示 if (i == 0) { point.setEnabled(true); } else { point.setEnabled(false); } } // 3.设置适配器 viewPager.setAdapter(new MyPagerAdapter()); // 4.设置页面改变监听(广告图片和文字一起改变) viewPager.setOnPageChangeListener(new OnPageChangeListener() { /** * 当某个页面被选择的时候回调 */ @Override public void onPageSelected(int position) { int newIndex = position % imageViews.size(); // 取出广告文字 String msg = imageDescriptions[newIndex]; //设置广告文字 tv_msg.setText(msg); //对应的点高亮 ll_point_groups.getChildAt(newIndex).setEnabled(true); //上次的点击设置成默认 ll_point_groups.getChildAt(lastIndex).setEnabled(false); lastIndex = newIndex; } /** * 当页面滚动的时候被调用 */ @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } /** * 当状态发生改变的时候回调 * 静止-滚动 * 滚蛋-静止 */ @Override public void onPageScrollStateChanged(int arg0) { } }); //默认中 中间开始滚动 int midPosition = Integer.MAX_VALUE/2; viewPager.setCurrentItem(midPosition); isRuning = true; //从第0个位置开始,每隔2秒,自动运行广告条 handler.sendEmptyMessageDelayed(0, 2000); } @Override protected void onDestroy() { super.onDestroy(); isRuning = false; } private class MyPagerAdapter extends PagerAdapter { // 得到总条数 @Override public int getCount() { // 把这个总条数设置很大很大 return Integer.MAX_VALUE; } /** * 相当于getView:实例化每个页面的View和添加View ViewGroup container:容器 int position:位置 */ @Override public Object instantiateItem(ViewGroup container, int position) { // 根据位置去某个View int newPosition = position % imageViews.size();// 值总在0~imageViews.size()之间 ImageView view = imageViews.get(newPosition); // 添加到容器中 container.addView(view); // 返回实例化的View return view; } /** * 判断view和instantiateItem返回的对象是否一样 Object obj:是instantiateItem返回的对象 */ @Override public boolean isViewFromObject(View view, Object object) { // if(view == object){ // return true; // }else{ // return false; // } // 上面的代码可以写成下面这样的形式 return view == object; } /** * 实例化两张图片 最多只能装三张图片 */ @Override public void destroyItem(ViewGroup container, int position, Object object) { // 释放资源,自己处理了,不需要执行父类的方法了 container.removeView((View) object); // super.destroyItem(container, position, object); } } }