1. 项目概述

这里,我们使用自定义组合控件实现一个自动轮播的广告条,也叫轮播图,完整版的效果图如下图所示。其实,这就是我们经常见到的滚动广告,默认情况下每隔N 秒会自动滚动,用手指左右滑动时也会切换到上一张或者下一张。当界面切换时,对应广告图片的标题也会随着改变,并且还有对应图片索引的点也会被选中变为红色。此处,实现的核心控件是ViewPager,它是Android3.0 版本加入的新控件,为了向下兼容,谷歌给我们提供了android-support-v4.jar 包。

2. 轮播图UI布局

布局整体采用RelativeLayout,android.support.v4.view.ViewPager,TextView,LinearLayout 配合使用布局文件activity_main.xml 的代码如下文件所示:

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><FrameLayout
        android:layout_width="match_parent"android:layout_height="wrap_content"><android.support.v4.view.ViewPager
            android:id="@+id/vp_pager"android:layout_width="match_parent"android:layout_height="160dp"/><LinearLayout
            android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_gravity="bottom"android:background="#a000"android:orientation="vertical"android:padding="5dp"><TextView
                android:id="@+id/tv_title"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="新闻标题"android:textColor="#fff"android:textSize="16sp"/><LinearLayout
                android:id="@+id/ll_container"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center_horizontal"android:orientation="horizontal"></LinearLayout></LinearLayout></FrameLayout>
</RelativeLayout>

3. 轮播图的代码逻辑实现

<?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="wrap_content"android:orientation="vertical"><FrameLayout
        android:layout_width="match_parent"android:layout_height="wrap_content"><android.support.v4.view.ViewPager
            android:id="@id/viewpager"android:layout_width="match_parent"android:layout_height="180dp"/><!--android:background="#a000"--><LinearLayout
            android:id="@id/content"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_gravity="bottom"android:orientation="vertical"android:padding="5dp"><TextView
                android:id="@id/tvTitle"android:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center"android:textColor="#fff"android:textSize="16sp"/><LinearLayout
                android:id="@id/llcontainer"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="3dp"android:gravity="center_horizontal"android:orientation="horizontal"/></LinearLayout></FrameLayout><android.support.v7.widget.RecyclerView
        android:id="@id/recyclerview"android:layout_width="match_parent"android:layout_height="match_parent"/></LinearLayout>
public class BannerActivity extends AppCompatActivity implements ViewPager.OnPageChangeListener{@Bind(R.id.viewpager)public ViewPager mViewPager;@Bind(R.id.tvTitle)public TextView mTextView;@Bind(R.id.llcontainer)public LinearLayout mContainer;@Bind(R.id.content)public LinearLayout mContent;@Bind(R.id.recyclerview)RecyclerView mRecyclerView;private int mPreviousPos;private int[] imgs = new int[]{R.mipmap.a, R.mipmap.b, R.mipmap.c, R.mipmap.d, R.mipmap.e};private String[] title;private ArrayList<String> transformerList = new ArrayList<>();private RvAdapter mRvAdapter;private Handler mHandler = new Handler() {@Overridepublic void handleMessage(Message msg) {int currentItem = mViewPager.getCurrentItem();mViewPager.setCurrentItem(++currentItem);mHandler.sendEmptyMessageDelayed(0, 5000);}};private ViewPagerScroller mScroller;private ViewPagerScroller scroller;private ActionBar mActionBar;@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);initView();initRecyclerView();initListener();initTransformer();initViewPagerScroll();}private void initView() {setContentView(R.layout.activity_banner);ButterKnife.bind(this);title = UIUtil.getStringArray(R.array.title);SpannableString actionBarTitle = new SpannableString("大图轮播");actionBarTitle.setSpan(new ForegroundColorSpan(Color.WHITE), 0, actionBarTitle.length(),Spannable.SPAN_INCLUSIVE_EXCLUSIVE);mActionBar = getSupportActionBar();mActionBar.setTitle(actionBarTitle);mViewPager.setAdapter(new Adapter());int middle = Integer.MAX_VALUE / 2;int extra = middle % imgs.length;int currentItem = middle - extra;mViewPager.setCurrentItem(currentItem);mHandler.sendEmptyMessageDelayed(0, 5000);for (int i = 0; i < imgs.length; i++) {ImageView img = new ImageView(this);img.setImageResource(R.drawable.point_selector);LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);if (i != 0) {params.leftMargin = 10;img.setEnabled(false);}img.setLayoutParams(params);mContainer.addView(img);}mTextView.setText(title[0]);mViewPager.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {@Overridepublic void onGlobalLayout() {BannerActivity.this.onPageSelected(0);mViewPager.getViewTreeObserver().removeGlobalOnLayoutListener(this);}});}private void initRecyclerView() {LinearLayoutManager manager = new LinearLayoutManager(this);mRecyclerView.setLayoutManager(manager);mRvAdapter = new RvAdapter(this, R.layout.list_item, transformerList);mRecyclerView.setAdapter(mRvAdapter);}private void initListener() {mViewPager.addOnPageChangeListener(this);/*new ViewPager.OnPageChangeListener() {@Overridepublic void onPageScrolled(int position, float positionOffset, intpositionOffsetPixels) {}@Overridepublic void onPageSelected(int position) {int pos = position % imgs.length;mTextView.setText(title[pos]);mContainer.getChildAt(pos).setEnabled(true);mContainer.getChildAt(mPreviousPos).setEnabled(false);mPreviousPos = pos;colorChange(pos);}@Overridepublic void onPageScrollStateChanged(int state) {}}*/mViewPager.setOnTouchListener(new View.OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:mHandler.removeCallbacksAndMessages(null);break;case MotionEvent.ACTION_MOVE:break;case MotionEvent.ACTION_UP:mHandler.sendEmptyMessageDelayed(0, 5000);break;}return false;}});mRvAdapter.setOnItemClickListener(new OnItemClickListener() {@Overridepublic void onItemClick(ViewGroup parent, View view, Object o, int position) {String transforemerName = transformerList.get(position);try {Class clazz = Class.forName("com.ToxicBakery.viewpager.transforms." +transforemerName);ABaseTransformer transformer = (ABaseTransformer) clazz.newInstance();mViewPager.setPageTransformer(true, transformer);if (transforemerName.equals("StackTransformer")) {scroller.setScrollDuration(1200);}} catch (ClassNotFoundException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}}@Overridepublic boolean onItemLongClick(ViewGroup parent, View view, Object o, int position) {return false;}});}/*** 设置ViewPager的滑动速度*/private void initViewPagerScroll() {Field mScroller = null;try {mScroller = ViewPager.class.getDeclaredField("mScroller");mScroller.setAccessible(true);scroller = new ViewPagerScroller(mViewPager.getContext());mScroller.set(mViewPager, scroller);} catch (NoSuchFieldException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}}private void initTransformer() {//各种翻页效果transformerList.add(DefaultTransformer.class.getSimpleName());transformerList.add(AccordionTransformer.class.getSimpleName());transformerList.add(BackgroundToForegroundTransformer.class.getSimpleName());transformerList.add(CubeInTransformer.class.getSimpleName());transformerList.add(CubeOutTransformer.class.getSimpleName());transformerList.add(DepthPageTransformer.class.getSimpleName());transformerList.add(FlipHorizontalTransformer.class.getSimpleName());transformerList.add(FlipVerticalTransformer.class.getSimpleName());transformerList.add(ForegroundToBackgroundTransformer.class.getSimpleName());transformerList.add(RotateDownTransformer.class.getSimpleName());transformerList.add(RotateUpTransformer.class.getSimpleName());transformerList.add(StackTransformer.class.getSimpleName());transformerList.add(ZoomInTransformer.class.getSimpleName());transformerList.add(ZoomOutTranformer.class.getSimpleName());mRvAdapter.notifyDataSetChanged();}private void colorChange(int pos) {Bitmap bitmap = BitmapFactory.decodeResource(getResources(), imgs[pos]);Palette.from(bitmap).generate(new Palette.PaletteAsyncListener() {@Overridepublic void onGenerated(Palette palette) {Palette.Swatch vibrant = palette.getVibrantSwatch();mContent.setBackgroundColor(toARGB(vibrant.getRgb()));mTextView.setTextColor(vibrant.getBodyTextColor());mActionBar.setBackgroundDrawable(new ColorDrawable(vibrant.getRgb()));if (Build.VERSION.SDK_INT >=21){Window window = getWindow();window.setStatusBarColor(colorBurn(vibrant.getRgb()));//window.setNavigationBarColor(Color.RED);}}});}@Overridepublic void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}@Overridepublic void onPageSelected(int position) {int pos = position % imgs.length;mTextView.setText(title[pos]);mContainer.getChildAt(pos).setEnabled(true);if (pos != mPreviousPos){mContainer.getChildAt(mPreviousPos).setEnabled(false);}mPreviousPos = pos;colorChange(pos);}/*** 颜色添加透明度* @param rgb* @return*/protected  static  int toARGB(int rgb){int red = rgb >> 16 & 0xFF;int green = rgb >> 8 & 0xFF;int blue = rgb & 0xFF;return Color.argb(180 , red , green , blue );}/*** 颜色加深处理* @param RGBValues* @return*/private int colorBurn(int RGBValues) {int alpha = RGBValues >> 24;int red = RGBValues >> 16 & 0xFF;int green = RGBValues >> 8 & 0xFF;int blue = RGBValues & 0xFF;red = (int) Math.floor(red * (1 - 0.1));green = (int) Math.floor(green * (1 - 0.1));blue = (int) Math.floor(blue * (1 - 0.1));return Color.rgb(red, green, blue);}@Overridepublic void onPageScrollStateChanged(int state) {}private class Adapter extends PagerAdapter {@Overridepublic int getCount() {if (imgs.length != 0) {return Integer.MAX_VALUE;}return 0;}@Overridepublic boolean isViewFromObject(View view, Object object) {return view == object;}@Overridepublic Object instantiateItem(ViewGroup container, int position) {int pos = position % imgs.length;ImageView img = new ImageView(BannerActivity.this);img.setBackgroundResource(imgs[pos]);container.addView(img);return img;}@Overridepublic void destroyItem(ViewGroup container, int position, Object object) {container.removeView((View) object);}}private class RvAdapter extends CommonAdapter<String> {public RvAdapter(Context context, int layoutId, List<String> datas) {super(context, layoutId, datas);}@Overridepublic void convert(ViewHolder holder, String s) {holder.setText(R.id.tv_item, s);}}
}

4. 把Banner封装成一个模块

public class RollViewPager extends ViewPager implements ViewPager.OnPageChangeListener {private List<String> mImageLists;private List<String> mTitleLists;private List<View>   mDotLists;public  Context      mContext;private TextView     mTopNewsTitle;private Task         mTask;private boolean hasAdapter   = false;private int     oldPosition  = 0;private int     mCurrentItem = 0;private int  downX;private int  downY;private long downTimeMillis;// 是否滑动private boolean isMove = false;public RollViewPager(Context context, List<View> mDotLists) {super(context);this.mDotLists = mDotLists;this.mContext = context;mTask = new Task();// 设置viewpager 的触摸事件RollViewPager.this.setOnTouchListener(new OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {// 当手指触摸到屏幕的时候。viewpage 停止跳动// 当手指离开屏幕的时候。viewpage 继续跳动if (event.getAction() == MotionEvent.ACTION_DOWN) {// 获取到down 的时间downTimeMillis = System.currentTimeMillis();// 停止跳动// 删除消息handler.removeCallbacksAndMessages(null);// 删除任务//handler.removeCallbacks(mTask);} else if (event.getAction() == MotionEvent.ACTION_UP) {// 获取的是当前时间long currentTimeMillis = System.currentTimeMillis();if (currentTimeMillis - downTimeMillis < 500) {// Toast.makeText(mContext, "我被点击了", 0).show();if (mViewPageOnTouchListener != null) {mViewPageOnTouchListener.onViewPageClickListener();}}// 继续跳动start();} else if (event.getAction() == MotionEvent.ACTION_CANCEL) {System.out.println("MotionEvent.ACTION_CANCEL");start();}return false;}});}public void start() {if (!hasAdapter) {hasAdapter = true;RollViewPagerAdapter adapter = new RollViewPagerAdapter();RollViewPager.this.setAdapter(adapter);RollViewPager.this.setOnPageChangeListener(this);}handler.postDelayed(mTask, 2000);}public void stop() {handler.removeCallbacksAndMessages(null);}@Overridepublic void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {super.onPageScrolled(position, positionOffset, positionOffsetPixels);}@Overridepublic void onPageSelected(int position) {mCurrentItem = position;if (null != mTitleLists && mTitleLists.size() > 0&& null != mTopNewsTitle) {mTopNewsTitle.setText(mTitleLists.get(position));}if (null != mDotLists && mDotLists.size() > 0) {mDotLists.get(position).setBackgroundResource(R.drawable.dot_focus);mDotLists.get(oldPosition).setBackgroundResource(R.drawable.dot_normal);}oldPosition = position;}@Overridepublic void onPageScrollStateChanged(int state) {}@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {switch (ev.getAction()) {case MotionEvent.ACTION_DOWN:downX = (int) ev.getX();downY = (int) ev.getY();// isMove = false;break;case MotionEvent.ACTION_MOVE:int currentX = (int) ev.getX();int currentY = (int) ev.getY();if (Math.abs(currentX - downX) > Math.abs(currentY - downY)) {// 左右滑动viewPageisMove = false;} else {// 上下滑动listviewisMove = true;}break;}// 请求父类不要拦截我getParent().requestDisallowInterceptTouchEvent(!isMove);return super.dispatchTouchEvent(ev);}private class RollViewPagerAdapter extends PagerAdapter {@Overridepublic void destroyItem(ViewGroup container, int position, Object object) {container.removeView((View) object);}@Overridepublic Object instantiateItem(ViewGroup container, int position) {View view = View.inflate(mContext, R.layout.viewpager_item, null);ImageView image = (ImageView) view.findViewById(R.id.image);BitmapUtils.display(mContext, image, mImageLists.get(position));container.addView(view);return view;}@Overridepublic int getCount() {return mImageLists.size();}@Overridepublic boolean isViewFromObject(View arg0, Object arg1) {return arg0 == arg1;}}/*** 设置轮播图上面的标题** @param mTopNewsTitle* @param mTitleLists*/public void setTextTitle(TextView mTopNewsTitle, List<String> mTitleLists) {if (null != mTopNewsTitle && null != mTitleLists && mTitleLists.size() > 0) {this.mTopNewsTitle = mTopNewsTitle;this.mTitleLists = mTitleLists;mTopNewsTitle.setText(mTitleLists.get(0));}}/*** 设置背景图片** @param mImageLists*/public void setImageRes(List<String> mImageLists) {this.mImageLists = mImageLists;}private class Task implements Runnable {@Overridepublic void run() {mCurrentItem = (mCurrentItem + 1) % mImageLists.size();handler.obtainMessage().sendToTarget();}}private Handler handler = new Handler() {public void handleMessage(android.os.Message msg) {RollViewPager.this.setCurrentItem(mCurrentItem, false);start();}};private ViewPageOnTouchListener mViewPageOnTouchListener;public interface ViewPageOnTouchListener {public void onViewPageClickListener();}public void setViewPageOnTouchListener(ViewPageOnTouchListener viewPageOnTouchListener) {mViewPageOnTouchListener = viewPageOnTouchListener;}
}

源代码:https://github.com/JackChen1999/Banner

5. 开源项目

Android-ConvenientBanner

DecentBanner

AndroidImageSlider

关于我

  • Email:<815712739@qq.com>
  • CSDN博客:Allen Iverson
  • 新浪微博:AndroidDeveloper

License

Copyright 2015 AllenIversonCopyright 2012 Jake Wharton
Copyright 2011 Patrik Åkerfeldt
Copyright 2011 Francisco Figueiredo Jr.Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License athttp://www.apache.org/licenses/LICENSE-2.0Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

自定义组合控件:Banner、轮播图、广告栏控件相关推荐

  1. Mint-UI 移动首页开发 - header导航、banner轮播图

    Mint-UI 移动首页style排版问题:header导航.banner轮播图.footer底部版权··· ··· 资源预览: 中文 2.x官方文档(含演示地址): 文档首页 中文 2.x官方文档( ...

  2. AxureRP实战(三)Banner轮播图交互(进阶篇)

    前一篇<AxureRP实战(二)Banner轮播图交互(基础篇)>用淘宝的首页banner案例讲解了如何运用动态面板实现banner轮播图的切换,有了基本交互功能.但是,交互效果还有些欠缺 ...

  3. html中制作banner,css banner轮播图怎么做?

    css banner轮播图怎么做?下面本篇文章给大家简单介绍一下.有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助. 初步了解动画效果吧.轮播图我一直以为靠jquery插件完成的,突然发 ...

  4. 谷粒学院-首页数据显示-banner轮播图微服务搭建

    新建banner轮播图微服务 1.在service模块下创建子模块service_cms 2.配置application.properties # 服务端口 server.port=8004 # 服务 ...

  5. banner轮播图切换插件

    下载地址 banner轮播图切换插件,基于jquery实现的图片轮播效果. dd:

  6. H5页面中的视频轮播(类似于banner轮播图效果)

    先说下我的需求,如下图: 手机模型中间部分是视频播放,当一条视频播放完毕后,整屏会自动上滑切换到下一个视频. 详细效果展示请在PC端点击:http://www.17jianyue.cn/ 查看 提起轮 ...

  7. Android Studio Banner轮播图

    Banner轮播图 使用步骤 代码片段 使用步骤 1.导依赖 2.写布局 3.图片集合(图片网址,图片资源id),标题集合 4.常用方法 图片集合 banner.setImages(imgs); 加载 ...

  8. 安卓实现Banner轮播图自定义图片(非网络图片)

    需要一个轮播图,研究了一下,github上最好的就是这个banner了. 首先,在build.gradle中添加依赖: implementation 'com.youth.banner:banner: ...

  9. 2.2.2新版Banner轮播图实现

    随着Android弃用了jcenter库以后,Banner的使用也大大的和以前不同,下面就来介绍一下2.2.2版本banner的使用和Demo 文章目录 一.改进内容 二.Demo效果图 二.步骤 1 ...

  10. Android入门Banner轮播图的使用(详解)

    Banner是Android一个轮播图的框架,使用Banner让我们实现轮播效果的代码更加简洁化. 先上效果图: 1.添加依赖 ---- com.youth.banner:banner:1.4.9 i ...

最新文章

  1. javascript:为string类添加三个成员,实现去左,右,及所有空格
  2. 中文版GPT-3来了?智源研究院发布清源 CPM —— 以中文为核心的大规模预训练模型...
  3. 文件可视化编辑_高维数据可视化必备图形平行坐标图
  4. linux网络共享文件夹,[Linux] - Windows与Linux网络共享文件夹挂载方法
  5. c++ STL 容器——序列
  6. 1.1收集域名信息-完整介绍
  7. 多功能嵌入式解码软件(2)
  8. 利用NLB建立双机负载均衡群集
  9. JavaScript开发工具--Aptana
  10. SecureCRT 连接Win10内置ubuntu问题层层突围
  11. C#语言开发环境的搭建
  12. access注入大全
  13. 算法设计与分析(期末复习重点)更新中
  14. java action接口,Struts2 Action接口与ActionSupport类
  15. xmind下载安装电脑版教程
  16. 总结HTMLT5高级的新特性
  17. 软件测试面试题【变态逻辑题】,盘点那些大厂面试必出变态逻辑题
  18. 企查查企业详情爬虫(自动模拟登录企业详情页法律风险爬取)
  19. BERT模型—1.BERT模型架构
  20. matlab:反三角函数

热门文章

  1. 持续高温引发百姓热议 ***趁机放毒谋取暴利
  2. PON:EPON/GPON/10G PON/XG-PON/NG-PON2—Vecloud微云
  3. perl+cgi学习
  4. ASP.NET中常用的文件上传下载方法
  5. sklearn学习总结(超全面)
  6. 9.2.4 .net core 通过ViewComponent封装控件
  7. 心路历程(一)-自学java两个月心得
  8. poj 3398 (树上的最小支配集)
  9. 有空时深入阅读这两篇文章
  10. 非常快的文本模式的emacs