在上一次的代码中加入了无限循环的功能,这一次我详细讲解一下我的逻辑。
1.实现添加imageview 进入viewpager
a.首先写一个CusViewpage继承自ViewPager
public class CusViewpage extends ViewPager{
public CusViewpage(Context context, AttributeSet attrs) {
super(context, attrs);
}
}
b.定义变量 List<ImageView> viewPagerImage和展示小点的LinearLayout
private List<ImageView> viewPagerImage;
private LinearLayout dotslayout;
c.自定义OnPageChangListener,和PagerAdapter,传说ViewPager如果不传入这个两个东西就会报错,我也没试过额,有兴趣的大虾们试试后告诉我一声哈,
/**
*
* @author 任爱民
* 自定义的OnPageChangeListener
*/
public class ImagePagerChangeListener implements OnPageChangeListener {
/**
* 1是手指滑动
* 2是结束滑动
* 0是开始滑动
*/
public void onPageScrollStateChanged(int n) {
}
public void onPageScrolled(int arg0, float arg1, int arg2) {
// TODO Auto-generated method stub
}
public void onPageSelected(int position) {
}
}
/**
*
* @author 任爱民
* 自定义的PagerAdapter
*/
public class ImagePagerAdapter extends PagerAdapter {
private List<ImageView> list;
public ImagePagerAdapter(List<ImageView> list) {
this.list = list;
}
@Override
public void destroyItem(View view, int index, Object arg2) {
((ViewPager) view).removeView(list.get(index));
}
@Override
public void finishUpdate(View arg0) {
// TODO Auto-generated method stub
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return list.size();
}
@Override
public Object instantiateItem(View view, int index) {
((ViewPager) view).addView(list.get(index), 0);
return list.get(index);
}
@Override
public boolean isViewFromObject(View view, Object object) {
// TODO Auto-generated method stub
return view == (object);
}
@Override
public void restoreState(Parcelable arg0, ClassLoader arg1) {
// TODO Auto-generated method stub
}
@Override
public Parcelable saveState() {
// TODO Auto-generated method stub
return null;
}
@Override
public void startUpdate(View arg0) {
// TODO Auto-generated method stub
}
}
d,init()方法初始化数据
public void init(List<ImageView> viewPagerImage,LinearLayout dotslayout){
this.viewPagerImage = viewPagerImage;
this.dotslayout = dotslayout;
initImagePager();
if(dotslayout != null)
initDots();
}
/**
* 初始化viewPage
*/
private void initImagePager() {
if(viewPagerImage != null){
this.setImageStyle();
this.setAdapter(new ImagePagerAdapter(viewPagerImage));
this.setOnPageChangeListener(new ImagePagerChangeListener());
}
}
/**
* 设置图片的一些风格
*/
public void setImageStyle(){
android.widget.FrameLayout.LayoutParams viewparams = new android.widget.FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
for(ImageView imagaview:viewPagerImage){
imagaview.setLayoutParams(viewparams);
//允许拉伸,填充屏幕
imagaview.setScaleType(ScaleType.FIT_XY);
}
}
/**
* 添加小点
*/
// 主页面切换的小点资源id
private int[] imagedotsid = { R.drawable.dotwhite, R.drawable.dotorange };
private void initDots() {
//在这里为什么dots[]的长度要减2,后面我会详细说明。
dots = new ImageView[viewPagerImage.size() - 2];
for (int i = 0; i < dots.length; i++) {
dots[i] = new ImageView(getContext());
dots[i].setLayoutParams(new android.widget.FrameLayout.LayoutParams(15, 15));
if (i == 0)
dots[i].setImageResource(imagedotsid[1]);
else
dots[i].setImageResource(imagedotsid[0]);
TextView tv = new TextView(getContext());
tv.setLayoutParams(new android.widget.FrameLayout.LayoutParams(10, 30));
dotslayout.addView(dots[i]);
dotslayout.addView(tv);
}
}
现在已经可以显示出PagerView了,后面我们添加图片的自动循环切换
2.现在我们实现图片的手动循环切换,并且添加点的改变
先说一下无限循环的简单逻辑, 先看图,看颜色。
如图所示,如果我要无限循环四张图片,那么我需要添加6张图片进去,第一张是要显示的第四张图片,最后一张是需要展示的第一张图片,初始化时实际是显示的第二张图片,这样我们才可以向前滑动到前一张即第四张图片,当滑动到此图时且动作完毕时,立即切换到最后一张的前一张图片,位置是list.size()-2。前后一直滑动的道理也是一样的。
其实这就是一个简单的循环逻辑,为了保留滑动动作,才加入了最前后两张图片循环。
所以我们需要传入多的两张图片,之前设置点的数量才是list.size() - 2;
所以在初始化init()方法中时,我们需要将图片的显示位置设为1
setCurrentItem(1, false);
在自定义的切换事件中,我们加入上面的逻辑代码
public class ImagePagerChangeListener implements OnPageChangeListener {
/**
* 1是手指滑动
* 2是结束滑动
* 0是开始滑动
*/
public void onPageScrollStateChanged(int n) {
//这里是加入的代码
if(n == 0){
if(dotint == 0){
setCurrentItem(viewPagerImage.size()-2, false);
}else if(dotint == viewPagerImage.size()-1){
setCurrentItem(1, false);
}
}
}
a,实现改变的点的方法。
/**
* 改变小点
*/
// 记录现在的原点位置
private int dotint = 0;
//记录原点应该显示的位置
private int dotprint = 0 ;
// 图片的位置
private static int imagemoveid = 1;
private void changedot(int dotintnew) {
if(dots != null){
dots[dotprint].setImageResource(imagedotsid[0]);
if(dotintnew == 0){
dotprint = viewPagerImage.size() - 3;
}else if(dotintnew == viewPagerImage.size() - 1){
dotprint = 0;
}else{
dotprint = dotintnew - 1;
}
dots[dotprint].setImageResource(imagedotsid[1]);
imagemoveid = dotintnew;
dotint = dotintnew;
}
}
b.在切换图片时,会响应OnPageChangeListener事件,所以我们在自定义的OnPageChangeListener中加入改变小点的方法
public void onPageSelected(int position) {
// 改变小点
if(dotslayout != null)
changedot(position);
}
现在我们已经实现了手动无线循环切换的pagerview,
3.实现自动无限切换图片
这里我先说明一个问题,我在实现这个功能的时候,开始是用的定时器Timer,过0.4秒就滑动一次。实现以后,在配合手动切换时,会出现,手动滑动一张图片后,立马就会自动切换到下一张图,这样的体验不是很好。后面我又改为线程去解决这个问题,每次手滑以后就重设线程,并设置0.1秒检测一次时候是否正在滑动.
a.创建滑动的线程
/**
* 自动切换 创建线程
*/
public boolean isMove = true;
private Handler switcherHandler;
//自动切换的时间
private int timelong = 40;
//消息int
private int message = 0x123;
//给线程唯一性加锁
public static boolean isHaveLoop = true;
private void startLoop() {
new Thread() {
public void run() {
//表示已经有Loop开始运行
isHaveLoop = true;
try {// 如果移动了则休眠四秒钟
//将检测ismove提高到0.1秒检测一次
int time = 0;
while (isMove) {
Thread.sleep(100);
if(time++ >= timelong){
switcherHandler.sendEmptyMessage(message);
time = 0;
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
//表示Loop运行结束
isHaveLoop = false;
};
}.start();
}
b.在init()初始化时,启动线程,并且在主线程中改变PagerView的位置
/**
* 设置广告图片切换的计时器
*/
private void setSwitcherImage() {
switcherHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what == message && isMove) {
int m = ++imagemoveid % (viewPagerImage.size());
setCurrentItem(m);
}
super.handleMessage(msg);
}
};
startLoop();
}
在init()中执行这个方法。
setSwitcherImage();
c.重写onTouch()方法,检测触控事件,每次手动滑动时,都应该重开线程。
/**
* 检测是否手势滑动
* 如果有收手势滑动则取消Loop线程,滑动结束后重新建立Loop线程
*/
@Override
public boolean onTouchEvent(MotionEvent arg0) {
if(arg0.getAction() == MotionEvent.ACTION_DOWN||arg0.getAction()==arg0.ACTION_MOVE){
isMove = false;
}else if(arg0.getAction() == MotionEvent.ACTION_UP){
isMove =true;
//如果不存在loop后,可以再次创建loop
if(!isHaveLoop){
startLoop();
}
}else{
isMove = true;
if(!isHaveLoop){
startLoop();
}
}
return super.onTouchEvent(arg0);
}
4.测试。
我们放入布局文件
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<aimin.myviewpager.CusViewpage
android:id="@+id/cusviewpage"
android:layout_width="match_parent"
android:layout_height="300dp" >
</aimin.myviewpager.CusViewpage>
<LinearLayout
android:id="@+id/dots"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="280dp"
android:layout_marginRight="30dp"
android:gravity="right"
android:orientation="horizontal" >
</LinearLayout>
</RelativeLayout>
在主activity中初始化
import java.util.ArrayList;
import java.util.List;
import aimin.myviewpager.CusViewpage;
import android.app.Activity;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.LinearLayout;
public class MainActivity extends Activity {
private CusViewpage imageSwitchertitle;
private LinearLayout dotLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageSwitchertitle = (CusViewpage) findViewById(R.id.cusviewpage);
dotLayout = (LinearLayout) findViewById(R.id.dots);
imageSwitchertitle.init(getTestImageView(),dotLayout);
}
/**
*
* @return测试用的List<ImageView>
*/
public List<ImageView> getTestImageView(){
List<ImageView> imageview = new ArrayList<ImageView>();
ImageView imageviewfourq = new ImageView(this);
imageviewfourq.setImageResource(R.drawable.title_four);
ImageView imageviewone = new ImageView(this);
imageviewone.setImageResource(R.drawable.title_one);
ImageView imageviewtwo = new ImageView(this);
imageviewtwo.setImageResource(R.drawable.title_two);
ImageView imageviewthree = new ImageView(this);
imageviewthree.setImageResource(R.drawable.title_three);
ImageView imageviewfour = new ImageView(this);
imageviewfour.setImageResource(R.drawable.title_four);
ImageView imageviewoneh = new ImageView(this);
imageviewoneh.setImageResource(R.drawable.title_one);
imageview.add(imageviewfourq);
imageview.add(imageviewone);
imageview.add(imageviewtwo);
imageview.add(imageviewthree);
imageview.add(imageviewfour);
imageview.add(imageviewoneh);
return imageview;
}
/**
* 初始化CusViewpage
*/
}
运行截图:
缺陷:
1.但是依然有不足之处,init方法初始化List<ImageView> viewPagerImage时,需要传入一定顺序的Imageview(即在最前和最后加入最后和最前的脱)。但这并不是我们想要的,我尝试过在init()中,将List<ImageView> viewPagerImage添加上首尾图片,但只能添加引用,在VIewpager换图时报错,ImageView又不能被复制对象(其实也可以做到复制,需要重写ImagerVIew的copy()方法吧,我觉得太麻烦了,有兴趣的同学可以试试),我只好在传入时先构造了一定顺序的list。
2.不能动态添加图片.