自定义控件:使用ViewPager实现广告条效果

来源:互联网 发布:淘宝贷款50万还不上 编辑:程序博客网 时间:2024/05/17 08:25

在许多项目之中,首页的activity或者fragment都会一般有广告条的效果,我们来自定义实现一下广告条。

整体运行效果:


一:广告条ViewPager的介绍:

布局文件activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent" >    <android.support.v4.view.ViewPager        android:id="@+id/viewpager"        android:layout_width="wrap_content"        android:layout_height="200dp" />    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_alignBottom="@id/viewpager"        android:background="#44000000"        android:gravity="center_horizontal"        android:orientation="vertical" >        <TextView            android:id="@+id/tv_msg"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:gravity="center_horizontal"            android:text="三只火枪手"            android:textColor="#ffffff"            android:textSize="18sp" />        <LinearLayout            android:id="@+id/ll_point_groups"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:orientation="horizontal"            android:padding="3dp" />    </LinearLayout></RelativeLayout>
实例化ViewPager和关联其源码:

public class MainActivity extends Activity {private ViewPager viewpager;private LinearLayout ll_point_group;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);viewpager = (ViewPager) findViewById(R.id.viewpager);ll_point_group = (LinearLayout) findViewById(R.id.ll_point_group);}}

关联源代码:

1.删除工程里面的Android Depandencies,删除后会报错,不要理会。看下面



2.添加libs目录下的Android-support-v4.jar

 选中-->右键-->build path-->add to build path

3.关联源代码

目录:C:\android\adt-bundle-windows-x86_64-20130219\sdk\extras\android\support\v4\src\java

点击ViewPager类,出现图标;


大家对于v4包都已经很熟悉了,现在在新建android项目时,v4包是默认导入的。v7包出来没多长时间,用的人也不多,主要对3.0以下版本提供 ActionBar支持,以及SearchView,PopupMenu等控件的支持。因为一些开源框架已经实现对3.0以下版本ActionBar的支 持,所以v7包的使用意义也不是很大。

知识拓展:

如果jar包导入错误,怎么修改呢?

右键工程---->properties---->Java Build Path --->Libraries-->选择android-support-v4.jar展开---->Editor--->External Folder

4.ViewPager的原理


能显示很多页面,这些页面可以是图片也可以是布局文件。

设置图片资源ID和图片标题集合和准备ImageView列表数据
// 图片资源IDprivate final int[] imageIds = { R.drawable.a,R.drawable.b, R.drawable.c,R.drawable.d,R.drawable.e };// 图片标题集合private final String[] imageDescriptions = {"巩俐不低俗,我就不能低俗","扑树又回来啦!再唱经典老歌引万人大合唱", "揭秘北京电影如何升级", "乐视网TV版大派送", "热血屌丝的反杀" };//准备数据imageList = new ArrayList<ImageView>();for(int i=0;i<imageIds.length;i++){<span style="white-space:pre">ImageView imageView = new ImageView(this);imageView.setBackgroundResource(imageIds[i]);imageList.add(imageView);</span>}
为ViewPager设置适配器:

private class MyPagerAdapter extends PagerAdapter {@Overridepublic int getCount() {// 页面或者图片的总数return imageList.size();}/** * 功能:给ViewPager添加指定的view * container 就是ViewPager,其实就是容器。 * position 具体页面或者图片的位置 */@Overridepublic Object instantiateItem(ViewGroup container, int position) {System.out.println("instantiateItem=="+position);View view = imageList.get(position);container.addView(view);//返回的值,不一定是View ,也可以是和View有关系的任意的Object//return super.instantiateItem(container, position);return view;}/** * 判断某个page和object的关系 * object 是 instantiateItem的返回值 */@Overridepublic boolean isViewFromObject(View view, Object object) {//if(view ==object){//return true;//}else{//return false;//}return view ==object;}/** * 销毁指定位置上的View或者object */@Overridepublic void destroyItem(ViewGroup container, int position, Object object) {System.out.println("destroyItem=="+position);container.removeView((View) object);//super.destroyItem(container, position, object);}}
解决运行时错误:

选中项目--->右键--->Java Build Path --->

order and  export--->勾选android-support-v4.jar--->千万不要忘了clean


二:广告条的基本功能:

1.根据不同图片显示不同的描述信息:
viewpager.setOnPageChangeListener(new OnPageChangeListener() {/** * 当页面被选择了回调 * position 当前被显示的页面的位置:从0开始 */@Overridepublic void onPageSelected(int position) {tv_image_desc.setText(imageDescriptions[position]);}/** * 当页面滑动了调用该方法 */@Overridepublic void onPageScrolled(int position, float positionOffset,int positionOffsetPixels) {}/** * 当页面状态发送变化的调用防方法 * 静止--滑动 * 滑动-静止 *  */@Overridepublic void onPageScrollStateChanged(int state) {}});
2.用shape资源定义点和背景:
point_nomal.xml
<?xml version="1.0" encoding="utf-8"?><shape xmlns:android="http://schemas.android.com/apk/res/android"     android:shape="oval">    <size android:height="5dp"        android:width="5dp"/>    <solid android:color="#55000000"/></shape>
point_focused.xml
<?xml version="1.0" encoding="utf-8"?><shape xmlns:android="http://schemas.android.com/apk/res/android"     android:shape="oval">    <size android:height="5dp"        android:width="5dp"/>    <solid android:color="#88ffffff"/></shape>
point_selector.xml
<?xml version="1.0" encoding="utf-8"?><selector xmlns:android="http://schemas.android.com/apk/res/android" >    <item android:drawable="@drawable/point_normal" android:state_enabled="false"/>    <item android:drawable="@drawable/point_focused" android:state_enabled="true"/></selector>
3.代码里面添加指示点:
for(int i=0;i<imageIds.length;i++){ImageView imageView = new ImageView(this);imageView.setBackgroundResource(imageIds[i]);imageViews.add(imageView);//添加指示点ImageView point = new ImageView(this);point.setBackgroundResource(R.drawable.point_selsetor);ll_point_group.addView(point);//默认情况下,第一个小点enable为trueif(i ==0){point.setEnabled(true);}else{point.setEnabled(false);}}
4.设置改变指示点的状态:
/** * 上次的位置 */private int lastPointIndex;viewpager.setOnPageChangeListener(new OnPageChangeListener() {/** * 当页面被选择了回调 * position 当前被显示的页面的位置:从0开始 */@Overridepublic void onPageSelected(int position) {System.out.println("onPageSelected="+position);tv_image_desc.setText(imageDescriptions[position]);//设置指示点的状态 enable 的状态为true或者为false;ll_point_group.getChildAt(position).setEnabled(true);ll_point_group.getChildAt(lastPointIndex).setEnabled(false);lastPointIndex = position;}/** * 当页面滑动了调用该方法 */@Overridepublic void onPageScrolled(int position, float positionOffset,int positionOffsetPixels) {}/** * 但页面状态发送变化的调用防方法 * 静止--滑动 * 滑动-静止 *  */@Overridepublic void onPageScrollStateChanged(int state) {System.out.println("onPageScrollStateChanged===state=="+state);}});
5.设置指示点的间距:
for(int i=0;i<imageIds.length;i++){ImageView imageView = new ImageView(this);imageView.setBackgroundResource(imageIds[i]);imageViews.add(imageView);//添加指示点ImageView point = new ImageView(this);LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, -2);params.leftMargin = 15;point.setLayoutParams(params);point.setBackgroundResource(R.drawable.point_selsetor);ll_point_group.addView(point);//默认情况下,第一个小点enable为trueif(i ==0){point.setEnabled(true);}else{point.setEnabled(false);}}

注意导入包的时候,当前控件放入什么布局就导入谁的LayoutParams的。

6.设置可以循环滚动:
viewpager.setOnPageChangeListener(new OnPageChangeListener() {/** * 当页面被选择了回调 * position 当前被显示的页面的位置:从0开始 */@Overridepublic void onPageSelected(int position) {int  myIndex = position % imageViews.size();System.out.println("onPageSelected="+position);tv_image_desc.setText(imageDescriptions[myIndex]);//设置指示点的状态 enable 的状态为true或者为false;ll_point_group.getChildAt(myIndex).setEnabled(true);ll_point_group.getChildAt(lastPointIndex).setEnabled(false);lastPointIndex = myIndex;}//..............................});}private class MyPagerAdapter extends PagerAdapter {@Overridepublic int getCount() {//得到数据的总数//return imageViews.size();return Integer.MAX_VALUE;}/** * 给ViewPager添加指定的View * container 是ViewPage,他是一个容器 * position 要实例化的view的位置 */@Overridepublic Object instantiateItem(ViewGroup container, int position) {//System.out.println("instantiateItem=="+position);//实例化ViewView view = imageViews.get(position%imageViews.size());container.addView(view);//返回值,不一定要是View对象,也可以是和View有关系的任意object//return super.instantiateItem(container, position);return view;}//......................
7.解决左滑没有效果问题:
//要求刚好是imageViews.size()的整数倍int item = Integer.MAX_VALUE/2-Integer.MAX_VALUE/2%imageViews.size();//让ViewPager跳转到指定的位置,应该保证是imageView.size()的整数倍viewpager.setCurrentItem(item );//11 和 101

三:广告条自动翻页

实现方式有多种方案:

1.定时器 timer + Handler

2.while true 循环 sleep  + Handler;

3,ClockManger + Handler ;

4,Handler 

我们采用常用的方式Handler

/** * 是否自定滑动运行中 */private boolean isRunning = false;private Handler handler = new Handler(){public void handleMessage(android.os.Message msg) {viewpager.setCurrentItem(viewpager.getCurrentItem()+1);if(isRunning){handler.sendEmptyMessageDelayed(0, 4000);}};};

onCreate中写上

isRunning = true;handler.sendEmptyMessageDelayed(0, 2000);

四:整体代码:

package com.xbmu.adviewpager;import java.util.ArrayList;import java.util.List;import android.app.Activity;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.View;import android.view.ViewGroup;import android.widget.ImageView;import android.widget.LinearLayout;import android.widget.TextView;import android.widget.LinearLayout.LayoutParams;public class MainActivity extends Activity {private ViewPager viewPager;private TextView tv_msg;private LinearLayout ll_point_groups;private List<ImageView> imageViews;// 图片标题集合private final String[] imageDescriptions = { "巩俐不低俗,我就不能低俗","朴树又回来啦!再唱经典老歌引万人大合唱", "揭秘北京电影如何升级", "乐视网TV版大派送", "热血屌丝的反杀" };private int[] ids = { R.drawable.a, R.drawable.b, R.drawable.c,R.drawable.d, R.drawable.e };/** * 记录上次被高亮的位置 */private int lastIndex = 0;/** * true:自动滑动 * false:停止自动滑动 */private boolean isRuning = false;private Handler handler = new Handler(){public void handleMessage(android.os.Message msg) {if(isRuning){//自动滑动viewPager.setCurrentItem(viewPager.getCurrentItem()+1);handler.sendEmptyMessageDelayed(0, 2000);}};};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 1.初始化控件viewPager = (ViewPager) findViewById(R.id.viewpager);tv_msg = (TextView) findViewById(R.id.tv_msg);ll_point_groups = (LinearLayout) findViewById(R.id.ll_point_groups);// 2.准备数据,实例化广告图片imageViews = new ArrayList<ImageView>();for (int i = 0; i < ids.length; i++) {ImageView view = new ImageView(this);// 设置背景view.setBackgroundResource(ids[i]);// 把图片添加到列表中imageViews.add(view);// 2.1实例化指示点或者下标点ImageView point = new ImageView(this);point.setImageResource(R.drawable.point_selector);// View的父亲(LinearLayout布局)是什么布局文件,就导入它的包LayoutParams params = new LayoutParams(10, 10);params.leftMargin = 15;point.setLayoutParams(params);// 把点添加到线性布局ll_point_groups.addView(point);// 默认设置第一个高亮显示if (i == 0) {point.setEnabled(true);} else {point.setEnabled(false);}}// 3.设置适配器viewPager.setAdapter(new MyPagerAdapter());// 4.设置页面改变监听(广告图片和文字一起改变)viewPager.setOnPageChangeListener(new OnPageChangeListener() {/** * 当某个页面被选择的时候回调 */@Overridepublic void onPageSelected(int position) {int newIndex = position % imageViews.size();// 取出广告文字String msg = imageDescriptions[newIndex];//设置广告文字tv_msg.setText(msg);//对应的点高亮ll_point_groups.getChildAt(newIndex).setEnabled(true);//上次的点击设置成默认ll_point_groups.getChildAt(lastIndex).setEnabled(false);lastIndex = newIndex;}/** * 当页面滚动的时候被调用 */@Overridepublic void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}/** * 当状态发生改变的时候回调 * 静止-滚动 * 滚蛋-静止 */@Overridepublic void onPageScrollStateChanged(int arg0) {}});//默认中 中间开始滚动int midPosition = Integer.MAX_VALUE/2;viewPager.setCurrentItem(midPosition);isRuning = true;//从第0个位置开始,每隔2秒,自动运行广告条handler.sendEmptyMessageDelayed(0, 2000);}@Overrideprotected void onDestroy() {super.onDestroy();isRuning = false;}private class MyPagerAdapter extends PagerAdapter {// 得到总条数@Overridepublic int getCount() {// 把这个总条数设置很大很大return Integer.MAX_VALUE;}/** * 相当于getView:实例化每个页面的View和添加View ViewGroup container:容器 int position:位置 */@Overridepublic Object instantiateItem(ViewGroup container, int position) {// 根据位置去某个Viewint newPosition = position % imageViews.size();// 值总在0~imageViews.size()之间ImageView view = imageViews.get(newPosition);// 添加到容器中container.addView(view);// 返回实例化的Viewreturn view;}/** * 判断view和instantiateItem返回的对象是否一样 Object obj:是instantiateItem返回的对象 */@Overridepublic boolean isViewFromObject(View view, Object object) {// if(view == object){// return true;// }else{// return false;// }// 上面的代码可以写成下面这样的形式return view == object;}/** * 实例化两张图片 最多只能装三张图片 */@Overridepublic void destroyItem(ViewGroup container, int position, Object object) {// 释放资源,自己处理了,不需要执行父类的方法了container.removeView((View) object);// super.destroyItem(container, position, object);}}}



1 0
原创粉丝点击