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

在许多项目之中,首页的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;
	@Override
	protected 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,删除后会报错,不要理会。看下面


自定义控件:使用ViewPager实现广告条效果_第1张图片

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类,出现图标;

自定义控件:使用ViewPager实现广告条效果_第2张图片

大家对于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列表数据
// 图片资源ID
private 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 {

	@Override
	public int getCount() {
		// 页面或者图片的总数
		return imageList.size();
	}
	/**
	 * 功能:给ViewPager添加指定的view
	 * container 就是ViewPager,其实就是容器。
	 * position 具体页面或者图片的位置
	 */
	@Override
	public 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的返回值
	 */
	@Override
	public boolean isViewFromObject(View view, Object object) {
		//if(view ==object){
		//	return true;
		//}else{
		//	return false;
		//}
		return view ==object;	
	}

	/**
	 * 销毁指定位置上的View或者object
	 */
	@Override
	public 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开始
	 */
	@Override
	public void onPageSelected(int position) {
		tv_image_desc.setText(imageDescriptions[position]);	
	}
	/**
	 * 当页面滑动了调用该方法
	 */
	@Override
	public void onPageScrolled(int position, float positionOffset,
		int positionOffsetPixels) {			
	}
	/**
	 * 当页面状态发送变化的调用防方法
	 * 静止--滑动
	 * 滑动-静止
	 * 
	 */
	@Override
	public 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为true
	if(i ==0){
		point.setEnabled(true);
	}else{
		point.setEnabled(false);
	}
}
4.设置改变指示点的状态:
/**
 * 上次的位置
 */
private int lastPointIndex;

viewpager.setOnPageChangeListener(new OnPageChangeListener() {
	/**
	 * 当页面被选择了回调
	 * position 当前被显示的页面的位置:从0开始
	 */
	@Override
	public 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;
	}
	/**
	 * 当页面滑动了调用该方法
	 */
	@Override
	public void onPageScrolled(int position, float positionOffset,
		int positionOffsetPixels) {		
	}
	/**
	 * 但页面状态发送变化的调用防方法
	 * 静止--滑动
	 * 滑动-静止
	 * 
	 */
	@Override
	public 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为true
	if(i ==0){
		point.setEnabled(true);
	}else{
		point.setEnabled(false);
	}
}

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

6.设置可以循环滚动:
viewpager.setOnPageChangeListener(new OnPageChangeListener() {
	/**
	 * 当页面被选择了回调
	 * position 当前被显示的页面的位置:从0开始
	 */
	@Override
	public 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 {
	@Override
	public int getCount() {
		//得到数据的总数
		//return imageViews.size();
		return Integer.MAX_VALUE;
	}

	/**
	 * 给ViewPager添加指定的View
	 * container 是ViewPage,他是一个容器
	 * position 要实例化的view的位置
	 */
	@Override
	public Object instantiateItem(ViewGroup container, int position) {
		//System.out.println("instantiateItem=="+position);
		//实例化View
		View 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);
			}
		};
	};
	@Override
	protected 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() {
			/**
			 * 当某个页面被选择的时候回调
			 */
			@Override
			public 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;
			}
			/**
			 * 当页面滚动的时候被调用
			 */
			@Override
			public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
				
			}
			/**
			 * 当状态发生改变的时候回调
			 * 静止-滚动
			 * 滚蛋-静止
			 */
			@Override
			public void onPageScrollStateChanged(int arg0) {

			}
		});
		//默认中 中间开始滚动
		int midPosition = Integer.MAX_VALUE/2;
		viewPager.setCurrentItem(midPosition);
		
		isRuning = true;
		//从第0个位置开始,每隔2秒,自动运行广告条
		handler.sendEmptyMessageDelayed(0, 2000);
	}
	@Override
	protected void onDestroy() {
		super.onDestroy();
		isRuning = false;
	}
	
	
	private class MyPagerAdapter extends PagerAdapter {
		// 得到总条数
		@Override
		public int getCount() {
			// 把这个总条数设置很大很大
			return Integer.MAX_VALUE;
		}

		/**
		 * 相当于getView:实例化每个页面的View和添加View ViewGroup container:容器 int position:位置
		 */
		@Override
		public Object instantiateItem(ViewGroup container, int position) {
			// 根据位置去某个View
			int newPosition = position % imageViews.size();// 值总在0~imageViews.size()之间
			ImageView view = imageViews.get(newPosition);
			// 添加到容器中
			container.addView(view);
			// 返回实例化的View
			return view;
		}

		/**
		 * 判断view和instantiateItem返回的对象是否一样 Object obj:是instantiateItem返回的对象
		 */

		@Override
		public boolean isViewFromObject(View view, Object object) {
			// if(view == object){
			// return true;
			// }else{
			// return false;
			// }
			// 上面的代码可以写成下面这样的形式
			return view == object;
		}

		/**
		 * 实例化两张图片 最多只能装三张图片
		 */
		@Override
		public void destroyItem(ViewGroup container, int position, Object object) {
			// 释放资源,自己处理了,不需要执行父类的方法了
			container.removeView((View) object);
			// super.destroyItem(container, position, object);
		}

	}

}



你可能感兴趣的:(viewpager,广告条)