热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

[置顶]ViewPager实现Galler效果,中间大图显示,两边小图展示(优化篇)

上一张效果图:之前的项目有一个Galley的项目,但是代码结构特别乱,别问我为什么,我也是刚接手这个项目,为了方便以后阅读和维护我对一些模块进行了重构。ViewPager实现Galler效果,但是当时

上一张效果图:

之前的项目有一个Galley的项目,但是代码结构特别乱,别问我为什么,我也是刚接手这个项目,为了方便以后阅读和维护我对一些模块进行了重构。ViewPager实现Galler效果,但是当时时间比较急,写的比较仓促,上一篇实现了简单的效果,但是对于初始的时候左边滑动是有问题的,这是因为我们在自己的Adapter的时候对于getCount,我们想通过Integer.MAX_VALUE来实现无限循环,简单的说这个是向右(无限大)吧,所以也就只是实现了向右的循环,对于像左的还是不行的。

那么怎么解决呢?

首先我们对Adapter还是需要按以前的写法,其实Adapter适配器就是帮我们做界面的,其他的逻辑最好不要加,我之前的想法是用过

viewPager.addOnPageChangeListener来实现,通过判断是否滑到最左边或者最右边来实现循环滑到。
 int realPosition = mAdapter.toRealPosition(position);            if (mPreviousPosition != realPosition) {                mPreviousPosition = realPosition;                if (mOuterPageChangeListener != null) {                    mOuterPageChangeListener.onPageSelected(realPosition);                }            }

这里我封装了一个类,只要将你的ViewPager改为我封装好的ViewPager就行
LoopViewPager 
public class LoopViewPager extends ViewPager {    private static final boolean DEFAULT_BOUNDARY_CASHING = false;    private OnPageChangeListener mOuterPageChangeListener;    private LoopPagerAdapterWrapper mAdapter;    private boolean mBoundaryCaching = DEFAULT_BOUNDARY_CASHING;    public static int toRealPosition( int position, int count ){        position = position-1;        if( position <0 ){            position += count;        }else{            position = position%count;        }        return position;    }        public void setBoundaryCaching(boolean flag) {        mBoundaryCaching = flag;        if (mAdapter != null) {            mAdapter.setBoundaryCaching(flag);        }    }    @Override    public void setAdapter(PagerAdapter adapter) {        mAdapter = new LoopPagerAdapterWrapper(adapter);        mAdapter.setBoundaryCaching(mBoundaryCaching);        super.setAdapter(mAdapter);        setCurrentItem(0, false);    }    @Override    public PagerAdapter getAdapter() {        return mAdapter != null ? mAdapter.getRealAdapter() : mAdapter;    }    @Override    public int getCurrentItem() {        return mAdapter != null ? mAdapter.toRealPosition(super.getCurrentItem()) : 0;    }    public void setCurrentItem(int item, boolean smoothScroll) {        int realItem = mAdapter.toInnerPosition(item);        super.setCurrentItem(realItem, smoothScroll);    }    @Override    public void setCurrentItem(int item) {        if (getCurrentItem() != item) {            setCurrentItem(item, true);        }    }    @Override    public 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);    }    private OnPageChangeListener OnPageChangeListener= new OnPageChangeListener() {        private float mPreviousOffset = -1;        private float mPreviousPosition = -1;        @Override        public void onPageSelected(int position) {            int realPosition = mAdapter.toRealPosition(position);            if (mPreviousPosition != realPosition) {                mPreviousPosition = realPosition;                if (mOuterPageChangeListener != null) {                    mOuterPageChangeListener.onPageSelected(realPosition);                }            }        }        @Override        public 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);                    }                }            }        }        @Override        public void onPageScrollStateChanged(int state) {            if (mAdapter != null) {                int position = LoopViewPager.super.getCurrentItem();                int realPosition = mAdapter.toRealPosition(position);                if (state == ViewPager.SCROLL_STATE_IDLE                        && (position == 0 || position == mAdapter.getCount() - 1)) {                    setCurrentItem(realPosition, false);                }            }            if (mOuterPageChangeListener != null) {                mOuterPageChangeListener.onPageScrollStateChanged(state);            }        }    };}

LoopPagerAdapterWrapper
public class LoopPagerAdapterWrapper extends PagerAdapter {    private PagerAdapter mAdapter;    private SparseArray mToDestroy = new SparseArray();    private boolean mBoundaryCaching;    void setBoundaryCaching(boolean flag) {        mBoundaryCaching = flag;    }    LoopPagerAdapterWrapper(PagerAdapter adapter) {        this.mAdapter = adapter;    }    @Override    public void notifyDataSetChanged() {        mToDestroy = new SparseArray();        super.notifyDataSetChanged();    }    int toRealPosition(int position) {        int realCount = getRealCount();        if (realCount == 0)            return 0;        int realPosition = (position-1) % realCount;        if (realPosition <0)            realPosition += realCount;        return realPosition;    }    public int toInnerPosition(int realPosition) {        int position = (realPosition + 1);        return position;    }    private int getRealFirstPosition() {        return 1;    }    private int getRealLastPosition() {        return getRealFirstPosition() + getRealCount() - 1;    }    @Override    public int getCount() {        return mAdapter.getCount() + 2;    }    public int getRealCount() {        return mAdapter.getCount();    }    public PagerAdapter getRealAdapter() {        return mAdapter;    }    @Override    public Object instantiateItem(ViewGroup container, int position) {        int realPosition = (mAdapter instanceof FragmentPagerAdapter || mAdapter instanceof FragmentStatePagerAdapter)                ? position                : toRealPosition(position);        if (mBoundaryCaching) {            ToDestroy toDestroy = mToDestroy.get(position);            if (toDestroy != null) {                mToDestroy.remove(position);                return toDestroy.object;            }        }        return mAdapter.instantiateItem(container, realPosition);    }    @Override    public void destroyItem(ViewGroup container, int position, Object object) {        int realFirst = getRealFirstPosition();        int realLast = getRealLastPosition();        int realPosition = (mAdapter instanceof FragmentPagerAdapter || mAdapter instanceof FragmentStatePagerAdapter)                ? position                : toRealPosition(position);        if (mBoundaryCaching && (position == realFirst || position == realLast)) {            mToDestroy.put(position, new ToDestroy(container, realPosition,                    object));        } else {            mAdapter.destroyItem(container, realPosition, object);        }    }    @Override    public void finishUpdate(ViewGroup container) {        mAdapter.finishUpdate(container);    }    @Override    public boolean isViewFromObject(View view, Object object) {        return mAdapter.isViewFromObject(view, object);    }    @Override    public void restoreState(Parcelable bundle, ClassLoader classLoader) {        mAdapter.restoreState(bundle, classLoader);    }    @Override    public Parcelable saveState() {        return mAdapter.saveState();    }    @Override    public void startUpdate(ViewGroup container) {        mAdapter.startUpdate(container);    }    @Override    public void setPrimaryItem(ViewGroup container, int position, Object object) {        mAdapter.setPrimaryItem(container, position, object);    }    static class ToDestroy {        ViewGroup container;        int position;        Object object;        public ToDestroy(ViewGroup container, int position, Object object) {            this.cOntainer= container;            this.position = position;            this.object = object;        }    }}

这里需要注意对于上一篇的WelfareAdapter ,我们就按常规写法就行。
public class WelfareAdapter extends PagerAdapter {    private Context mContext;    private List dataList = new ArrayList<>();    public WelfareAdapter(Context mContext) {        this.mCOntext= mContext;    }    public void setDatas(List list) {        if (list.size() <= 0) {            dataList.clear();            notifyDataSetChanged();            return;        }        dataList.clear();        dataList.addAll(list);        notifyDataSetChanged();    }    @Override    public int getCount() {        return /*Integer.MAX_VALUE*/dataList.size();    }    @Override    public int getItemPosition(Object object) {        return POSITION_NONE;    }    @Override    public void destroyItem(View container, int position, Object object) {    }    @Override    public Object instantiateItem(ViewGroup container, int position) {//        position %= dataList.size();//        if (position<0){//            position = dataList.size()+position;//        }            PanicBean data = dataList.get(position);            ViewHolder viewHolder = null;            View view = LayoutInflater.from(mContext).inflate(                    R.layout.item_finefare_layout, null);            if (viewHolder == null) {                viewHolder = new ViewHolder(view);            }            bindView(viewHolder, data);            container.addView(view, LayoutParams.MATCH_PARENT,                    LayoutParams.MATCH_PARENT);            return view;    }    private void bindView(ViewHolder viewholder, final PanicBean data) {        Glide.with(mContext).load(data.pic).into(viewholder.welfareImage);        viewholder.welfareImage.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                ToastUtils.showToast("你点击了"+data.href);            }        });    }    @Override    public boolean isViewFromObject(View view, Object object) {        return view == object;    }    @Override    public void destroyItem(ViewGroup container, int position, Object object) {        container.removeView((View) object);    }    class ViewHolder {        @BindView(R.id.welfare_image)        RoundedImageView welfareImage;        ViewHolder(View view) {            ButterKnife.bind(this, view);            view.setTag(this);        }        public void reset() {            welfareImage.setBackground(mContext.getResources().getDrawable(R.drawable.welfare_default_icon));        }    }}

部分源码:https://github.com/xiangzhihong/jingdongApp



推荐阅读
  • 本文介绍了一种自定义的Android圆形进度条视图,支持在进度条上显示数字,并在圆心位置展示文字内容。通过自定义绘图和组件组合的方式实现,详细展示了自定义View的开发流程和关键技术点。示例代码和效果展示将在文章末尾提供。 ... [详细]
  • 【问题】在Android开发中,当为EditText添加TextWatcher并实现onTextChanged方法时,会遇到一个问题:即使只对EditText进行一次修改(例如使用删除键删除一个字符),该方法也会被频繁触发。这不仅影响性能,还可能导致逻辑错误。本文将探讨这一问题的原因,并提供有效的解决方案,包括使用Handler或计时器来限制方法的调用频率,以及通过自定义TextWatcher来优化事件处理,从而提高应用的稳定性和用户体验。 ... [详细]
  • 使用 ListView 浏览安卓系统中的回收站文件 ... [详细]
  • 深入解析 Android 中 EditText 的 getLayoutParams 方法及其代码应用实例 ... [详细]
  • ButterKnife 是一款用于 Android 开发的注解库,主要用于简化视图和事件绑定。本文详细介绍了 ButterKnife 的基础用法,包括如何通过注解实现字段和方法的绑定,以及在实际项目中的应用示例。此外,文章还提到了截至 2016 年 4 月 29 日,ButterKnife 的最新版本为 8.0.1,为开发者提供了最新的功能和性能优化。 ... [详细]
  • 在分析和解决 Keepalived VIP 漂移故障的过程中,我们发现主备节点配置如下:主节点 IP 为 172.16.30.31,备份节点 IP 为 172.16.30.32,虚拟 IP 为 172.16.30.10。故障表现为监控系统显示 Keepalived 主节点状态异常,导致 VIP 漂移到备份节点。通过详细检查配置文件和日志,我们发现主节点上的 Keepalived 进程未能正常运行,最终通过优化配置和重启服务解决了该问题。此外,我们还增加了健康检查机制,以提高系统的稳定性和可靠性。 ... [详细]
  • 在Android开发中,当TextView的高度固定且内容超出时,可以通过设置其内置的滚动条属性来实现垂直滚动功能。具体来说,可以通过配置`android:scrollbars="vertical"`来启用垂直滚动,确保用户能够查看完整的内容。此外,为了优化用户体验,建议结合`setMovementMethod(ScrollerMovementMethod.getInstance())`方法,使滚动操作更加流畅和自然。 ... [详细]
  • C++ 异步编程中获取线程执行结果的方法与技巧及其在前端开发中的应用探讨
    本文探讨了C++异步编程中获取线程执行结果的方法与技巧,并深入分析了这些技术在前端开发中的应用。通过对比不同的异步编程模型,本文详细介绍了如何高效地处理多线程任务,确保程序的稳定性和性能。同时,文章还结合实际案例,展示了这些方法在前端异步编程中的具体实现和优化策略。 ... [详细]
  • 在处理 XML 数据时,如果需要解析 `` 标签的内容,可以采用 Pull 解析方法。Pull 解析是一种高效的 XML 解析方式,适用于流式数据处理。具体实现中,可以通过 Java 的 `XmlPullParser` 或其他类似的库来逐步读取和解析 XML 文档中的 `` 元素。这样不仅能够提高解析效率,还能减少内存占用。本文将详细介绍如何使用 Pull 解析方法来提取 `` 标签的内容,并提供一个示例代码,帮助开发者快速解决问题。 ... [详细]
  • 在Android开发中,BroadcastReceiver(广播接收器)是一个重要的组件,广泛应用于多种场景。本文将深入解析BroadcastReceiver的工作原理、应用场景及其具体实现方法,帮助开发者更好地理解和使用这一组件。通过实例分析,文章详细探讨了静态广播的注册方式、生命周期管理以及常见问题的解决策略,为开发者提供全面的技术指导。 ... [详细]
  • 在Android应用开发中,实现与MySQL数据库的连接是一项重要的技术任务。本文详细介绍了Android连接MySQL数据库的操作流程和技术要点。首先,Android平台提供了SQLiteOpenHelper类作为数据库辅助工具,用于创建或打开数据库。开发者可以通过继承并扩展该类,实现对数据库的初始化和版本管理。此外,文章还探讨了使用第三方库如Retrofit或Volley进行网络请求,以及如何通过JSON格式交换数据,确保与MySQL服务器的高效通信。 ... [详细]
  • Squaretest:自动生成功能测试代码的高效插件
    本文将介绍一款名为Squaretest的高效插件,该工具能够自动生成功能测试代码。使用这款插件的主要原因是公司近期加强了代码质量的管控,对各项目进行了严格的单元测试评估。Squaretest不仅提高了测试代码的生成效率,还显著提升了代码的质量和可靠性。 ... [详细]
  • 在Android开发中,实现多点触控功能需要使用`OnTouchListener`监听器来捕获触摸事件,并在`onTouch`方法中进行详细的事件处理。为了优化多点触控的交互体验,开发者可以通过识别不同的触摸手势(如缩放、旋转等)并进行相应的逻辑处理。此外,还可以结合`MotionEvent`类提供的方法,如`getPointerCount()`和`getPointerId()`,来精确控制每个触点的行为,从而提升用户操作的流畅性和响应性。 ... [详细]
  • Spring Boot 应用中实现观察者模式的深度解析与实践
    在 Spring Boot 应用中,观察者模式是一种常用的设计模式,用于建立对象间的依赖关系。当某一对象的状态发生改变时,所有依赖该对象的对象会自动接收到通知并进行相应的更新。本文将深入探讨观察者模式的实现原理,并通过具体实例展示如何在 Spring Boot 项目中有效应用这一模式,以提高系统的解耦性和可维护性。 ... [详细]
  • 本文详细探讨了MySQL数据库实例化参数的优化方法及其在实例查询中的应用。通过具体的源代码示例,介绍了如何高效地配置和查询MySQL实例,为开发者提供了有价值的参考和实践指导。 ... [详细]
author-avatar
392399224_619416
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有