Android 使用pk10系统架设RecyclerView实现轮播图
一、需求
ViewPager有个天生的缺陷是View无法重用,此外pk10系统架设详情咨询【企娥166848365】ViewPager的滑动过程会频繁requestLayout,尽管可以通过addViewInLayout和removeViewInLayout配合PagerAdapter 的startUpdate和finishUpdate可以减少重绘,但在ListView和RecyclerView中仍然达不到最好的效果。因此,使用一种新的方式十分必要。
二、代码实现
RecyclerPagerView
public class RecyclerPagerView extends RecyclerView implements Handler.Callback {
private static final long TASK_TIMEOUT = 3000;
public OnPageChangeListener onPageChangeListener;
private final Handler mRecyclerHandler;
private final int MSG_PLAY_NEXT = 112233;
private volatile boolean isPlaying = false;
private boolean lastIsPlayState = false;
private int realPosition = -1;
public RecyclerPagerView(Context context) {
this(context,null);
}
public RecyclerPagerView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}
public RecyclerPagerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mRecyclerHandler = new Handler(Looper.getMainLooper(),this);
}
public void setOnPageChangeListener(OnPageChangeListener onPageChangeListener) {
this.onPageChangeListener = onPageChangeListener;
if(this.onPageChangeListener!=null){
addOnScrollListener(this.onPageChangeListener);
int currentItem = getCurrentItem();
this.onPageChangeListener.onPageSelection(currentItem);
}
}
public int getCurrentItem(){
LinearLayoutManager linearLayoutManager = (LinearLayoutManager) getLayoutManager();
return linearLayoutManager.findFirstVisibleItemPosition();
}
public void setCurrentItem(int position,boolean isAnimate){
Adapter adapter = getAdapter();
if(adapter==null || adapter.getItemCount()<=position){
return;
}
if(!isAnimate)
{
scrollToPosition(position);
}else {
smoothScrollToPosition(position);
}
}
public void setCurrentItem(int position ){
setCurrentItem(position,true);
}
@Override
public boolean fling(int velocityX, int velocityY) {
LinearLayoutManager linearLayoutManager = (LinearLayoutManager) getLayoutManager();
int screenWidth = Resources.getSystem().getDisplayMetrics().widthPixels;
// views on the screen
int lastVisibleItemPosition = linearLayoutManager.findLastVisibleItemPosition();
View lastView = linearLayoutManager.findViewByPosition(lastVisibleItemPosition);
int firstVisibleItemPosition = linearLayoutManager.findFirstVisibleItemPosition();
View firstView = linearLayoutManager.findViewByPosition(firstVisibleItemPosition);
// distance we need to scroll
int leftMargin = (screenWidth - lastView.getWidth()) / 2;
int rightMargin = (screenWidth - firstView.getWidth()) / 2 + firstView.getWidth();
int leftEdge = lastView.getLeft();
int rightEdge = firstView.getRight();
int scrollDistanceLeft = leftEdge - leftMargin;
int scrollDistanceRight = rightMargin - rightEdge;
int targetPosition;
if (Math.abs(velocityX) < 1500) {
// The fling is slow -> stay at the current page if we are less than half through,
// or go to the next page if more than half through
if (leftEdge > screenWidth / 2) {
// go to next page
smoothScrollBy(-scrollDistanceRight, 0);
targetPosition = firstVisibleItemPosition;
} else if (rightEdge < screenWidth / 2) {
// go to next page
smoothScrollBy(scrollDistanceLeft, 0);
targetPosition = firstVisibleItemPosition+1;
} else {
// stay at current page
if (velocityX > 0) {
smoothScrollBy(-scrollDistanceRight, 0);
} else {
smoothScrollBy(scrollDistanceLeft, 0);
}
targetPosition = firstVisibleItemPosition;
}
} else {
// The fling is fast -> go to next page
if (velocityX > 0) {
smoothScrollBy(scrollDistanceLeft, 0);
targetPosition = firstVisibleItemPosition+1;
} else {
smoothScrollBy(-scrollDistanceRight, 0);
targetPosition = firstVisibleItemPosition;
}
}
Log.e("RecyclerPagerView","nextPage="+targetPosition);
if(this.onPageChangeListener!=null){
realPosition = targetPosition;
this.onPageChangeListener.onPageSelection(targetPosition);
}
return true;
}
@Override
public void onScrollStateChanged(final int state) {
super.onScrollStateChanged(state);
if (state == SCROLL_STATE_IDLE) {
LinearLayoutManager linearLayoutManager = (LinearLayoutManager) getLayoutManager();
int screenWidth = Resources.getSystem().getDisplayMetrics().widthPixels;
int lastVisibleItemPosition = linearLayoutManager.findLastVisibleItemPosition();
View lastView = linearLayoutManager.findViewByPosition(lastVisibleItemPosition);
int firstVisibleItemPosition = linearLayoutManager.findFirstVisibleItemPosition();
View firstView = linearLayoutManager.findViewByPosition(firstVisibleItemPosition);
// distance we need to scroll
int leftMargin = (screenWidth - lastView.getWidth()) / 2;
int rightMargin = (screenWidth - firstView.getWidth()) / 2 + firstView.getWidth();
int leftEdge = lastView.getLeft();
int rightEdge = firstView.getRight();
int scrollDistanceLeft = leftEdge - leftMargin;
int scrollDistanceRight = rightMargin - rightEdge;
int targetPosition = -1;
if (leftEdge > screenWidth / 2) {
smoothScrollBy(-scrollDistanceRight, 0);
targetPosition = firstVisibleItemPosition+1;
} else if (rightEdge < screenWidth / 2) {
smoothScrollBy(scrollDistanceLeft, 0);
targetPosition = lastVisibleItemPosition;
}else{
targetPosition = firstVisibleItemPosition;
}
if(this.onPageChangeListener!=null){
realPosition = targetPosition;
this.onPageChangeListener.onPageSelection(targetPosition);
}
}
}
@Override
public boolean handleMessage(Message msg) {
int what = msg.what;
switch (what){
case MSG_PLAY_NEXT:
showNextPage();
break;
}
return false;
}
private void showNextPage() {
if(!isPlaying){
return;
}
if(!canRecyclePlaying()){
isPlaying = false;
return;
}
Adapter adapter = getAdapter();
int currentItem = getCurrentItem();
if(adapter!=null && adapter.getItemCount()>0) {
if (currentItem == NO_POSITION ) {
setCurrentItem(0);
}else {
setCurrentItem(currentItem+1);
}
}
mRecyclerHandler.sendEmptyMessageDelayed(MSG_PLAY_NEXT,TASK_TIMEOUT);
}
public void startPlay(){
if(isPlaying){
stopPlay();
}
if (!canRecyclePlaying()){
isPlaying = false;
return;
}
isPlaying = true;
mRecyclerHandler.sendEmptyMessageDelayed(MSG_PLAY_NEXT,TASK_TIMEOUT);
}
@Override
public void setAdapter(Adapter adapter) {
super.setAdapter(adapter);
if(canRecyclePlaying()){
if(realPosition==-1){
realPosition = 1000;
}
setCurrentItem(realPosition,false);
}
}
private boolean canRecyclePlaying() {
Adapter adapter = getAdapter();
if(adapter==null || adapter.getItemCount()<1) return false;
return true;
}
private void stopPlay() {
isPlaying = false;
mRecyclerHandler.removeMessages(MSG_PLAY_NEXT);
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if(lastIsPlayState){
startPlay();
}
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
lastIsPlayState = isPlaying;
stopPlay();
}
public static abstract class OnPageChangeListener extends RecyclerView.OnScrollListener{
public abstract void onPageSelection(int position);
}
}
Adapter+Holder 适配器
该类的作用主要用于约束和快速接入
public class QuickViewHolder extends RecyclerView.ViewHolder{
private SparseArray<View> mViews;
private View mConvertView;
private QuickViewHolder(View v){
super(v);
mConvertView = v;
mViews = new SparseArray<>();
}
public static QuickViewHolder get(ViewGroup parent, int layoutId){
View convertView = LayoutInflater.from(parent.getContext()).inflate(layoutId, parent, false);
return new QuickViewHolder(convertView);
}
public <T extends View> T getView(int id){
View v = mViews.get(id);
if(v == null){
v = mConvertView.findViewById(id);
mViews.put(id, v);
}
return (T)v;
}
}
BannerAdapter实现,该类继承QuickAdapter
public class BannerAdapter extends QuickAdapter<String> {
public BannerAdapter(List<String> datas) {
super(datas);
}
@Override
public int getLayoutId(int viewType) {
return R.layout.item_banner_image;
}
@Override
public void convert(QuickViewHolder holder, String url, int position) {
final Resources resources = holder.itemView.getResources();
final int drawableId = resources.getIdentifier(url, "drawable", holder.itemView.getContext().getPackageName());
if(drawableId!=0) {
ImageView bannerImage = holder.getView(R.id.banner_image_item);
bannerImage.setImageResource(drawableId);
}
}
}
三、使用
final RecyclerPagerView rpv = findViewById(R.id.recycler_pager);
tipTextView = findViewById(R.id.tip_text);
LinearLayoutManager lm = new LinearLayoutManager(this,LinearLayoutManager.HORIZONTAL,false);
rpv.setLayoutManager(lm);
List<String> imagelist = new ArrayList<>();
imagelist.add("banner_t1");
imagelist.add("banner_t2");
imagelist.add("banner_t3");
imagelist.add("banner_t4");
rpv.setAdapter(new BannerAdapter(imagelist));
rpv.setOnPageChangeListener(new PagerChangeListener(tipTextView,imagelist.size()));
rpv.startPlay();
监听器
public static class PagerChangeListener extends RecyclerPagerView.OnPageChangeListener {
private TextView tipTextView;
private int size;
public PagerChangeListener(TextView tipTextView,int size) {
this.tipTextView = tipTextView;
this.size = size;
}
@Override
public void onPageSelection(int position) {
tipTextView.setText((position%size+1)+"/"+size);
}
}
Android 使用pk10系统架设RecyclerView实现轮播图的更多相关文章
- Android开发之ViewPager实现轮播图(轮播广告)效果的自定义View
最近开发中需要做一个类似京东首页那样的广告轮播效果,于是采用ViewPager自己自定义了一个轮播图效果的View. 主要原理就是利用定时任务器定时切换ViewPager的页面. 效果图如下: 主页面 ...
- 小程序实践(二):swiper组件实现轮播图效果
swiper组件类似于Android中的ViewPager,实现类似轮播图的效果,相对于Android的Viewpager,swiper实现起来更加方便,快捷. 效果图: 首先看下swiper支持的属 ...
- Android零基础入门第56节:翻转视图ViewFlipper打造引导页和轮播图
原文:Android零基础入门第56节:翻转视图ViewFlipper打造引导页和轮播图 前面两期学习了 ViewAnimator及其子类ViewSwitcher的使用,以及ViewSwitcher的 ...
- 从零开始,搭建博客系统MVC5+EF6搭建框架(5),博客详情页、留言、轮播图管理、右侧统计博文
一.博客系统进度回顾 上一遍博客介绍到,系统已经实现到了发布以及前台布局展示,接下来就是实现一些,详情页,留言.轮播图管理.右侧博文统计信息实现. 二.博客系统详情页实现 2.1先来看看详情页展示的效 ...
- Android自定义控件之轮播图控件
背景 最近要做一个轮播图的效果,网上看了几篇文章,基本上都能找到实现,效果还挺不错,但是在写的时候感觉每次都要单独去重新在Activity里写一堆代码.于是自己封装了一下.本篇轮播图实现原理原文出处: ...
- Android ViewPager轮播图
Android客户端开发中很多时候需要用到轮播图的方式进行重点新闻的推送或者欢迎页面的制作,下面这个轮播图效果的Deamo来自互联网再经过修改而成. 1.布局文件activity_main.xml中添 ...
- android中广告轮播图总结
功能点:无限轮播.指示点跟随.点击响应.实现思路: 1.指示点跟随,指示点通过代码动态添加,数量由图片数量决定. 在viewpager的页面改变监听中,设置点的状态选择器enable,当前页时,set ...
- android项目实战 --ListView 头部ViewPager广告轮询图效果
看开源框架:https://github.com/tianshaojie/AndroidFine,里面有如下效果,特记录学习下,以后项目中用也好能够立刻想起来. 如上面所示,是常见项目中的图片轮训 ...
- Android 轮播图Banner切换图片的效果
Android XBanner使用详解 2018年03月14日 08:19:59 AND_Devil 阅读数:910 版权声明:本文为博主原创文章,未经博主允许不得转载. https://www. ...
随机推荐
- Django学习---cookie和session
cookie 客户端浏览器上的一个文件,以键值对的形式存储,如{“user”:“dacehgnzi”} 入门:实现一个简单的登录功能 views.py: user_info = { '}, '}, } ...
- Linux下安装php的memcached扩展(memcache的客户端)
php的扩展memcache,不支持cas,所以我们要装memcached扩展,memcached扩展是基于libmemcached,所以要先安装libmemcached 一.下载软件 1.libme ...
- 一个进程间同步和通讯的 C# 框架
转自原文 一个进程间同步和通讯的 C# 框架 threadmsg_demo.zip ~ 41KB 下载 threadmsg_src.zip ~ 65KB 下载 0.背景简介 微软在 .NE ...
- delphi 选择文件夹,路径选择,浏览文件夹
选择文件夹,路径选择, 文件夹 资源管理器 推荐 SelectDirectory http://docwiki.embarcadero.com/Libraries/Seattle/en/Vcl.Fi ...
- Django 获取时间 和Linux 本地 系统时间 不一致
问题描述 Django 中获取的本地时间 ,和系统时间不一致 错误原因 Django在配置文件settings.py 中 默认配置 UTC世界标准时间,而北京时间是东八区,比UTC时间早8个小时. T ...
- UINavigation,UiView,ModalView Controller之间的关系
如果当前是个VC,那么就太简单了,直接就可以push到下一个vc AddShopViewController *controller = [[AddShopViewController alloc] ...
- 从socket开始讲IOS网络编程
home list tags talk user rss Mac&iOS Socket 大纲 一.Socket简介 二.BSD Socket编程准备 1.地址 2.端口 3.网络字节序 4.半 ...
- 【原】Coursera—Andrew Ng机器学习—课程笔记 Lecture 10—Advice for applying machine learning 机器学习应用建议
Lecture 10—Advice for applying machine learning 10.1 如何调试一个机器学习算法? 有多种方案: 1.获得更多训练数据:2.尝试更少特征:3.尝试更多 ...
- WCF配置多个终节点
配置多个终节点的意义(自己理解):一个服务可以有多个终节点,网上也经常有人说终节点才是服务的真正的接口,的确如此,当我们为一个服务配置多个终节点时,就表明这个服务可以被以不同的方式访问(不同的绑定等等 ...
- 反射与dynamic
反射 var a = Assembly.GetExecutingAssembly(); Type type = a.GetType("CLRTest.ReflectClass"); ...