viewpager广告轮播
基于ViewPager做一个广告轮播图
一 初步搭起viewpager轮播
1.1 在activity_main.xml中放置viewpager控件
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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:orientation="vertical"
tools:context=".MainActivity">
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="320dp"/>
</FrameLayout>
1.2 代码中准备数据
private int[] mImages = {
R.drawable.img1,
R.drawable.img2,
R.drawable.img3,
R.drawable.img4,
R.drawable.img5
};
1.3 设置适配器
import android.content.Context;
import android.support.v4.view.PagerAdapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
/**
* Created by wxyass
*/
public class BannerAdapter extends PagerAdapter{
private LayoutInflater mInflater;
private int[] mImages;
public BannerAdapter(Context context,int[] mImagesi) {
mInflater = LayoutInflater.from(context);
mImages = mImagesi;
}
// 个数
@Override
public int getCount() {
return mImages.length;
}
/**
* 判断是否可以复用条目
*/
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
/**
* 初始化条目
*/
@Override
public Object instantiateItem(ViewGroup container, int position) {
// 条目布局
View view = mInflater.inflate(R.layout.item, container, false);
ImageView imageView = (ImageView) view.findViewById(R.id.image);
imageView.setImageResource(mImages[position]);
// 将图片控件添加到容器
container.addView(view);
// 返回
return view;
}
/**
* 销毁条目
*/
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
}
1.4 附上viewpager的adapter条目的布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#b0b0b0">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:id="@+id/image" />
</LinearLayout>
1.5 代码中调用适配器
import android.os.Bundle;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
private ViewPager mBanner;
// 图片资源
private int[] mImages = {
R.drawable.img1,
R.drawable.img2,
R.drawable.img3,
R.drawable.img4,
R.drawable.img5
};
BannerAdapter mBannerAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mBanner = (ViewPager) findViewById(R.id.viewpager);
// 调用适配器
mBannerAdapter = new BannerAdapter(this,mImages);
mBanner.setAdapter(mBannerAdapter);
}
}
二 添加底部小圆点
2.1 修改activity_main.xml布局
<?xml version="1.0" encoding="utf-8"?>
<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"
tools:context=".MainActivity">
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="320dp"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignBottom="@id/viewpager"
android:background="#66000000"
android:gravity="center_horizontal"
android:orientation="vertical"
android:padding="5dp">
<TextView
android:id="@+id/tv_image_description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:text="图片描述"
android:textColor="#FFFFFF"
android:textSize="16sp"/>
<LinearLayout
android:id="@+id/pointgroup"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="3dp"
android:orientation="horizontal"/>
</LinearLayout>
</RelativeLayout>
2.2 制作小圆点颜色选择器
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/shape_bg_point_enable" android:state_enabled="true"/>
<item android:drawable="@drawable/shape_bg_point_disable" android:state_enabled="false"/>
</selector>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval" >
<corners android:radius="5dp" />
<solid android:color="@android:color/darker_gray" />
</shape>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval" >
<corners android:radius="5dp" />
<solid android:color="#FFFFFF" />
</shape>
2.3 将小圆点添加到LinearLayout容器中
// 将小圆点添加到LinearLayout容器中
private void initPointGroup() {
pointGroup = (LinearLayout) findViewById(R.id.pointgroup);
for (int i = 0; i < mImages.length; i++) {
// 制作底部小圆点
ImageView pointImage = new ImageView(this);
pointImage.setImageResource(R.drawable.selector_bg_point);
// 设置小圆点的布局参数
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(5, 5);
if (i > 0) {
params.leftMargin = 10;
pointImage.setEnabled(false);
} else {
// 第一个点,点亮
pointImage.setEnabled(true);
}
pointImage.setLayoutParams(params);
// 添加到容器里
pointGroup.addView(pointImage);
}
}
2.4 设置小圆点随着ViewPager切换移动
// 设置小圆点随着ViewPager切换移动
private void setListen() {
// 对ViewPager设置滑动监听
mBanner.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
int lastPosition;
@Override
public void onPageSelected(int position) {
// 设置图片描述 (也可以在viewpager的条目adapter中设置图片描述)
tv_image_description.setText(imageDescriptionArrays[position]);
// 设置前一页不选中
pointGroup.getChildAt(lastPosition).setEnabled(false);
// 设置当前页面选中
pointGroup.getChildAt(position).setEnabled(true);
// 替换位置
lastPosition = position;
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
}
2.5 在代码onCreate中调用
import android.os.Bundle;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private ViewPager mBanner;
private int[] mImages = {
R.drawable.img1,
R.drawable.img2,
R.drawable.img3,
R.drawable.img4,
R.drawable.img5
};
private String[] imageDescriptionArrays = new String[]{
"第一张图片的描述",
"第2张图片的描述",
"第3张图片的描述",
"第4张图片的描述",
"第5张图片的描述",
};
BannerAdapter mBannerAdapter;
LinearLayout pointGroup;
TextView tv_image_description;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mBanner = (ViewPager) findViewById(R.id.viewpager);
tv_image_description = (TextView) findViewById(R.id.tv_image_description);
// 默认显示第一张图片描述
tv_image_description.setText(imageDescriptionArrays[0]);
// 调用适配器
mBannerAdapter = new BannerAdapter(this, mImages);
mBanner.setAdapter(mBannerAdapter);
// 将小圆点添加到LinearLayout容器中
initPointGroup();
// 设置小圆点随着ViewPager切换移动
setListen();
}
// 设置小圆点随着ViewPager切换移动
private void setListen() {
// 对ViewPager设置滑动监听
mBanner.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
int lastPosition;
@Override
public void onPageSelected(int position) {
// 设置图片描述 (也可以在viewpager的条目adapter中设置图片描述)
tv_image_description.setText(imageDescriptionArrays[position]);
// 设置前一页不选中
pointGroup.getChildAt(lastPosition).setEnabled(false);
// 设置当前页面选中
pointGroup.getChildAt(position).setEnabled(true);
// 替换位置
lastPosition = position;
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
}
// 将小圆点添加到LinearLayout容器中
private void initPointGroup() {
pointGroup = (LinearLayout) findViewById(R.id.pointgroup);
for (int i = 0; i < mImages.length; i++) {
// 制作底部小圆点
ImageView pointImage = new ImageView(this);
pointImage.setImageResource(R.drawable.selector_bg_point);
// 设置小圆点的布局参数
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(5, 5);
if (i > 0) {
params.leftMargin = 10;
pointImage.setEnabled(false);
} else {
// 第一个点,点亮
pointImage.setEnabled(true);
}
pointImage.setLayoutParams(params);
// 添加到容器里
pointGroup.addView(pointImage);
}
}
}
三 无限滑动的ViewPager
3.1 修改viewpager的adapter中的getCount()和instantiateItem()
import android.content.Context;
import android.support.v4.view.PagerAdapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
/**
* Created by wxyass
*/
public class BannerAdapter extends PagerAdapter{
private LayoutInflater mInflater;
private int[] mImages;
private int mSize;
public BannerAdapter(Context context,int[] mImagesi) {
mInflater = LayoutInflater.from(context);
mImages = mImagesi;
mSize = mImagesi.length;
}
// 个数
@Override
public int getCount() {
return Short.MAX_VALUE;
}
/**
* 判断是否可以复用条目
*/
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
/**
* 初始化条目
*/
@Override
public Object instantiateItem(ViewGroup container, int position) {
int newPosition = position % mSize;
// 条目布局
View view = mInflater.inflate(R.layout.item, container, false);
ImageView imageView = (ImageView) view.findViewById(R.id.image);
imageView.setImageResource(mImages[newPosition]);
// 将图片控件添加到容器
container.addView(view);
// 返回
return view;
}
/**
* 销毁条目
*/
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
}
3.2 修改viewpager滑动监听OnPageChangeListener中的onPageSelected
// 设置小圆点随着ViewPager切换移动
private void setListen() {
// 对ViewPager设置滑动监听
mBanner.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
int lastPosition;
@Override
public void onPageSelected(int position) {
int newPosition = position % mImages.length;
// 设置图片描述 (也可以在viewpager的条目adapter中设置图片描述)
tv_image_description.setText(imageDescriptionArrays[newPosition]);
// 设置前一页不选中
pointGroup.getChildAt(lastPosition).setEnabled(false);
// 设置当前页面选中
pointGroup.getChildAt(newPosition).setEnabled(true);
// 替换位置
lastPosition = newPosition;
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
}
3.3 设置第一个条目从中间某个数开始
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mBanner = (ViewPager) findViewById(viewpager);
tv_image_description = (TextView) findViewById(R.id.tv_image_description);
// 默认显示第一张图片描述
tv_image_description.setText(imageDescriptionArrays[0]);
// 调用适配器
mBannerAdapter = new BannerAdapter(this, mImages);
mBanner.setAdapter(mBannerAdapter);
// 将小圆点添加到LinearLayout容器中
initPointGroup();
// 设置小圆点随着ViewPager切换移动
setListen();
// 设置从中间某个数开始, 左右都可以滑动
int item = Short.MAX_VALUE/2 - ((Short.MAX_VALUE/2) % mImages.length);
mBanner.setCurrentItem(item);
}
3.4 无限滑动基本完成, 附上MainActivity的代码
import android.os.Bundle;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import static com.wxyass.tpbanner.R.id.viewpager;
public class MainActivity extends AppCompatActivity {
private ViewPager mBanner;
private int[] mImages = {
R.drawable.img1,
R.drawable.img2,
R.drawable.img3,
R.drawable.img4,
R.drawable.img5
};
private String[] imageDescriptionArrays = new String[]{
"第一张图片的描述",
"第2张图片的描述",
"第3张图片的描述",
"第4张图片的描述",
"第5张图片的描述",
};
BannerAdapter mBannerAdapter;
LinearLayout pointGroup;
TextView tv_image_description;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mBanner = (ViewPager) findViewById(viewpager);
tv_image_description = (TextView) findViewById(R.id.tv_image_description);
// 默认显示第一张图片描述
tv_image_description.setText(imageDescriptionArrays[0]);
// 调用适配器
mBannerAdapter = new BannerAdapter(this, mImages);
mBanner.setAdapter(mBannerAdapter);
// 将小圆点添加到LinearLayout容器中
initPointGroup();
// 设置小圆点随着ViewPager切换移动
setListen();
// 设置从中间某个数开始, 左右都可以滑动
int item = Short.MAX_VALUE/2 - ((Short.MAX_VALUE/2) % mImages.length);
mBanner.setCurrentItem(item);
}
// 设置小圆点随着ViewPager切换移动
private void setListen() {
// 对ViewPager设置滑动监听
mBanner.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
int lastPosition;
@Override
public void onPageSelected(int position) {
int newPosition = position % mImages.length;
// 设置图片描述 (也可以在viewpager的条目adapter中设置图片描述)
tv_image_description.setText(imageDescriptionArrays[newPosition]);
// 设置前一页不选中
pointGroup.getChildAt(lastPosition).setEnabled(false);
// 设置当前页面选中
pointGroup.getChildAt(newPosition).setEnabled(true);
// 替换位置
lastPosition = newPosition;
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
}
// 将小圆点添加到LinearLayout容器中
private void initPointGroup() {
pointGroup = (LinearLayout) findViewById(R.id.pointgroup);
for (int i = 0; i < mImages.length; i++) {
// 制作底部小圆点
ImageView pointImage = new ImageView(this);
pointImage.setImageResource(R.drawable.selector_bg_point);
// 设置小圆点的布局参数
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(5, 5);
if (i > 0) {
params.leftMargin = 10;
pointImage.setEnabled(false);
} else {
// 第一个点,点亮
pointImage.setEnabled(true);
}
pointImage.setLayoutParams(params);
// 添加到容器里
pointGroup.addView(pointImage);
}
}
}
四 实现无限自动轮播的广告图
自动循环有多种实现方式:
1、开子线程 while true 循环
2、用handler 发送延时信息,实现循环
3、定时器:Timer
4、ColckManager
4.1 开子线程 while true 循环
private void setThreadAuto(){
new Thread(){
public void run() {
isRunning = true;
while(isRunning){
// 睡3秒
SystemClock.sleep(3000);
// 在主线程每次将ViewPager向右设置一次
runOnUiThread(new Runnable() {
@Override
public void run() {
// System.out.println("设置了新的位置");
mBanner.setCurrentItem(mBanner.getCurrentItem() + 1);
Log.d("wxyass",(mBanner.getCurrentItem() + 1)+"");
}
});
}
};
}.start();
}
/**
* Activity生命周期结束时终止定时,否则可能一直进行下去
*/
@Override
protected void onDestroy() {
super.onDestroy();
isRunning = false;
};
4.1.1 写好子线程,然后在onCreate总调用
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mBanner = (ViewPager) findViewById(viewpager);
tv_image_description = (TextView) findViewById(R.id.tv_image_description);
// 默认显示第一张图片描述
tv_image_description.setText(imageDescriptionArrays[0]);
// 调用适配器
mBannerAdapter = new BannerAdapter(this, mImages);
mBanner.setAdapter(mBannerAdapter);
// 将小圆点添加到LinearLayout容器中
initPointGroup();
// 设置小圆点随着ViewPager切换移动
setListen();
// 设置从中间某个数开始, 左右都可以滑动
int item = Short.MAX_VALUE/2 - ((Short.MAX_VALUE/2) % mImages.length);
mBanner.setCurrentItem(item);
// 设置子线程自动轮播
setThreadAuto();
}
4.2 用handler 发送延时信息,实现循环
/**
* 自动滑动的Handler
* 利用 Handler.sendEmptyMessageDelayed方法,实现定时滚动
*
*/
private Handler handler = new Handler(){
public void handleMessage(android.os.Message msg) {
//让ViewPager滑到下一页
mBanner.setCurrentItem(mBanner.getCurrentItem()+1);
//延时,循环调用handler
if(isRunning){
handler.sendEmptyMessageDelayed(0, 2000);
Log.d("wxyass",(mBanner.getCurrentItem() + 1)+"");
}
};
};
/**
* Activity生命周期结束时终止定时,否则可能一直进行下去
*/
@Override
protected void onDestroy() {
super.onDestroy();
isRunning = false;
};
4.2.1 写好Handle,然后在onCreate总调用
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mBanner = (ViewPager) findViewById(R.id.viewpager);
tv_image_description = (TextView) findViewById(R.id.tv_image_description);
// 默认显示第一张图片描述, 后面会随着滑动改变描述
tv_image_description.setText(imageDescriptionArrays[0]);
// 调用适配器
mBannerAdapter = new BannerAdapter(this, mImages);
mBanner.setAdapter(mBannerAdapter);
// 将小圆点添加到LinearLayout容器中
initPointGroup();
// 设置小圆点随着ViewPager切换移动
setListen();
// 设置从中间某个数开始, 左右都可以滑动
int item = Short.MAX_VALUE/2 - ((Short.MAX_VALUE/2) % mImages.length);
mBanner.setCurrentItem(item);
// 设置子线程自动轮播
//setThreadAuto();
// 设置handle自动轮播
isRunning = true;
handler.sendEmptyMessageDelayed(0, 2000);
}
4.3 定时器:Timer
private TimerTask mTimerTask = new TimerTask() {
@Override
public void run() {
if (isRunning) {
// 在主线程每次将ViewPager向右设置一次
runOnUiThread(new Runnable() {
@Override
public void run() {
// System.out.println("设置了新的位置");
mBanner.setCurrentItem(mBanner.getCurrentItem() + 1);
Log.d("wxyass", (mBanner.getCurrentItem() + 1) + "");
}
});
}
}
};
/**
* Activity生命周期结束时终止定时,否则可能一直进行下去
*/
@Override
protected void onDestroy() {
super.onDestroy();
isRunning = false;
if(mTimer!=null){
mTimer.cancel();
mTimer = null;
}
if(mTimerTask!=null){
mTimerTask.cancel();
mTimerTask = null;
}
};
4.3.1 写好Timer,然后在onCreate总调用
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mBanner = (ViewPager) findViewById(R.id.viewpager);
tv_image_description = (TextView) findViewById(R.id.tv_image_description);
// 默认显示第一张图片描述, 后面会随着滑动改变描述
tv_image_description.setText(imageDescriptionArrays[0]);
// 调用适配器
mBannerAdapter = new BannerAdapter(this, mImages);
mBanner.setAdapter(mBannerAdapter);
// 将小圆点添加到LinearLayout容器中
initPointGroup();
// 设置小圆点随着ViewPager切换移动
setListen();
// 设置从中间某个数开始, 左右都可以滑动
int item = Short.MAX_VALUE / 2 - ((Short.MAX_VALUE / 2) % mImages.length);
mBanner.setCurrentItem(item);
// 设置子线程自动轮播
//setThreadAuto();
// 设置handle自动轮播
/*isRunning = true;
handler.sendEmptyMessageDelayed(0, 2000);*/
// 设置定时器自动轮播
isRunning = true;
mTimer = new Timer();
mTimer.schedule(mTimerTask, 2000, 5000);//在2秒后每5秒执行一次定时器中的方法
}
五 设置触摸时不自动轮播
5.1 添加触摸监听,触摸时不自动轮播
// 设置触摸时不自动轮播
private void setTouchNoAuto() {
mBanner.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
int action = event.getAction();
if (action == MotionEvent.ACTION_DOWN|| action == MotionEvent.ACTION_MOVE) {
isRunning = false;
} else if (action == MotionEvent.ACTION_UP) {
isRunning = true;
}
return false;
}
});
}
5.2 在代码onCreate中调用
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mBanner = (ViewPager) findViewById(R.id.viewpager);
tv_image_description = (TextView) findViewById(R.id.tv_image_description);
// 默认显示第一张图片描述, 后面会随着滑动改变描述
tv_image_description.setText(imageDescriptionArrays[0]);
// 调用适配器
mBannerAdapter = new BannerAdapter(this, mImages);
mBanner.setAdapter(mBannerAdapter);
// 将小圆点添加到LinearLayout容器中
initPointGroup();
// 设置小圆点随着ViewPager切换移动
setListen();
// 设置从中间某个数开始, 左右都可以滑动
int item = Short.MAX_VALUE / 2 - ((Short.MAX_VALUE / 2) % mImages.length);
mBanner.setCurrentItem(item);
// 设置子线程自动轮播
//setThreadAuto();
// 设置handle自动轮播
/*isRunning = true;
handler.sendEmptyMessageDelayed(0, 2000);*/
// 设置定时器自动轮播
isRunning = true;
mTimer = new Timer();
mTimer.schedule(mTimerTask, 2000, 5000);//在2秒后每5秒执行一次定时器中的方法
// 设置触摸时不自动轮播
setTouchNoAuto();
}
六 项目源码
项目已经传到云端,有兴趣的可以下载看看.
项目下载