在做这个效果的时候,我第一时间看了网上的轮播方式,发现问题很多,有的人在代码里大量的判断手动滑动和自动滑动的状态改变,有的人的轮播是定义了一个很大的Int值,通过顺序播放相同的图片来实现的伪轮播,看过这些代码感觉并不满意,所以尝试自己实现。
在轮播更新UI的时候,我尝试了Thread+handler,handler.postdelay,和timer+timertask+handler的方式,前两种方式都会出现一些小Bug,并且不利于功能扩展,读者可自行尝试,所以我采用了第三种方式。
在解决手动滑动和自动滑动的上,其实根本不用设置什么标志位进行大量的判断,这是一个思维误区,因为我们根本不需要解决这两者之间的冲突,我们只需要关注当前页面是不是改变成功了,当前页面是第几个就可以了。所以我们只需要判断onPageScrollStateChanged的state为2的时候,这个页面的position就可以解决上述问题。
如果要给自己的轮播增加一些文字描述也非常的简单,具体可以看我下面的代码分析。
效果图:
直接看核心代码:
MainActivity.java
public class MainActivity extends AppCompatActivity {
private Context ctx;
//viewpager初始化
private ViewPager viewPager;
private List<View> list;
private LPagerAdapter adapter;
//轮播控制
private Handler handler;
private Timer timer;
private TimerTask task;
private int mPosition;
//轮播内容
private LinearLayout point_container;
private ImageView[] imgs;
private List<ImageTip> tips;
private TextView tip1;
private TextView tip2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager = (ViewPager) findViewById(R.id.viewpager);
tip1 = (TextView) findViewById(R.id.tv_tip1);
tip2 = (TextView) findViewById(R.id.tv_tip2);
ctx = this;
initdata();
initpoint();
initTip();
//自定义adapter
adapter = new LPagerAdapter(ctx, list, new LPagerImgClickListener() {
@Override
public void ImgClick(int position) {
Toast.makeText(ctx, "点击了" + mPosition, Toast.LENGTH_SHORT).show();
Intent intent = new Intent(ctx, SecondActivity.class);
intent.putExtra("position", position);
startActivity(intent);
}
});
//第一种动画
// viewPager.setPageTransformer(true, new ZoomOutPageTransformer());
//第二种动画
viewPager.setPageTransformer(true,new DepthPageTransformer());
viewPager.setAdapter(adapter);
//监听页面的改变
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
// Log.i("LHD", "onPageScrolled" + " positionOffset:" + positionOffset + " positionOffsetPixels:" + positionOffsetPixels);
}
@Override
public void onPageSelected(final int position) {
// Log.i("LHD", "onPageSelected" + position);
}
@Override
public void onPageScrollStateChanged(int state) {
// Log.i("LHD", "onPageScrollStateChanged:" + state);
if (state == 2) {//图片切换成功的状态为2
mPosition = viewPager.getCurrentItem();
Log.i("LHD", "当前页是:" + mPosition);
for (int i = 0; i < list.size(); i++) {
//设置所有原点
imgs[i].setImageResource(R.drawable.point1);
}
//设置当前页的小圆点图片和文字信息
imgs[mPosition].setImageResource(R.drawable.point2);
tip1.setText(tips.get(mPosition).getTip1());
tip2.setText(tips.get(mPosition).getTip2());
}
}
});
imgPlay();
}
private void imgPlay() {
//循环播放
task = new TimerTask() {
@Override
public void run() {
Message msg = new Message();
msg.what = 1;
handler.sendMessage(msg);
}
};
timer = new Timer();
timer.schedule(task, 3000, 3000);
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what == 1) {
if (mPosition == (list.size() - 1)) {
viewPager.setCurrentItem(0, true);
} else {
Log.i("LHD", "bbbb: " + mPosition + "当前的进程ID: " + Thread.currentThread().getId());
viewPager.setCurrentItem(mPosition + 1, true);
Log.i("LHD", "cccc: " + mPosition);
}
}
}
};
}
private void imgStop() {
handler.removeMessages(1);
timer.cancel();
task.cancel();
}
private void initdata() {
list = new ArrayList<View>();
ImageView iv = new ImageView(ctx);
ImageView iv2 = new ImageView(ctx);
ImageView iv3 = new ImageView(ctx);
ImageView iv4 = new ImageView(ctx);
ImageView iv5 = new ImageView(ctx);
ImageView iv6 = new ImageView(ctx);
iv.setImageResource(R.drawable.image3);
iv2.setImageResource(R.drawable.image4);
iv3.setImageResource(R.drawable.image5);
iv4.setImageResource(R.drawable.image6);
iv5.setImageResource(R.drawable.image7);
iv6.setImageResource(R.drawable.image8);
list.add(iv);
list.add(iv2);
list.add(iv3);
list.add(iv4);
list.add(iv5);
list.add(iv6);
imgs = new ImageView[list.size()];
}
private void initpoint() {
point_container = (LinearLayout) findViewById(R.id.point_container);
for (int i = 0; i < list.size(); i++) {
ImageView imageView = new ImageView(ctx);
imageView.setImageResource(R.drawable.point1);
//对布局控件添加相对属性
LinearLayout.LayoutParams param = new LinearLayout.LayoutParams(
20,
20);
//添加规则,示例 靠父控件最右边
param.setMargins(10, 0, 0, 0);
Log.i("LHD", "添加小圆点:" + list.size());
imgs[i] = imageView;//添加到图片数组
point_container.addView(imageView, param);
imgs[0].setImageResource(R.drawable.point2);
}
}
private void initTip() {
tips = new ArrayList<ImageTip>();
tips.add(new ImageTip("山治:我要寻找all bule", "2016/6/23"));
tips.add(new ImageTip("弗兰奇:我要飞上天", "2016/6/24"));
tips.add(new ImageTip("乌索普:我要成为勇敢的海上战士", "2016/6/25"));
tips.add(new ImageTip("罗宾:我要寻找历史原文", "2016/6/26"));
tips.add(new ImageTip("娜美:我要环绕世界一周", "2016/6/27"));
tips.add(new ImageTip("路飞:我要成为海贼王!", "2016/6/28"));
tip1.setText(tips.get(0).getTip1());
tip2.setText(tips.get(0).getTip2());
}
@Override
protected void onPause() {
super.onPause();
Log.i("LHD", "onPause");
//保存当前页位置
mPosition = viewPager.getCurrentItem();
//停止轮播
imgStop();
}
@Override
protected void onRestart() {
super.onRestart();
Log.i("LHD", "onRestart");
//重新启动轮播
imgPlay();
}
}
分析:
imgPlay()
这个函数就是用来控制图片轮播的函数,
在这个函数里,使用了Timer+TimerTask+handler的方式来更新UI。
imgStop()
这个函数用来取消图片轮播,当按下HOME键或者返回键的时候需要将动画取消,再次启动Activity的时候再恢复。
initdata()
将需要轮播的图片存放在一个List里,并且定义了一个存放图片的数组。
initpoint()
根据图片数量来添加小圆点
initTip()
图片下面文字的初始化
重写了onPause方法和onRestart方法,在onPause方法里保存图片位置,停止动画,在onRestart方法里重启动画。
接下来看ViewPager的适配器:
LPagerAdapter.java
/** * Created by LHD on 2016/6/29. */
public class LPagerAdapter extends PagerAdapter {
private Context ctx;
private List<View> mlist;
private LPagerImgClickListener mlistener;
public LPagerAdapter(Context ctx, List<View> mlist, LPagerImgClickListener listener) {
this.ctx = ctx;
this.mlist = mlist;
this.mlistener = listener;
}
@Override
public int getCount() {
return mlist.size();
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public Object instantiateItem(ViewGroup container, final int position) {
container.addView(mlist.get(position));
mlist.get(position).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Toast.makeText(ctx, "点击了" + position, Toast.LENGTH_SHORT).show();
if (mlistener != null) {
mlistener.ImgClick(position);
}
}
});
return mlist.get(position);
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView(mlist.get(position));
}
}
和普通的viewpager适配器没有区别,只是增加了一个监听,当点击图片的时候,调用mlistener.ImgClick(position);
接口:
LPagerImgClickListener.java
public interface LPagerImgClickListener {
public void ImgClick(int position);
}
另外提供了两种viewpager的动画,这两种动画都是谷歌官方提供,可以根据需要修改里面的参数。
动画1:
DepthPageTransformer.java
/** * Created by LHD on 2016/6/30. */
public class DepthPageTransformer implements ViewPager.PageTransformer{
private static float MIN_SCALE = 0.75f;
@SuppressLint("NewApi")
@Override
public void transformPage(View view, float position) {
int pageWidth = view.getWidth();
if (position < -1) { // [-Infinity,-1)
// This page is way off-screen to the left.
view.setAlpha(0);
} else if (position <= 0) { // [-1,0]
// Use the default slide transition when
// moving to the left page
view.setAlpha(1);
view.setTranslationX(0);
view.setScaleX(1);
view.setScaleY(1);
} else if (position <= 1) { // (0,1]
// Fade the page out.
view.setAlpha(1 - position);
// Counteract the default slide transition
view.setTranslationX(pageWidth * -position);
// Scale the page down (between MIN_SCALE and 1)
float scaleFactor = MIN_SCALE + (1 - MIN_SCALE)
* (1 - Math.abs(position));
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
} else { // (1,+Infinity]
// This page is way off-screen to the right.
view.setAlpha(0);
}
}
}
动画2:
ZoomOutPageTransformer.java
package com.example.eventbus.imagecarousellhd;
import android.support.v4.view.ViewPager;
import android.view.View;
/** * Created by LHD on 2016/6/30. */
public class ZoomOutPageTransformer implements ViewPager.PageTransformer{
private static float MIN_SCALE = 0.85f;
private static float MIN_ALPHA = 0.5f;
@Override
public void transformPage(View view, float position) {
int pageWidth = view.getWidth();
int pageHeight = view.getHeight();
if (position < -1) { // [-Infinity,-1)
// This page is way off-screen to the left.
view.setAlpha(0);
} else if (position <= 1) { // [-1,1]
// Modify the default slide transition to
// shrink the page as well
float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position));
float vertMargin = pageHeight * (1 - scaleFactor) / 2;
float horzMargin = pageWidth * (1 - scaleFactor) / 2;
if (position < 0) {
view.setTranslationX(horzMargin - vertMargin / 2);
} else {
view.setTranslationX(-horzMargin + vertMargin / 2);
}
// Scale the page down (between MIN_SCALE and 1)
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
// Fade the page relative to its size.
view.setAlpha(MIN_ALPHA + (scaleFactor - MIN_SCALE)
/ (1 - MIN_SCALE) * (1 - MIN_ALPHA));
} else { // (1,+Infinity]
// This page is way off-screen to the right.
view.setAlpha(0);
}
}
}
代码下载:
http://dl.download.csdn.net/down11/20160630/0d6a1d49d94dc37ad2d036876956b959.zip?response-content-disposition=attachment%3Bfilename%3D%22ImageCarouselLHD.zip%22&OSSAccessKeyId=9q6nvzoJGowBj4q1&Expires=1467270036&Signature=9MhZGsUC9qiLVG7y2YSWjj1EbIo%3D