Android自定义控件——仿淘宝、网易、彩票等广告条、Banner的制作

尊重作者劳动成果,转载时请标明该文章出自 http://blog.csdn.net/allen315410/article/details/39294343

最近翻看以前的某项目时,发现了一个极其常用的效果——广告条,或者也称不上自定义组件,但是使用频率还是相当普遍的。

打开市面上各大App主界面,或多或少会出现这样的东西,甚至一个应用中出现N多个,这种展示广告的效果,不仅动态效果好,而且众所周知的“不占屏”,想想在手机设备这么小的屏幕尺寸下,能放下几页甚至十几页的广告循环播放,就知道这种广告的使用频率之大了。以下是我收集的部分APP中使用的效果截图:

这些“千万亿”级别的APP都在使用的效果,为什么我们不能效仿追随一下呢,那下面我就开始动手做一个自己的广告条;

要求如下:1,实现多图展示

2,实现手势切换

3,广告图片与广告标语同时切换

4,循环切换,定时循环播放

以下是我的项目结构:

广告条实际上用的是ViewPager来做的,布局中仅仅放了一个ViewPager而已,其它的图片切换都是用ViewPager来展示的,布局如下:

<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="match_parent"
        android:layout_height="200dp" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@id/viewpager"
        android:background="#33000000"
        android:orientation="vertical"
        android:padding="5dp" >

        <TextView
            android:id="@+id/tv_image_description"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:text="巩俐不低俗,我们也不低俗"
            android:textColor="@android:color/white" />

        <LinearLayout
            android:id="@+id/ll_point_group"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:layout_marginTop="5dp"
            android:orientation="horizontal" >
        </LinearLayout>
    </LinearLayout>

</RelativeLayout>

上面的ViewPager用来显示广告图片,下面的LinearLayout嵌在ViewPager底部,实现阴影效果。里面包括TextView来显示广告标语,和一个LinearLayout来显示广告切换状态指示点。写完布局,就可以为这个ViewPager加载数据,增加动态效果了,主要代码如下,注释清晰:

package com.example.banner;

import java.util.ArrayList;
import java.util.List;

import android.os.Bundle;
import android.os.SystemClock;
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;
import android.app.Activity;

public class MainActivity extends Activity {

	private List<ImageView> mImageList;
	/** 广告条正下方的标语 */
	private String[] imageDescriptionArray = { //
	"巩俐不低俗,我就不能低俗", //
			"扑树又回来啦!再唱经典老歌引万人大合唱", //
			"揭秘北京电影如何升级", //
			"乐视网TV版大派送", //
			"热血屌丝的反杀" };
	/** 记录上一次点的位置,默认为0 */
	private int previousPointEnale = 0;
	private ViewPager mViewPager;
	private LinearLayout llPointGroup;
	private TextView tvDescription;
	/** 记录是否停止循环播放 */
	private boolean isStop = false;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		init();
		// 开启子线程,让广告条以2秒的频率循环播放
		new Thread(new Runnable() {

			@Override
			public void run() {

				while (!isStop) {
					SystemClock.sleep(2000);
					runOnUiThread(new Runnable() {
						public void run() {
							mViewPager.setCurrentItem(mViewPager.getCurrentItem() + 1);
						}
					});
				}
			}
		}).start();
	}

	private void init() {
		llPointGroup = (LinearLayout) findViewById(R.id.ll_point_group);
		tvDescription = (TextView) findViewById(R.id.tv_image_description);
		mImageList = new ArrayList<ImageView>();
		int[] imageIds = new int[] { R.drawable.a, R.drawable.b, R.drawable.c, R.drawable.d, R.drawable.e };
		ImageView mImageView;
		LayoutParams params;
		// 初始化广告条资源
		for (int id : imageIds) {
			mImageView = new ImageView(this);
			mImageView.setBackgroundResource(id);
			mImageList.add(mImageView);

			// 初始化广告条正下方的"点"
			View dot = new View(this);
			dot.setBackgroundResource(R.drawable.point_background);
			params = new LayoutParams(5, 5);
			params.leftMargin = 10;
			dot.setLayoutParams(params);
			dot.setEnabled(false);
			llPointGroup.addView(dot);
		}
		mViewPager = (ViewPager) findViewById(R.id.viewpager);
		mViewPager.setAdapter(new MyAdapter());

		// 设置广告条跳转时,广告语和状态语的变化
		mViewPager.setOnPageChangeListener(new MyListener());

		// 初始化广告条,当前索引Integer.MAX_VALUE的一半
		int index = (Integer.MAX_VALUE / 2) - (Integer.MAX_VALUE / 2 % mImageList.size());
		mViewPager.setCurrentItem(index); // 设置当前选中的Page,会触发onPageChangListener.onPageSelected方法
	}

	private class MyListener implements OnPageChangeListener {

		@Override
		public void onPageScrollStateChanged(int arg0) {
			// TODO Auto-generated method stub

		}

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

		}

		@Override
		public void onPageSelected(int arg0) {
			// 获取新的位置
			int newPosition = arg0 % imageDescriptionArray.length;
			// 设置广告标语
			tvDescription.setText(imageDescriptionArray[newPosition]);
			// 消除上一次的状态点
			llPointGroup.getChildAt(previousPointEnale).setEnabled(false);
			// 设置当前的状态点“点”
			llPointGroup.getChildAt(newPosition).setEnabled(true);
			// 记录位置
			previousPointEnale = newPosition;
		}

	}

	/**
	 * ViewPager数据适配器
	 */
	private class MyAdapter extends PagerAdapter {

		@Override
		public int getCount() {
			// 将viewpager页数设置成Integer.MAX_VALUE,可以模拟无限循环
			return Integer.MAX_VALUE;
		}

		/**
		 * 复用对象 true 复用view false 复用的是Object
		 */
		@Override
		public boolean isViewFromObject(View arg0, Object arg1) {
			// TODO Auto-generated method stub
			return arg0 == arg1;
		}

		/**
		 * 销毁对象
		 *
		 * @param position
		 *            被销毁对象的索引位置
		 */
		@Override
		public void destroyItem(ViewGroup container, int position, Object object) {
			container.removeView(mImageList.get(position % mImageList.size()));
		}

		/**
		 * 初始化一个对象
		 *
		 * @param position
		 *            初始化对象的索引位置
		 */
		@Override
		public Object instantiateItem(ViewGroup container, int position) {
			container.addView(mImageList.get(position % mImageList.size()));
			return mImageList.get(position % mImageList.size());
		}

	}

	@Override
	protected void onDestroy() {
		// activity销毁时候,关闭循环播放
		isStop = true;
		super.onDestroy();
	}

}

需要注意的是,为了达到广告条循环播放的效果,故不能将ViewPager所展示的总数设置较小的定值,这样若ViewPager划过这个定值的时候,页面会定住,用户体验就不太理想化了,为了能达到这个循环的效果,只能将ViewPager展示总数设置成一个很大的值,以便来给用户造成无限循环的假象。那么这个值该取多大合适呢?思前想后,觉得在PagerAdapter的getCount方法中,返回Integer.MAX_VALUE这个值,这个值2147483647,无论如何用户也不可以拿手机没事划上个好几亿次吧。

到此还要注意的地方就是,因为getCount中返回Integer.MAX_VALUE这么大数值,为了达到有图循环的效果,避免Bug,所以其后每次涉及到position索引的地方都得用position和资源尺度取余的结果。

此外,在“点”的初始化的时候,应当设置“点”的索引为int index = (Integer.MAX_VALUE / 2) - (Integer.MAX_VALUE / 2 % mImageList.size());

而不能简单设置成0,若是设置成0,就无法制造出循环播放的“假象”,不信试试设置0,往左滑动。

关于“点”的资源,没有用到图片,下面是资源代码,贴出来:

广告条获得焦点:point_bg_enable.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval" >

    <corners android:radius="0.5dp" />

    <solid android:color="#AAFFFFFF" />

</shape>

广告条普通样式:point_bg_normal.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval" >

    <corners android:radius="0.5dp" />

    <solid android:color="#55000000" />

</shape>

广告条的状态选择器:point_background.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:drawable="@drawable/point_bg_enable" android:state_enabled="true"></item>
    <item android:drawable="@drawable/point_bg_normal" android:state_enabled="false"></item>

</selector>

以下是效果图:

最后,还需要实现广告的自动循环播放,这个很简单,只要开启一个新线程,在线程中每隔2000ms循环更新一下ViewPager就行。就是在ViewPager中获取当前展示的Item的索引,加上1之后,设置展示这个值即可。还得注意程序的严谨性啊,当activity销毁的时候,这个新线程里负责循环播放的代码是徐璈停止执行的。故设置一个boolean的变量isStop,在while循环的时候,判断是否开启/关闭,在activity的onDestory方法中,设置其为true,即停止循环播放!

源码请在这里下载

时间: 2024-10-13 11:48:36

Android自定义控件——仿淘宝、网易、彩票等广告条、Banner的制作的相关文章

Android中仿淘宝首页顶部滚动自定义HorizontalScrollView定时水平自动切换图片

Android中仿淘宝首页顶部滚动自定义HorizontalScrollView定时水平自动切换图片 自定义ADPager 自定义水平滚动的ScrollView效仿ViewPager 当遇到要在ViewPager中添加多张网络请求图片的情况下,不能进行复用,导致每次都要重新去求情已经请求过的数据致使流量数据过大 自定义的数据结构解决了这个问题,固定传递的图片数据之后进行统一请求,完成后进行页面切换数据复用 代码中涉及网络请求是用的Volley网络请求框架 PicCarousel是网络数据请求的U

android版高仿淘宝客户端源码V2.3

android版高仿淘宝客户端源码V2.3,这个版本我已经更新到2.3了,源码也上传到源码天堂那里了,大家可以看一下吧,该应用实现了我们常用的购物功能了,也就是在手机上进行网购的流程的,如查看产品(浏览),下订单,进行付款等流程,该应用一一实现了,同时还可以远程读取图片功能,和实时监控网络状态等操作,大家如果有什么不同的意见可以留下,我们会定时来查看. 原文地址:http://www.cnblogs.com/androidioscom/p/3613035.html [1].[代码] [Java]

自定义View之仿淘宝详情页

自定义View之仿淘宝详情页 转载请标明出处: http://blog.csdn.net/lisdye2/article/details/52353071 本文出自:[Alex_MaHao的博客] 项目中的源码已经共享到github,有需要者请移步[Alex_MaHao的github] 基本介绍 现在的一些购物类App例如淘宝,京东等,在物品详情页,都采用了类似分层的模式,即上拉加载详情的方式,节省了空间,使用户的体验更加的舒适.只要对于某个东西的介绍很多时,都可以采取这样的方式,第一个页面显示

高仿淘宝和聚美优品商城详情页实现《IT蓝豹》

android-vertical-slide-view高仿淘宝和聚美优品商城详情页实现,在商品详情页,向上拖动时,可以加载下一页.使用ViewDragHelper,滑动比较流畅. scrollView滑动到底部的时候,再行向上拖动时,添加了一些阻力.本项目来源:https://github.com/xmuSistone/android-vertical-slide-view主要代码如下:首先先看一下布局:  <com.stone.verticalslide.DragLayout        a

Listview嵌套Viewpager实现仿淘宝搜狐广告主页,并实现listview的下拉刷新

Android实现功能:Listview嵌套viewpager仿淘宝搜狐视频主页面,和listview的下拉刷新. 什么都不说了:直接上图说效果 listview嵌套viewpager实现仿淘宝的广告滑动主页面 源码连接:(http://download.csdn.net/detail/qq_30000411/9528977) APK下载连接:(http://download.csdn.net/detail/qq_30000411/9528973) 下面给出我源码的主要文件构成: MyListV

仿淘宝页面的搜索引擎,点击输入框文字不消失

1 <!DOCTYPE html> 2 <html> 3 <head lang="en"> 4 <meta charset="UTF-8"> 5 <title></title> 6 <style> 7 #txt { 8 position: relative; 9 10 } 11 #lbl { 12 position: absolute; 13 top: 8px; 14 left: 1

jquery仿淘宝规格颜色选择效果

jquery实现的仿淘宝规格颜色选择效果源代码如下 jquery仿淘宝规格颜色选择效果 -收缩HTML代码 运行代码 [如果运行无效果,请自行将源代码保存为html文件运行] <script type="text/javascript" src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.4.2.min.js"></script> <style> dd,dl{zoom:1;ove

一款仿淘宝购物的商品列表页面多条件查询(含有单选和全部)

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Typ

高仿淘宝客户端

高仿淘宝客户端 仿淘宝安卓客户端的demo源码,主要实现了:商品的基本展示.宝贝详情,图片展示的放大缩小功能.界面之间切换的动画.购物车多项删除.弹窗的动画效果.首页广告的轮播效果.获得本机具有传感器的列表.listView的上拉刷新,下拉加载功能.二维码扫描.刮刮乐等功能和效果. 下载地址:http://www.devstore.cn/code/info/925.html 运行截图: