Android UI实现广告Banner轮播效果
本篇博客要分享的一个效果是实现广告banner轮播效果,这个效果也比较常见,一些视频类应用就经常有,就拿360影视大全来举例吧:
用红框框住的那个效果就是小巫今天要分享的,先来思考一下会用到什么控件?有什么用户体验?
控件我们可能一下子就可以想到的自然是viewpager,没错!用到的就是viewpager,那么它会有什么用户体验呢,它可能有以下几个体验:
1. 间隔不停的切换图片,指示器也跟着变
2. 点击图片可以跳转到指定的页面
如何实现?
布局开始着手
/bannerautoscrolldemo/res/layout/banner.xml
<?xml version="1.0" encoding="utf-8"?> <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <framelayout android:layout_width="match_parent" android:layout_height="210dp" > <android.support.v4.view.viewpager android:id="@+id/vp" android:layout_width="match_parent" android:layout_height="210dp" /> <relativelayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="bottom" android:background="@drawable/shadow_article" > <textview android:id="@+id/tv_date" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_above="@+id/author_layout" android:layout_marginbottom="10dp" android:layout_marginleft="10dp" android:maxlines="2" android:text="3月4日" android:textcolor="@color/white" android:textsize="18sp" /> <textview android:id="@+id/tv_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_above="@+id/author_layout" android:layout_marginbottom="10dp" android:layout_marginleft="10dp" android:layout_marginright="10dp" android:layout_torightof="@+id/tv_date" android:maxlines="2" android:text="我和*只是同姓" android:textcolor="@color/white" android:textsize="18sp" /> <relativelayout android:id="@+id/author_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignparentbottom="true" android:layout_marginleft="10dp" android:gravity="center_vertical" android:paddingbottom="20dp" > <textview android:id="@+id/tv_pre" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="文章选题来自" android:textcolor="@color/white" android:textsize="12sp" /> <textview android:id="@+id/tv_topic_from" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_torightof="@+id/tv_pre" android:text="阿宅的" android:textcolor="@color/white" android:textsize="12sp" /> <textview android:id="@+id/tv_topic" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginleft="10dp" android:layout_torightof="@+id/tv_topic_from" android:text="“我想知道令狐安和*有什么关系?”" android:textcolor="@color/white" android:textsize="12sp" /> </relativelayout> </relativelayout> <linearlayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margintop="10dip" android:layout_gravity="bottom|center_horizontal" android:layout_marginbottom="10dp" android:gravity="center" > <view android:id="@+id/v_dot0" style="@style/dot_style" android:background="@drawable/dot_focused" android:visibility="invisible" /> <view android:id="@+id/v_dot1" style="@style/dot_style" android:visibility="invisible"/> <view android:id="@+id/v_dot2" style="@style/dot_style" android:visibility="invisible"/> <view android:id="@+id/v_dot3" style="@style/dot_style" android:visibility="invisible"/> <view android:id="@+id/v_dot4" style="@style/dot_style" android:visibility="invisible" /> </linearlayout> </framelayout> </linearlayout>
一个viewpager,下面五个指示点,注意每个点都有同样的样式,我们在style.xml中定义样式:
/bannerautoscrolldemo/res/values/styles.xml
<style name="dot_style"> <item name="android:layout_width">5dip</item> <item name="android:layout_height">5dip</item> <item name="android:background">@drawable/dot_normal</item> <item name="android:layout_marginleft">1.5dip</item> <item name="android:layout_marginright">1.5dip</item> </style>
定义圆点图形资源
/bannerautoscrolldemo/res/drawable/dot_normal.xml
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval" > <solid android:color="#33000000" /> <corners android:radius="5dip" /> </shape>
/bannerautoscrolldemo/res/drawable/dot_focused.xml
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval" > <solid android:color="#aaffffff" /> <corners android:radius="5dip" /> </shape>
定义广告实体
/bannerautoscrolldemo/src/com/xiaowu/banner/demo/addomain.java
package com.xiaowu.banner.demo; /** * 广告实体 * * @author wwj_748 * */ public class addomain { private string id; // 广告id private string date; // 日期 private string title; // 标题 private string topicfrom; //选题来自 private string topic; // 选题 private string imgurl; // 图片url private boolean isad; // 是否为广告 private string starttime; // 广告开始时间 private string endtime; // 广告结束时间 private string targeturl; // 目标url private int width; // 宽 private int height; // 高 private boolean available; // 是否可用 public string getid() { return id; } public void setid(string id) { this.id = id; } public string gettitle() { return title; } public void settitle(string title) { this.title = title; } public string getimgurl() { return imgurl; } public void setimgurl(string imgurl) { this.imgurl = imgurl; } public boolean isad() { return isad; } public void setad(boolean isad) { this.isad = isad; } public string getdate() { return date; } public void setdate(string date) { this.date = date; } public string gettopic() { return topic; } public void settopic(string topic) { this.topic = topic; } public string gettopicfrom() { return topicfrom; } public void settopicfrom(string topicfrom) { this.topicfrom = topicfrom; } public string getstarttime() { return starttime; } public void setstarttime(string starttime) { this.starttime = starttime; } public string getendtime() { return endtime; } public void setendtime(string endtime) { this.endtime = endtime; } public string gettargeturl() { return targeturl; } public void settargeturl(string targeturl) { this.targeturl = targeturl; } public int getwidth() { return width; } public void setwidth(int width) { this.width = width; } public int getheight() { return height; } public void setheight(int height) { this.height = height; } public boolean isavailable() { return available; } public void setavailable(boolean available) { this.available = available; } }
实现切换逻辑
1. 定时切换
2. 切换图片
3. 切换标题
4. 切换指示器
定时切换用到一个类:scheduledexecutorservice
作用是定时执行任务,我们这里要做的定时任务是,2秒执行一次图片切换
private void startad() { scheduledexecutorservice = executors.newsinglethreadscheduledexecutor(); // 当activity显示出来后,每两秒切换一次图片显示 scheduledexecutorservice.scheduleatfixedrate(new scrolltask(), 1, 2, timeunit.seconds); }
定义子线程
private class scrolltask implements runnable { @override public void run() { synchronized (adviewpager) { currentitem = (currentitem + 1) % imageviews.size(); handler.obtainmessage().sendtotarget(); } } }
通过handle来通知viewpager进行视图切换
private handler handler = new handler() { public void handlemessage(android.os.message msg) { adviewpager.setcurrentitem(currentitem); }; };
我们提供模拟数据来进行测试
/** * 轮播广播模拟数据 * * @return */ public static list<addomain> getbannerad() { list<addomain> adlist = new arraylist<addomain>(); addomain addomain = new addomain(); addomain.setid("108078"); addomain.setdate("3月4日"); addomain.settitle("我和*只是同姓"); addomain.settopicfrom("阿宅"); addomain.settopic("我想知道令狐安和*有什么关系?"); addomain.setimgurl("/d50735fae6cd7b8900d74cd40c2442a7d9330e29.jpg"); addomain.setad(false); adlist.add(addomain); addomain addomain2 = new addomain(); addomain2.setid("108078"); addomain2.setdate("3月5日"); addomain2.settitle("我和*只是同姓"); addomain2.settopicfrom("小巫"); addomain2.settopic("“我想知道令狐安和*有什么关系?”"); addomain2 .setimgurl("/eaf81a4c510fd9f9a1edb58b262dd42a2934a45e.jpg"); addomain2.setad(false); adlist.add(addomain2); addomain addomain3 = new addomain(); addomain3.setid("108078"); addomain3.setdate("3月6日"); addomain3.settitle("我和*只是同姓"); addomain3.settopicfrom("旭东"); addomain3.settopic("“我想知道令狐安和*有什么关系?”"); addomain3 .setimgurl("/8718367adab44aed22a58aeeb11c8701a08bfbd4.jpg"); addomain3.setad(false); adlist.add(addomain3); addomain addomain4 = new addomain(); addomain4.setid("108078"); addomain4.setdate("3月7日"); addomain4.settitle("我和*只是同姓"); addomain4.settopicfrom("小软"); addomain4.settopic("“我想知道令狐安和*有什么关系?”"); addomain4 .setimgurl("/a686c9177f3e670932e4cf9338c79f3df9dc55f2.jpg"); addomain4.setad(false); adlist.add(addomain4); addomain addomain5 = new addomain(); addomain5.setid("108078"); addomain5.setdate("3月8日"); addomain5.settitle("我和*只是同姓"); addomain5.settopicfrom("大熊"); addomain5.settopic("“我想知道令狐安和*有什么关系?”"); addomain5 .setimgurl("/0bd162d9f2d3572c7dad11ba8913632762d0c30d.jpg"); addomain5.setad(true); // 代表是广告 adlist.add(addomain5); return adlist; }
viewpager逻辑处理
1. 填充数据(自定义adapter)
2. 设置页面切换监听事件
3. 在自定义adapter中的instantiateitem方法设置viewpager点击事件
这里我们的图片是从网上下载的,用到了universal-image-loader-1.8.6-with-sources.jar这个类库,可以实现异步加载图片,具体使用查看代码。
最后给出完整代码:
/bannerautoscrolldemo/src/com/xiaowu/banner/demo/mainactivity.java
package com.xiaowu.banner.demo; import java.io.file; import java.util.arraylist; import java.util.list; import java.util.concurrent.executors; import java.util.concurrent.scheduledexecutorservice; import java.util.concurrent.timeunit; import android.app.activity; import android.graphics.bitmap; import android.os.bundle; import android.os.handler; import android.os.parcelable; 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.view.onclicklistener; import android.view.viewgroup; import android.widget.imageview; import android.widget.imageview.scaletype; import android.widget.textview; import com.nostra13.universalimageloader.cache.disc.impl.unlimiteddisccache; import com.nostra13.universalimageloader.cache.memory.impl.lrumemorycache; import com.nostra13.universalimageloader.core.displayimageoptions; import com.nostra13.universalimageloader.core.imageloader; import com.nostra13.universalimageloader.core.imageloaderconfiguration; import com.nostra13.universalimageloader.core.assist.imagescaletype; import com.nostra13.universalimageloader.core.assist.queueprocessingtype; public class mainactivity extends activity { public static string image_cache_path = "imageloader/cache"; // 图片缓存路径 private viewpager adviewpager; private list<imageview> imageviews;// 滑动的图片集合 private list<view> dots; // 图片标题正文的那些点 private list<view> dotlist; private textview tv_date; private textview tv_title; private textview tv_topic_from; private textview tv_topic; private int currentitem = 0; // 当前图片的索引号 // 定义的五个指示点 private view dot0; private view dot1; private view dot2; private view dot3; private view dot4; // 定时任务 private scheduledexecutorservice scheduledexecutorservice; // 异步加载图片 private imageloader mimageloader; private displayimageoptions options; // 轮播banner的数据 private list<addomain> adlist; private handler handler = new handler() { public void handlemessage(android.os.message msg) { adviewpager.setcurrentitem(currentitem); }; }; @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); // 使用imageloader之前初始化 initimageloader(); // 获取图片加载实例 mimageloader = imageloader.getinstance(); options = new displayimageoptions.builder() .showstubimage(r.drawable.top_banner_android) .showimageforemptyuri(r.drawable.top_banner_android) .showimageonfail(r.drawable.top_banner_android) .cacheinmemory(true).cacheondisc(true) .bitmapconfig(bitmap.config.rgb_565) .imagescaletype(imagescaletype.exactly).build(); initaddata(); startad(); } /** * 初始化imageloader */ private void initimageloader() { file cachedir = com.nostra13.universalimageloader.utils.storageutils .getowncachedirectory(getapplicationcontext(), image_cache_path); displayimageoptions defaultoptions = new displayimageoptions.builder() .cacheinmemory(true).cacheondisc(true).build(); imageloaderconfiguration config = new imageloaderconfiguration.builder( this).defaultdisplayimageoptions(defaultoptions) .memorycache(new lrumemorycache(12 * 1024 * 1024)) .memorycachesize(12 * 1024 * 1024) .disccachesize(32 * 1024 * 1024).disccachefilecount(100) .disccache(new unlimiteddisccache(cachedir)) .threadpriority(thread.norm_priority - 2) .tasksprocessingorder(queueprocessingtype.lifo).build(); imageloader.getinstance().init(config); } /** * 初始化广告数据 */ private void initaddata() { // 广告数据 adlist = getbannerad(); imageviews = new arraylist<imageview>(); // 点 dots = new arraylist<view>(); dotlist = new arraylist<view>(); dot0 = findviewbyid(r.id.v_dot0); dot1 = findviewbyid(r.id.v_dot1); dot2 = findviewbyid(r.id.v_dot2); dot3 = findviewbyid(r.id.v_dot3); dot4 = findviewbyid(r.id.v_dot4); dots.add(dot0); dots.add(dot1); dots.add(dot2); dots.add(dot3); dots.add(dot4); tv_date = (textview) findviewbyid(r.id.tv_date); tv_title = (textview) findviewbyid(r.id.tv_title); tv_topic_from = (textview) findviewbyid(r.id.tv_topic_from); tv_topic = (textview) findviewbyid(r.id.tv_topic); adviewpager = (viewpager) findviewbyid(r.id.vp); adviewpager.setadapter(new myadapter());// 设置填充viewpager页面的适配器 // 设置一个监听器,当viewpager中的页面改变时调用 adviewpager.setonpagechangelistener(new mypagechangelistener()); adddynamicview(); } private void adddynamicview() { // 动态添加图片和下面指示的圆点 // 初始化图片资源 for (int i = 0; i < adlist.size(); i++) { imageview imageview = new imageview(this); // 异步加载图片 mimageloader.displayimage(adlist.get(i).getimgurl(), imageview, options); imageview.setscaletype(scaletype.center_crop); imageviews.add(imageview); dots.get(i).setvisibility(view.visible); dotlist.add(dots.get(i)); } } @override protected void onresume() { super.onresume(); } private void startad() { scheduledexecutorservice = executors.newsinglethreadscheduledexecutor(); // 当activity显示出来后,每两秒切换一次图片显示 scheduledexecutorservice.scheduleatfixedrate(new scrolltask(), 1, 2, timeunit.seconds); } private class scrolltask implements runnable { @override public void run() { synchronized (adviewpager) { currentitem = (currentitem + 1) % imageviews.size(); handler.obtainmessage().sendtotarget(); } } } @override protected void onstop() { super.onstop(); // 当activity不可见的时候停止切换 scheduledexecutorservice.shutdown(); } private class mypagechangelistener implements onpagechangelistener { private int oldposition = 0; @override public void onpagescrollstatechanged(int arg0) { } @override public void onpagescrolled(int arg0, float arg1, int arg2) { } @override public void onpageselected(int position) { currentitem = position; addomain addomain = adlist.get(position); tv_title.settext(addomain.gettitle()); // 设置标题 tv_date.settext(addomain.getdate()); tv_topic_from.settext(addomain.gettopicfrom()); tv_topic.settext(addomain.gettopic()); dots.get(oldposition).setbackgroundresource(r.drawable.dot_normal); dots.get(position).setbackgroundresource(r.drawable.dot_focused); oldposition = position; } } private class myadapter extends pageradapter { @override public int getcount() { return adlist.size(); } @override public object instantiateitem(viewgroup container, int position) { imageview iv = imageviews.get(position); ((viewpager) container).addview(iv); final addomain addomain = adlist.get(position); // 在这个方法里面设置图片的点击事件 iv.setonclicklistener(new onclicklistener() { @override public void onclick(view v) { // 处理跳转逻辑 } }); return iv; } @override public void destroyitem(view arg0, int arg1, object arg2) { ((viewpager) arg0).removeview((view) arg2); } @override public boolean isviewfromobject(view arg0, object arg1) { return arg0 == arg1; } @override public void restorestate(parcelable arg0, classloader arg1) { } @override public parcelable savestate() { return null; } @override public void startupdate(view arg0) { } @override public void finishupdate(view arg0) { } } /** * 轮播广播模拟数据 * * @return */ public static list<addomain> getbannerad() { list<addomain> adlist = new arraylist<addomain>(); addomain addomain = new addomain(); addomain.setid("108078"); addomain.setdate("3月4日"); addomain.settitle("我和*只是同姓"); addomain.settopicfrom("阿宅"); addomain.settopic("我想知道令狐安和*有什么关系?"); addomain.setimgurl("/d50735fae6cd7b8900d74cd40c2442a7d9330e29.jpg"); addomain.setad(false); adlist.add(addomain); addomain addomain2 = new addomain(); addomain2.setid("108078"); addomain2.setdate("3月5日"); addomain2.settitle("我和*只是同姓"); addomain2.settopicfrom("小巫"); addomain2.settopic("“我想知道令狐安和*有什么关系?”"); addomain2 .setimgurl("/eaf81a4c510fd9f9a1edb58b262dd42a2934a45e.jpg"); addomain2.setad(false); adlist.add(addomain2); addomain addomain3 = new addomain(); addomain3.setid("108078"); addomain3.setdate("3月6日"); addomain3.settitle("我和*只是同姓"); addomain3.settopicfrom("旭东"); addomain3.settopic("“我想知道令狐安和*有什么关系?”"); addomain3 .setimgurl("/8718367adab44aed22a58aeeb11c8701a08bfbd4.jpg"); addomain3.setad(false); adlist.add(addomain3); addomain addomain4 = new addomain(); addomain4.setid("108078"); addomain4.setdate("3月7日"); addomain4.settitle("我和*只是同姓"); addomain4.settopicfrom("小软"); addomain4.settopic("“我想知道令狐安和*有什么关系?”"); addomain4 .setimgurl("/a686c9177f3e670932e4cf9338c79f3df9dc55f2.jpg"); addomain4.setad(false); adlist.add(addomain4); addomain addomain5 = new addomain(); addomain5.setid("108078"); addomain5.setdate("3月8日"); addomain5.settitle("我和*只是同姓"); addomain5.settopicfrom("大熊"); addomain5.settopic("“我想知道令狐安和*有什么关系?”"); addomain5 .setimgurl("/0bd162d9f2d3572c7dad11ba8913632762d0c30d.jpg"); addomain5.setad(true); // 代表是广告 adlist.add(addomain5); return adlist; } }
源码下载:http://xiazai.jb51.net/201612/yuanma/androidbannerautoscroll(jb51.net).rar
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。