您的位置:首页 > 其它

ViewPager实现图片轮播,下方带小点显示当前位置

2016-06-07 11:52 721 查看
先来张效果图


还是从布局文件开始说,使用到的布局文件就一个content_main.xml,因为小点图片是覆盖在大图片的上面的,所以这里要用Framelayout,包含了两个linearLayout,一个放置大图片,一个放置小图片的,这里在代码中动态添加,具体代码如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:showIn="@layout/activity_main" tools:context=".MainActivity">

<TextView
android:id="@+id/test_hello"
android:text="点击切换" android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/newsHead_layout"/>
<FrameLayout
android:id="@+id/newsHead_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<LinearLayout
android:id="@+id/view_pager_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">

</LinearLayout>

<LinearLayout
android:id="@+id/news_headView_dot"
android:layout_width="wrap_content"
android:layout_height="20dp"
android:layout_gravity="bottom|right"
android:layout_marginRight="10dp"
android:gravity="center"
android:orientation="horizontal"></LinearLayout>
</FrameLayout>
</RelativeLayout>
对应的类为MainActivity,具体代码如下:

public class MainActivity extends AppCompatActivity implements View.OnClickListener,
ListView.OnItemClickListener{
private ImageHandler handler = new ImageHandler(new WeakReference<MainActivity>(this));
private ViewPager vp;
private List<View> ivs;//大图集合
private List<ImageView> dotIvs;//小点集合
private int currentPosition = 0;// 记录当前图片的位置

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.content_main);
ivs = new ArrayList<View>();
dotIvs = new ArrayList<ImageView>();
initHeadView();
TextView tvHello = (TextView)findViewById(R.id.test_hello);
tvHello.setOnClickListener(this);

}
private void initHeadView() {
LinearLayout pagerLayout = (LinearLayout) findViewById(R.id.view_pager_content);
vp = new ViewPager(this);
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
//设置viewpager的宽高,高是宽度的特定比例,我的手机宽是720的,做了下适配
vp.setLayoutParams(new LinearLayout.LayoutParams(dm.widthPixels, dm.widthPixels * 462 / 720));
pagerLayout.addView(vp);

ivs.clear();
dotIvs.clear();
//这里有三张图片,所以i<3
for (int i = 0; i < 3; i++) {
ImageView iv = new ImageView(this);
iv.setId(i);// 处理其点击事件
iv.setOnClickListener(this);

iv.setScaleType(ImageView.ScaleType.FIT_XY);
// manager.bindBitmap(iv, mainNews.get(i).getPicUrl());
// iv.setBackgroundResource(R.id.main_logo);
if (i == 0) {
iv.setImageResource(R.drawable.rolling1);
} else if (i == 1) {
iv.setImageResource(R.drawable.rolling2);
} else if (i == 2) {
iv.setImageResource(R.drawable.rolling3);
}
ivs.add(iv);// 加入大图集合
ImageView dotIv = new ImageView(this);
dotIv.setImageResource(R.drawable.s_banner_unselect);
dotIv.setPadding(5, 0, 5, 0);//设置小点的间距left top right bottom
dotIvs.add(dotIv);// 加入小点集合
}

//小点所在的linearlayout
LinearLayout dotsLl = (LinearLayout) findViewById(R.id.news_headView_dot);
dotsLl.removeAllViews();

for (int i = 0; i < dotIvs.size(); i++) {
dotsLl.addView(dotIvs.get(i));
}
// TODO Auto-generated method stub
if (ivs.size() == 0) {
return;
}
vp.setAdapter(new FVpAdapter());
//        vp.setCurrentItem(Integer.MAX_VALUE/2);//默认在中间,使用户看不到边界
//开始轮播效果
handler.sendEmptyMessageDelayed(ImageHandler.MSG_UPDATE_IMAGE, ImageHandler.MSG_DELAY);
vp.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {

@Override
public void onPageSelected(int arg0) {
// TODO Auto-generated method stub
//				 Toast.makeText(MainSlidingMenuActivity.this, "这是第" + arg0 % dotIvs.size() + "张图片", Toast.LENGTH_SHORT).show();
currentPosition = arg0;
handler.sendMessage(Message.obtain(handler, ImageHandler.MSG_PAGE_CHANGED, arg0, 0));
//
selector(currentPosition);
}
//覆写该方法实现轮播效果的暂停和恢复
@Override
public void onPageScrollStateChanged(int arg0) {
switch (arg0) {
case ViewPager.SCROLL_STATE_DRAGGING:
handler.sendEmptyMessage(ImageHandler.MSG_KEEP_SILENT);
break;
case ViewPager.SCROLL_STATE_IDLE:
handler.sendEmptyMessageDelayed(ImageHandler.MSG_UPDATE_IMAGE, ImageHandler.MSG_DELAY);
break;
default:
break;
}

}

@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
// TODO Auto-generated method stub

}

});

// 更改viewPager的属性
try {
Field mScroller;
mScroller = ViewPager.class.getDeclaredField("mScroller");
mScroller.setAccessible(true);

FixedSpeedScroller scroller = new FixedSpeedScroller(
vp.getContext());// 调用这个构造方法即可
// scroller.setFixedDuration(5000);
mScroller.set(vp, scroller);
} catch (NoSuchFieldException e) {
} catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {
}

vp.setCurrentItem(currentPosition);// 从这个位置开始前后都可以无限滑动
vp.getNextFocusUpId();
selector(currentPosition);

}
//选择小点的方法
private void selector(int index) {
if (dotIvs.size() == 0) {
return;

}
index = index % dotIvs.size();
int len = dotIvs.size();
for (int i = 0; i < len; i++) {
if (index == i) {
dotIvs.get(i).setImageResource(R.drawable.s_banner_select);
} else {
dotIvs.get(i).setImageResource(R.drawable.s_banner_unselect);
}
}
}

@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.test_hello:
Toast.makeText(MainActivity.this, "hello", Toast.LENGTH_SHORT).show();
int count = ivs.size();
//设置点击切换,如果到头则重新开始
int item = currentPosition+1 == count? 0 : currentPosition+1;
vp.setCurrentItem(item,true);
break;
}
}

@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

}

class FVpAdapter extends PagerAdapter {

@Override
public int getCount() {
// TODO Auto-generated method stub
// return ivs.size();
return Integer.MAX_VALUE;
}

@Override
public boolean isViewFromObject(View arg0, Object arg1) {
// TODO Auto-generated method stub
return arg0 == arg1;
}

@Override
public void destroyItem(View arg0, int arg1, Object arg2) {
// TODO Auto-generated method stub
//不把划过去的View清空,否则再往回滑的话会变空白的View
//((ViewPager) arg0).removeView(ivs.get(arg1 % ivs.size()));
}

@Override
public Object instantiateItem(View arg0, int arg1) {
// TODO Auto-generated method stub

try {
// ((ViewPager) arg0).addView(list.get(arg1),0);
//                ((ViewPager) arg0).removeView(ivs.get(arg1 % ivs.size()));
((ViewPager) arg0)
.addView(ivs.get(arg1 % ivs.size()));
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}

return ivs.get(arg1 % ivs.size());

}

}
// 自定义scroller更改viewPager默认的切换时间
class FixedSpeedScroller extends Scroller {
//切换一秒钟
private int mDuration = 1000;

public FixedSpeedScroller(Context context) {
super(context);
}

public FixedSpeedScroller(Context context, Interpolator interpolator) {
super(context, interpolator);
}

@Override
public void startScroll(int startX, int startY, int dx, int dy,
int duration) {
// Ignore received duration, use fixed one instead
super.startScroll(startX, startY, dx, dy, mDuration);
}

@Override
public void startScroll(int startX, int startY, int dx, int dy) {
// Ignore received duration, use fixed one instead
super.startScroll(startX, startY, dx, dy, mDuration);
}
}

private static class ImageHandler extends Handler{
/**
* 请求更新显示的View。
*/
protected static final int MSG_UPDATE_IMAGE  = 1;
/**
* 请求暂停轮播。
*/
protected static final int MSG_KEEP_SILENT   = 2;
/**
* 请求恢复轮播。
*/
protected static final int MSG_BREAK_SILENT  = 3;
/**
* 记录最新的页号,当用户手动滑动时需要记录新页号,否则会使轮播的页面出错。
* 例如当前如果在第一页,本来准备播放的是第二页,而这时候用户滑动到了末页,
* 则应该播放的是第一页,如果继续按照原来的第二页播放,则逻辑上有问题。
*/
protected static final int MSG_PAGE_CHANGED  = 4;

//轮播间隔时间
protected static final long MSG_DELAY = 3000;

//使用弱引用避免Handler泄露.这里的泛型参数可以不是Activity,也可以是Fragment等
private WeakReference<MainActivity> weakReference;
private int currentItem = 0;

protected ImageHandler(WeakReference<MainActivity> wk){
weakReference = wk;
}

@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
MainActivity activity = weakReference.get();
if (activity==null){
//Activity已经回收,无需再处理UI了
return ;
}
//检查消息队列并移除未发送的消息,这主要是避免在复杂环境下消息出现重复等问题。
if (activity.handler.hasMessages(MSG_UPDATE_IMAGE)){
//次句不加,更换变得很不稳定
activity.handler.removeMessages(MSG_UPDATE_IMAGE);
}
switch (msg.what) {
case MSG_UPDATE_IMAGE:
currentItem++;
activity.vp.setCurrentItem(currentItem);
//准备下次播放
activity.handler.sendEmptyMessageDelayed(MSG_UPDATE_IMAGE, MSG_DELAY);
break;
case MSG_KEEP_SILENT:
//只要不发送消息就暂停了
break;
case MSG_BREAK_SILENT:
activity.handler.sendEmptyMessageDelayed(MSG_UPDATE_IMAGE, MSG_DELAY);
break;
case MSG_PAGE_CHANGED:
//记录当前的页号,避免播放的时候页面显示不正确。
currentItem = msg.arg1;
break;
default:
break;
}
}
}

}
代码中注释已经很详细了,这里就不在说明,大家有问题的可以给我留言

源码下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: