今天我学习了使用ViewPager实现广告条的效果,以后项目中也可以使用
来看代码,首先是xml布局文件:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="wrap_content"
android:layout_height="200dp"></android.support.v4.view.ViewPager>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignBottom="@id/viewpager"
android:orientation="vertical">
<TextView
android:id="@+id/tv_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="666"
android:gravity="center"/>
<LinearLayout
android:id="@+id/dot_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_gravity="center_horizontal">
</LinearLayout>
</LinearLayout>
</RelativeLayout>
然后在Activity中实例化:
mViewPager = (ViewPager) findViewById(R.id.viewpager);
dot_layout = (LinearLayout) findViewById(R.id.dot_layout);
tv_text = (TextView) findViewById(R.id.tv_text);
设置ViewPager的Adapter:
mViewPager.setAdapter(new PagerAdapter() {
@Override
public int getCount() {
return Integer.MAX_VALUE;
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
int realPosition = position%imageViewList.size();
ImageView imageView = imageViewList.get(realPosition);
container.addView(imageView);
System.out.println("instantiateItem position" + position);
return imageView;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
System.out.println("destroyItem position" + position);
}
});
图片资源:
private int[] images = {
R.drawable.a,
R.drawable.b,
R.drawable.c,
R.drawable.d,
R.drawable.e
};
这样一个简单的ViewPager就是实现好了。
1下面来看一下图片下面小圆点的实现:
这里我们可以这样做,在LinearLayout中addView数量为images.lenth的ImageView,然后给每个imageView设置图片资源,可以用select来做,也可以用两张不同原色图片来做,这里我就用select来做,然后监听ViewPager的滑动事件,滑动到哪张图片根据position给那个小圆点设置为高亮,前一个小圆点就变为正常,代码如下:
select代码:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/normal" android:state_enabled="false" />
<item android:drawable="@drawable/selected" android:state_enabled="true" />
</selector>
图片资源文件,这里用shape来做:
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval"> <size android:height="8dp" android:width="8dp"/> <solid android:color="#44000000"/> </shape>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval"> <size android:height="8dp" android:width="8dp"/> <solid android:color="#d61212"/> </shape>
Viewpager的滑动监听:
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageSelected(int position) { int realPosition = position % imageViewList.size(); dot_layout.getChildAt(preposition).setEnabled(false); dot_layout.getChildAt(realPosition).setEnabled(true); preposition = realPosition; } @Override public void onPageScrollStateChanged(int state) { } });
2.实现左右无限滑动的效果:实现无限滑动的效果网上都是在adapter的getCount方法中设置出一个很大的值,然后Viewpager开始的时候用setCurrentItem设置在中间的位置,这样就可以左右滑动了
这里注意的是,Viewpager是每次只能实例化最多3个View,比如说有0,1,2,3,张图片,一开始ViewPager就实例化了0和1张图片,当我滑动到图片1时,图片2就被实例化了,当我又滑动到图片2时,图片3就被实例化了,而图片0就被remove掉,以此类推。
上代码:
首先改写getCount方法,这里最好使用Short.MAX_VALUE,避免Viewpager的卡顿
@Override public int getCount() { return Integer.MAX_VALUE;
然后在开始的时候把Viewpager设置为中间页:这里我的图片是5张,所以用此算法来得到item是5的整数倍
int item = Integer.MAX_VALUE / 2 - Integer.MAX_VALUE / 2 % imageViewList.size();//保证item是5的整数倍 mViewPager.setCurrentItem(item);
然后在onPagerSelect方法中:
int realPosition = position % imageViewList.size(); dot_layout.getChildAt(preposition).setEnabled(false); dot_layout.getChildAt(realPosition).setEnabled(true); preposition = realPosition;
还有在instantiateItem方法中:int realPosition = position%imageViewList.size(); ImageView imageView = imageViewList.get(realPosition); container.addView(imageView); System.out.println("instantiateItem position" + position); return imageView;
此时运行程序就可以实现上面1和2的效果了
3.自动滑动
思路:使用handler实现:
private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); int item = mViewPager.getCurrentItem() + 1; mViewPager.setCurrentItem(item); handler.sendEmptyMessageDelayed(0, 4000); } };
然后在程序启动时发出消息:
handler.sendEmptyMessageDelayed(0, 4000);
4.当手指按下时停止滑动:
思路:监听imageview的onTouch事件,当MotionEvent为down时取消之前发的消息,当为Up时再继续发送消息
for (int i = 0; i < images.length; i++) { ImageView imageView = new ImageView(this); imageView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: //当手指按下的时候移除消息 handler.removeCallbacksAndMessages(null); break; case MotionEvent.ACTION_UP: //当手指放开的时候再发送消息 handler.sendEmptyMessageDelayed(2, 4000); break; } return true; }
此时运行程序,发现当我手指按下时能停止滑动,手指松开后确实还能继续滑动,但是当我拖拽图片到另一页的时候,会发现图片再也不会自动滑动了,原因是因为当我们拖动图片时,手指松开时并不会触发up事件,而是触发了viewpager传送过来的MotionEvent.CANCEL事件,所以我们可以在MotionEvent.CANCEL事件中也加上发消息的代码,这时再启动程序会发现之前的问题解决了,但是新的问题又出现了,当你拖拽图片不到一半并按住图片停止时,图片会自动地转到了下一页,因为此时我们的在MotionEvent.CANCEL中已经发送了消息,4秒之后会跳到下一页,而此时我们还停止在原来的地方,自然而然4秒之后就跳到下一页了,所以此时我们要在viewpager的onPageScrollStateChanged方法中做处理
@Override public void onPageScrollStateChanged(int state) { System.out.println("state" + state); Log.i("tag", "state" + state); if (state == ViewPager.SCROLL_STATE_DRAGGING) {//如果当前状态是拖拽状态时 isDragging = true; handler.removeCallbacksAndMessages(null);//把之前的消息移除掉 } else if (state == ViewPager.SCROLL_STATE_IDLE && isDragging) {//如果当前状态是静止状态并且是拖拽过来的 isDragging = false; handler.sendEmptyMessageDelayed(4, 4000);//当拖拽来另一个页面时再发消息 } } });
定义一个boolean型变量,当拖拽时我们设置为true并且把消息移除,表示已经拖拽了,当viewpager静止状态时,如果isDragging为ttrue,即表示当前页面是拖拽过来的就重新发消息,并且把isDragging设置为false,此时启动程序会发现之前的问题都已经解决了