自定义View系列之ViewPager实现广告条效果

来源:互联网 发布:网络营销优化 编辑:程序博客网 时间:2024/05/21 07:07

今天我学习了使用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,此时启动程序会发现之前的问题都已经解决了

阅读全文
0 0
原创粉丝点击