之前写过简单的轮播图,可以无限轮播,但是没有处理过轮播时的点击事件,最近遇到了,就又仔细研究了一下,现代码如下:
package com.example.test;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.content.Context;
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.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
public class LoginActivity extends Activity {
private ViewPager viewpager;
private Context context = LoginActivity.this;
private MyAdapter myAdapter;
private RunnableTask runnableTask = new RunnableTask();
// 准备要显示的图片资源
private int[] imageIdArray = { R.drawable.shang_nine, R.drawable.shang_ten,
R.drawable.tu_gangaoyou };
// 准备title
private String[] titleArray = { "aaa", "bbb", "ccc" };
// 轮播图显示的当前页
private int currentPosition =Integer.MAX_VALUE/2-((Integer.MAX_VALUE/2)%imageIdArray.length);
int middle=Integer.MAX_VALUE/2-(Integer.MAX_VALUE/2%imageIdArray.length);
/**
* 放置点的集合
*/
private List<View> viewList = new ArrayList<View>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.item);
// 找到ViewPager控件
viewpager = (ViewPager) findViewById(R.id.vp);
}
@Override
protected void onResume() {
super.onResume();
// ★图片滚动的入口,为什么写在onResume方法里呢?
// ★因为当view失去焦点时,停止滚动,在重新获取焦点时要继续滚动起来
// ★如果写在onCreate方法里,只是activity第一次创建时才会滚动,一但停止滚动,再次获取焦点也不会滚动了
startRoll();
viewpager.setOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageSelected(int arg0) {
//★★★★★ 当轮播图显示当前页时,一定要把currentPosition设为arg0,
//★★★★★ 否则,当你用手指滑动轮播图时,放手后,轮播图显示的下一张页面是并不是当前显示页面的下一页
// ★★★★★而是,他自己根据3秒钟计算得到的下一页
currentPosition = arg0;
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
// TODO Auto-generated method stub
}
@Override
public void onPageScrollStateChanged(int arg0) {
// TODO Auto-generated method stub
}
});
}
/**
* 让轮播图viewpager滚动起来
*/
public void startRoll() {
// 滚动viewpager
if (myAdapter == null) {
// 1.第一次初始化适配器
myAdapter = new MyAdapter();
viewpager.setAdapter(myAdapter);
viewpager.setCurrentItem(currentPosition);
} else {// 8.第二次,只需要通知适配器数据发生了变化,要刷新Ui
myAdapter.notifyDataSetChanged();
}
// 2.发送一个延时的消息,3秒后执行runnableTask类里run方法里的操作
// ★(为什么执行的是runnableTask,而不是handleMessage呢?这里涉及到handler消息机制源码解析)
handler.postDelayed(runnableTask, 3000);
}
class RunnableTask implements Runnable {
@Override
public void run() {
// 3.变化轮播图当前要显示的页面位置,递增1,为了不使这个数字递增超过轮播图 图片的个数,取余数
currentPosition = currentPosition + 1;
// 4.发送消息给主线程的handler
handler.obtainMessage().sendToTarget();
}
}
private Handler handler = new Handler() {
// 5.接收并处理run方法发来的消息
public void handleMessage(android.os.Message msg) {
// 6.viewpager设置新的当前页
viewpager.setCurrentItem(currentPosition);
// 7.继续执行startRoll方法,成为一个循环
startRoll();
}
};
/**
* ★当手指按住轮播图不动时,轮播图停止滚动;当点击轮播图时,跳转到相关界面
*/
public void onTouchViewPager(View view, final int position) {
// 给图片注册触摸事件监听器
view.setOnTouchListener(new OnTouchListener() {
private long downTime;
private int downX;
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:// 按下去时,记录按下的坐标和时间,用于判断是否是点击事件
handler.removeCallbacksAndMessages(null);// 手指按下时,取消所有事件,即轮播图不在滚动了
downX = (int) event.getX();
downTime = System.currentTimeMillis();
break;
case MotionEvent.ACTION_UP:// 抬起手指时,判断落下抬起的时间差和坐标,符合以下条件为点击
// Toast.makeText(context, "手指抬起了", 0).show();
if (System.currentTimeMillis() - downTime < 500
&& Math.abs(downX - event.getX()) < 30) {// ★考虑到手按下和抬起时的坐标不可能完全重合,这里给出30的坐标偏差
// 点击事件被触发
Toast.makeText(context,
"这里就不弹出对应页面了,您打开的是第" + position + "张图片", 0)
.show();
}
startRoll();
break;
case MotionEvent.ACTION_CANCEL:
// ★写这个的目的为了让用户在手指滑动完图片后,能够让轮播图继续自动滚动
startRoll();
break;
}
return true;
}
});
}
@Override
protected void onPause() {
super.onPause();
// 移除所有的任务,即:view失去焦点时,停止轮播图的滚动
handler.removeCallbacksAndMessages(null);
}
/**
* 处理小点点,使得小点点随着轮播图的位置而改变颜色
*/
private void initDot(LinearLayout dots_ll, int position) {
// 必须每次进来清除线性布局里的所有小点点,不然,每次切换回页面,都运行initDot方法,会一直累加小点点,每次增加8个点
dots_ll.removeAllViews();
viewList.clear();
position=position%imageIdArray.length;
// 遍历轮播图片的集合,每遍历一个,new一个view,给这个view设置背景图片,
// 给包含小点点的父亲现形布局设置参数,设置间距,线性布局添加这些点,viewList也添加小点点
for (int i = 0; i < imageIdArray.length; i++) {
View view = new View(context);
if (i == position) {
view.setBackgroundResource(R.drawable.dot_focus);
} else {
view.setBackgroundResource(R.drawable.dot_normal);
}
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
6,
6);
view.setLayoutParams(layoutParams);
layoutParams.setMargins(5, 0, 5, 0);
dots_ll.addView(view);
viewList.add(view);
}
}
/**
* 适配器,要重写下面四个方法
*/
class MyAdapter extends PagerAdapter {
@Override
public boolean isViewFromObject(View arg0, Object arg1) {
return arg0 == arg1;
}
@Override
public int getCount() {
return Integer.MAX_VALUE;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
View view = View.inflate(context, R.layout.layout_roll_view, null);
ImageView imageView = (ImageView) view.findViewById(R.id.image);
imageView.setImageResource(imageIdArray[position%titleArray.length]);
TextView title = (TextView) view.findViewById(R.id.top_news_title);
title.setText(titleArray[position%titleArray.length]);
LinearLayout dots_ll = (LinearLayout) view
.findViewById(R.id.dots_ll);
// 处理小点点的操作
initDot(dots_ll, position);
// onTouchViewPager方法一定要写在instantiateItem内部,表示触摸的是当前位置的页面
onTouchViewPager(view, position);
// ★★★这句话很重要!!!别忘了写!!!
((ViewPager) container).addView(view);
return view;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
// ★★★这句话很重要!!!别忘了写!!!
((ViewPager) container).removeView((View) object);
}
}
}
对应的布局文件如下:
<?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:orientation="vertical" >
<android.support.v4.view.ViewPager
android:id="@+id/vp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
</android.support.v4.view.ViewPager>
</LinearLayout>
当中单个条目的布局如下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="185dp" >
<!-- 放置轮播图片位置 -->
<ImageView
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitXY" >
</ImageView>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="30dp"
android:layout_alignParentBottom="true"
android:background="#88000000"
android:gravity="center_vertical"
android:orientation="horizontal" >
<!-- 放置图片标题的位置 -->
<TextView
android:id="@+id/top_news_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="8dp"
android:layout_weight="1"
android:singleLine="true"
android:text="图片标题"
android:textColor="#F6F6F6" />
<!-- 放置图片中选中点的位置 -->
<LinearLayout
android:id="@+id/dots_ll"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="5dp"
android:gravity="center"
android:orientation="horizontal" />
</LinearLayout>
</RelativeLayout>
如果是网络加载数据,相对来说,上面的代码只需要在instanceItemView中的iv设置对应的网络资源文件就好