前因

近期打开爱奇艺的时候,突然发现它首页的轮播图跟以前不一样了,左右两个图都能显示一部分,且有滑动时缩放的效果,一直不知咋样实现,然后在鸿洋的微信公众号中看到了一篇仿魅族Banner效果的文章,最后在参考中放出了链接,然后就参考了这篇文章,就在此做个记录。废话不多说了,先上个效果图

后果

布局文件

<?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:clipChildren="false"android:orientation="vertical"><com.ly.viewpagerdemo.LoopViewPager
        android:id="@+id/looviewpager"android:layout_width="match_parent"android:layout_height="200dp"android:layout_marginLeft="20dp"android:layout_marginRight="20dp" /></LinearLayout>

这个属性android:clipChildren 很关键,是否裁剪子view
这里的LoopViewPager,是参考开源框架 LoopingViewPager来的,使用Integer.MAX_VALUE 来实现左右循环滚动的,使用方式是一致的


package com.ly.viewpagerdemo;import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.WindowManager;
import android.view.animation.Interpolator;
import android.widget.Scroller;import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.util.concurrent.atomic.AtomicBoolean;public class LoopViewPager extends ViewPager {OnPageChangeListener mOuterPageChangeListener;private LoopPagerAdapterWrapper mAdapter;private MyHandler mHandler;private final static int HANDLE_LOOP_MSG = 101;private AtomicBoolean isAutoLoop = new AtomicBoolean();@Overridepublic void setAdapter(PagerAdapter adapter) {mAdapter = new LoopPagerAdapterWrapper(adapter);super.setAdapter(mAdapter);isAutoLoop.set(false);setCurrentItem(0, false);}@Overridepublic PagerAdapter getAdapter() {return mAdapter != null ? mAdapter.getRealAdapter() : mAdapter;}/*** 获取当前真实的item** @return*/public int getRealItem() {return mAdapter != null ? mAdapter.toRealPosition(super.getCurrentItem()) : 0;}public void setCurrentItem(int item, boolean smoothScroll) {int realItem = mAdapter.toInnerPosition(item);super.setCurrentItem(realItem, smoothScroll);}@Overridepublic void setOnPageChangeListener(OnPageChangeListener listener) {mOuterPageChangeListener = listener;}public LoopViewPager(Context context) {super(context);init();}public LoopViewPager(Context context, AttributeSet attrs) {super(context, attrs);init();}private void init() {super.setOnPageChangeListener(onPageChangeListener);try {Field scrollerField = ViewPager.class.getDeclaredField("mScroller");scrollerField.setAccessible(true);Field interpolator = ViewPager.class.getDeclaredField("sInterpolator");interpolator.setAccessible(true);Scroller scroller = new Scroller(getContext(), (Interpolator) interpolator.get(null)) {@Overridepublic void startScroll(int startX, int startY, int dx, int dy, int duration) {//控制滑动速度super.startScroll(startX, startY, dx, dy, (int) (1300 * (double) Math.abs(dx) / getWidth(getContext())));}};scrollerField.set(this, scroller);} catch (Exception e) {e.printStackTrace();}}public void autoLoop(boolean isAuto) {if (mHandler == null) {mHandler = new MyHandler(getContext());}if (isAuto) {mHandler.sendEmptyMessageDelayed(HANDLE_LOOP_MSG, 3000);} else {mHandler.removeCallbacksAndMessages(null);}isAutoLoop.set(isAuto);}private OnPageChangeListener onPageChangeListener = new OnPageChangeListener() {private float mPreviousOffset = -1;private float mPreviousPosition = -1;@Overridepublic void onPageSelected(int position) {int realPosition = mAdapter.toRealPosition(position);if (mPreviousPosition != realPosition) {mPreviousPosition = realPosition;if (mOuterPageChangeListener != null) {mOuterPageChangeListener.onPageSelected(realPosition);}}}@Overridepublic void onPageScrolled(int position, float positionOffset,int positionOffsetPixels) {int realPosition = position;if (mAdapter != null) {realPosition = mAdapter.toRealPosition(position);if (positionOffset == 0&& mPreviousOffset == 0&& (position == 0 || position == mAdapter.getCount() - 1)) {setCurrentItem(realPosition, false);}}mPreviousOffset = positionOffset;if (mOuterPageChangeListener != null) {if (realPosition != mAdapter.getRealCount() - 1) {mOuterPageChangeListener.onPageScrolled(realPosition,positionOffset, positionOffsetPixels);} else {if (positionOffset > .5) {mOuterPageChangeListener.onPageScrolled(0, 0, 0);} else {mOuterPageChangeListener.onPageScrolled(realPosition,0, 0);}}}}@Overridepublic void onPageScrollStateChanged(int state) {switch (state) {case SCROLL_STATE_DRAGGING:if (isAutoLoop.get()) {mHandler.removeCallbacksAndMessages(null);}break;case SCROLL_STATE_IDLE:if (isAutoLoop.get()) {mHandler.sendEmptyMessageDelayed(HANDLE_LOOP_MSG, 3000);}break;case SCROLL_STATE_SETTLING:break;}if (mOuterPageChangeListener != null) {mOuterPageChangeListener.onPageScrollStateChanged(state);}}};private class MyHandler extends Handler {WeakReference<Context> mWeakReference;public MyHandler(Context context) {mWeakReference = new WeakReference<>(context);}@Overridepublic void handleMessage(Message msg) {final Context context = mWeakReference.get();if (context == null) {return;}switch (msg.what) {case HANDLE_LOOP_MSG:int curItem = getCurrentItem();setCurrentItem(++curItem);break;}}}public int getWidth(Context context) {WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);DisplayMetrics outMetrics = new DisplayMetrics();wm.getDefaultDisplay().getMetrics(outMetrics);return outMetrics.widthPixels;}
}

LoopPagerAdapterWrapper


package com.ly.viewpagerdemo;import android.os.Parcelable;
import android.support.v4.view.PagerAdapter;
import android.view.View;
import android.view.ViewGroup;public class LoopPagerAdapterWrapper extends PagerAdapter {private PagerAdapter mAdapter;LoopPagerAdapterWrapper(PagerAdapter adapter) {this.mAdapter = adapter;}@Overridepublic void notifyDataSetChanged() {super.notifyDataSetChanged();}public int toInnerPosition(int realPosition) {return realPosition + getCount() / 2  - getCount() % getRealCount();}int toRealPosition(int position) {return position % getRealCount();}@Overridepublic int getCount() {return Integer.MAX_VALUE;}public int getRealCount() {return mAdapter.getCount();}public PagerAdapter getRealAdapter() {return mAdapter;}@Overridepublic Object instantiateItem(ViewGroup container, int position) {int realPosition = position % getRealCount();return mAdapter.instantiateItem(container, realPosition);}@Overridepublic void destroyItem(ViewGroup container, int position, Object object) {int realPosition = position % getRealCount();mAdapter.destroyItem(container, realPosition, object);}@Overridepublic void finishUpdate(ViewGroup container) {mAdapter.finishUpdate(container);}@Overridepublic boolean isViewFromObject(View view, Object object) {return mAdapter.isViewFromObject(view, object);}@Overridepublic void restoreState(Parcelable bundle, ClassLoader classLoader) {mAdapter.restoreState(bundle, classLoader);}@Overridepublic Parcelable saveState() {return mAdapter.saveState();}@Overridepublic void startUpdate(ViewGroup container) {mAdapter.startUpdate(container);}@Overridepublic void setPrimaryItem(ViewGroup container, int position, Object object) {mAdapter.setPrimaryItem(container, position, object);}}

MainActivity

package com.ly.viewpagerdemo;import android.content.Context;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;public class MainActivity extends AppCompatActivity {private LoopViewPager looviewpager;Context context;int[] resIds = new int[]{R.mipmap.img1, R.mipmap.img2, R.mipmap.img3, R.mipmap.img4, R.mipmap.img5, R.mipmap.img6};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);context = this;looviewpager = (LoopViewPager) findViewById(R.id.looviewpager);looviewpager.setAdapter(new MyAdapter());looviewpager.setOffscreenPageLimit(3);looviewpager.setPageTransformer(true, new ViewPager.PageTransformer() {float scale = 0.9f;@Overridepublic void transformPage(View page, float position) {if (position >= 0 && position <= 1) {page.setScaleY(scale + (1 - scale) * (1 - position));} else if (position > -1 && position < 0) {page.setScaleY(1 + (1 - scale) * position);} else {page.setScaleY(scale);}}});looviewpager.autoLoop(true);}class MyAdapter extends PagerAdapter {@Overridepublic int getCount() {return resIds.length;}@Overridepublic boolean isViewFromObject(View view, Object object) {return view == object;}@Overridepublic Object instantiateItem(ViewGroup container, int position) {View view = View.inflate(context, R.layout.item_viewpager, null);RoundImageView itemImage = (RoundImageView) view.findViewById(R.id.item_image);itemImage.setImageResource(resIds[position]);container.addView(view);return view;}@Overridepublic void destroyItem(ViewGroup container, int position, Object object) {container.removeView((View) object);}}}

ViewPager的setPageTransformer是用来控制view的切换动画的

looviewpager.setPageTransformer(true, new ViewPager.PageTransformer() {float scale = 0.9f;@Overridepublic void transformPage(View page, float position) {if (position >= 0 && position <= 1) {page.setScaleY(scale + (1 - scale) * (1 - position));} else if (position > -1 && position < 0) {page.setScaleY(1 + (1 - scale) * position);} else {page.setScaleY(scale);}}});

参考

Android 三种方式实现圆角ImageView
http://blog.csdn.net/zz7zz7zz/article/details/50602748
仿魅族BannerView,图片轮播控件,支持多种模式切换…
https://github.com/pinguo-zhouwei/MZBannerView
viewpager 左右无限循环
https://github.com/imbryk/LoopingViewPager

源码下载

Android--仿爱奇艺 首页轮播图相关推荐

  1. android高仿奇艺影视,android仿爱奇艺加载动画实例

    本篇文章介绍了android仿爱奇艺加载动画实例,具体代码如下: 效果图: 用到的知识点: Path ValueAnimator 如果对Path和ValueAnimator还不熟悉推荐去看这几个大神的 ...

  2. 爱奇艺首页底部导航按钮android,仿爱奇艺/腾讯视频ViewPager导航条实现

    仿爱奇艺/腾讯视频ViewPager导航条实现,支持自定义导航条高度,宽度,颜色变化,字体大小变化.支持多种滚动模式,支持自定义每个TabView的样式.项目地址:https://github.com ...

  3. Android自定义控件之应用程序首页轮播图

    http://blog.csdn.net/android_jiangjun/article/details/39638129 现在基本上大多数的Android应用程序的首页都有轮播图,就是像下图这样的 ...

  4. 【VIP视频网站项目二】搭建爱奇艺优酷腾讯视频官网首页轮播图效果及实现原理分析

    这个是实现的效果,基本上轮播效果和主流网站的一致,但是我也在上面优化了一些效果, 可以在线预览效果:https://vip.52tech.tech/ 目前项目代码已经全部开源:项目地址:https:/ ...

  5. 仿爱奇艺视频,腾讯视频,搜狐视频首页推荐位轮播图(二)之SuperIndicator源码分析

    转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼:http://blog.csdn.net/hejjunlin/article/details/52510431 背景:仿爱奇艺视频,腾讯视频 ...

  6. 仿爱奇艺视频,腾讯视频,搜狐视频首页推荐位轮播图介绍(一)

    请尊重分享成果,转载请注明出处:http://blog.csdn.net/hejjunlin/article/details/52327435 前言:本篇只是一个介绍这个一个类库,具体实现思路代码会下 ...

  7. Android源码之高仿爱奇艺

    Android源码之高仿爱奇艺  支持平台:Android   运行环境:Eclipse   开发语言:Java 下载地址:http://www.devstore.cn/code/info/306.h ...

  8. Android基础控件——TabLayout的使用、仿爱奇艺导航条

    TabLayout的使用.仿爱奇艺导航条 学习,学习,学以致用,让基础控件贴近实战效果 TabLayout是Google新推出的Material Design的控件之一,TabLayout的使用必须结 ...

  9. html实现视频网站,仿爱奇艺,搜狐,迅雷看看(附源码)

    文章目录 1.功能模板 1.1 仿爱奇艺 1.2 仿搜狐视频 1.3 仿迅雷看看 1.4 视频播放 1.5 影视公司官网 2.效果和源码 2.1 源代码 2.2 模板目录 源码下载 作者:xcLeig ...

最新文章

  1. Slam十四讲(第二版):1、习题
  2. tensorflow 开始——创建定制化 Estimator(创建自定义评估器)
  3. 老男孩爬虫实战密训课第一季,2018.6,初识爬虫训练-实战1-爬取汽车之家新闻数据...
  4. PHP. 02®. Ajax异步处理、常见的响应状态、XMLHttpRequest对象及API、ajax的get/post方法、...
  5. Windows键盘快捷键使用
  6. for循环删除集合陷阱
  7. Program Library HOWTO(1)
  8. 所有浏览器的 CSS selectors 兼容性
  9. python 在图片的指定位置添加文字及图片
  10. 4款微信公众号编辑器,哪个最好用?
  11. 洛谷 P3332 BZOJ 3110 [ZJOI2013]K大数查询
  12. 残差分析(残差原理与标准化残差分析)
  13. (大集合)AI工具和用法汇总—集合的集合
  14. 摄像头水平视野垂直视野?_动物穿越:新视野的梦想更新
  15. Exchange Server 2010邮件撤回条件说明
  16. Apache和Spring提供的StopWatch执行时间监视器
  17. 用51单片机驱动蜂鸣器
  18. 黑马程序员————IO流4(day21)
  19. QGC地面站中视频流配置及gstreamer安装
  20. Apache Hive实战基础

热门文章

  1. 又发现几个有趣实用的网站
  2. ICS4U Summative Project: Hangman
  3. 涂鸦智能Java测评,涂鸦智能java一面面经9.2
  4. 除了路由器,还有什么其他方法可以在宿舍共享网络
  5. 【刷机】给小米8输入PE12
  6. f420、tplink 端口映射
  7. 8月3日第壹简报,星期三,农历七月初六
  8. 1-Wire搜索算法详解(2)
  9. QTA自动化测试框架(二)
  10. 各种ISO 8859字符集