gpt4 book ai didi

android - 修复圆形 ViewPager 的动画

转载 作者:可可西里 更新时间:2023-11-01 18:48:26 28 4
gpt4 key购买 nike

目标

构建一个圆形的 ViewPager。

第一个元素可让您达到最后一个元素并滑动到它,反之亦然。您应该能够永远向任一方向滑动。

现在这已经完成了,但是这些问题对我的实现不起作用。这里有一些供引用:

  • how to create circular viewpager?
  • ViewPager as a circular queue / wrapping
  • https://github.com/antonyt/InfiniteViewPager

  • 我如何尝试解决问题

    我们将使用大小为 7 的数组作为示例。要素如下:
    [0][1][2][3][4][5][6]

    当您在元素 0 处时,ViewPagers 不会让您向左滑动!多么糟糕:(。为了解决这个问题,我在前端和后端添加了 1 个元素。
       [0][1][2][3][4][5][6]      // Original
    [0][1][2][3][4][5][6][7][8] // New mapping

    当 ViewPageAdapter 请求 (instantiateItem()) 元素 0 时,我们返回元素 7。当 ViewPageAdapter 请求元素 8 时,我们返回元素 1。

    同样在 ViewPager 的 OnPageChangeListener 中,当 onPageSelected 被调用时为 0,我们设置了当前项(7),当它被调用时为 8,我们设置了当前项(1)。

    这有效。

    问题

    当您从 1 向左滑动到 0 并且我们 setCurrentItem(7) 时,它会一直向右移动 6 个全屏。这并没有给出圆形 ViewPager 的外观,它给出了在用户通过滑动 Action 请求的相反方向冲向最后一个元素的外观!

    这是非常非常刺耳的。

    我是如何尝试解决这个问题的

    我的第一个倾向是关闭平滑(即所有)动画。它好一点,但是当您从最后一个元素移动到第一个元素时,它现在会断断续续,反之亦然。

    然后我制作了自己的Scroller。

    http://developer.android.com/reference/android/widget/Scroller.html

    我发现在元素之间移动时总是有 1 次调用 startScroll(), 除了 当我从 1 移到 7 和 7 移到 1 时。

    第一个调用是方向和数量的正确动画。

    第二个调用是将所有内容向右移动多个页面的动画。

    这就是事情变得非常棘手的地方。

    我认为解决方案是跳过第二个动画。所以我做了。发生的是一个从 1 到 7 的平滑动画,有 0 个打嗝。完美的!然而,如果你滑动,甚至点击屏幕,你会突然(没有动画)在元素 6!如果您从 7 滑动到 1,您实际上将位于元素 2。没有对 setCurrentItem(2) 的调用,甚至没有对 OnPageChangeListener 的调用表明您在任何时间点都到达了 2。

    但你实际上并不在元素 2,这很好。您仍处于元素 1,但将显示元素 2 的 View 。然后当你向左滑动时,你会转到元素 1。即使你真的已经在元素 1.. 一些代码来帮助清理事情怎么样:

    动画坏了,但没有奇怪的副作用
    @Override
    public void startScroll(int startX, int startY, int dx, int dy, int duration) {
    super.startScroll(startX, startY, dx, dy, duration);
    }

    动画作品!但一切都是陌生而可怕的...
    @Override
    public void startScroll(int startX, int startY, int dx, int dy, int duration) {
    if (dx > 480 || dx < -480) {
    } else {
    super.startScroll(startX, startY, dx, dy, duration);
    }
    }

    唯一的区别是当第二个动画(大于 480 像素屏幕的宽度)被调用时,我们忽略它。

    在阅读了 Scroller 的 Android 源代码后,我发现 startScroll 并没有开始滚动任何东西。它设置要滚动的所有数据,但不启动任何内容。

    我的预感

    当您执行循环操作(1 到 7 或 7 到 1)时,会调用两次 startScroll()。我认为这两个电话之间的某些事情引起了问题。
  • 用户从元素 1 滚动到元素 7 导致从 0 跳转到 7。这​​应该向左移动。
  • 调用 startScroll() 指示左侧的短动画。
  • 可能发生了让我哭的事情,我认为
  • 调用 startScroll() 指示 动画到 .
  • 出现右侧的长动画。

  • 如果我注释掉 4,那么 5 就会变成“左边的正确动画短,事情变得疯狂”

    摘要

    我的 Circular ViewPager 实现有效,但动画坏了。在尝试修复动画时,它破坏了 ViewPager 的功能。我目前正在旋转我的轮子,试图弄清楚如何让它工作。帮我! :)

    如果有什么不清楚的,请在下面评论,我会澄清。我意识到我对事情是如何被破坏的不是很准确。这很难描述,因为我什至不清楚我在屏幕上看到了什么。如果我的解释是一个问题,我可以解决它,请告诉我!

    干杯,
    柯尔廷

    代码

    尽管功能与我当前的代码迭代相同,但此代码稍作修改以使其本身更具可读性。

    OnPageChangeListener.onPageSelected
    @Override
    public void onPageSelected(int _position) {
    boolean animate = true;
    if (_position < 1) {
    // Swiping left past the first element, go to element (9 - 2)=7
    setCurrentItem(getAdapter().getCount() - 2, animate);
    } else if (_position >= getAdapter().getCount() - 1) {
    // Swiping right past the last element
    setCurrentItem(1, animate);
    }
    }

    CircularScroller.startScroll
    @Override
    public void startScroll(int _startX, int _startY, int _dx, int _dy, int _duration) {
    // 480 is the width of the screen
    if (dx > 480 || dx < -480) {
    // Doing nothing in this block shows the correct animation,
    // but it causes the issues mentioned above

    // Uncomment to do the big scroll!
    // super.startScroll(_startX, _startY, _dx, _dy, _duration);

    // lastDX was to attempt to reset the scroll to be the previous
    // correct scroll distance; it had no effect
    // super.startScroll(_startX, _startY, lastDx, _dy, _duration);
    } else {
    lastDx = _dx;
    super.startScroll(_startX, _startY, _dx, _dy, _duration);
    }
    }

    CircularViewPageAdapter.CircularViewPageAdapter
    private static final int m_Length = 7; // For our example only
    private static Context m_Context;
    private boolean[] created = null; // Not the best practice..

    public CircularViewPageAdapter(Context _context) {
    m_Context = _context;
    created = new boolean[m_Length];
    for (int i = 0; i < m_Length; i++) {
    // So that we do not create things multiple times
    // I thought this was causing my issues, but it was not
    created[i] = false;
    }
    }

    CircularViewPageAdapter.getCount
    @Override
    public int getCount() {
    return m_Length + 2;
    }

    CircularViewPageAdapter.instantiateItem
    @Override
    public Object instantiateItem(View _collection, int _position) {

    int virtualPosition = getVirtualPosition(_position);
    if (created[virtualPosition - 1]) {
    return null;
    }

    TextView tv = new TextView(m_Context);
    // The first view is element 1 with label 0! :)
    tv.setText("Bonjour, merci! " + (virtualPosition - 1));
    tv.setTextColor(Color.WHITE);
    tv.setTextSize(30);

    ((ViewPager) _collection).addView(tv, 0);

    return tv;
    }

    CircularViewPageAdapter.destroyItem
    @Override
    public void destroyItem(ViewGroup container, int position, Object view) {
    ViewPager viewPager = (ViewPager) container;
    // If the virtual distance is distance 2 away, it should be destroyed.
    // If it's not intuitive why this is the case, please comment below
    // and I will clarify
    int virtualDistance = getVirtualDistance(viewPager.getCurrentItem(), getVirtualPosition(position));
    if ((virtualDistance == 2) || ((m_Length - virtualDistance) == 2)) {
    ((ViewPager) container).removeView((View) view);
    created[getVirtualPosition(position) - 1] = false;
    }
    }

    最佳答案

    我认为最好的可行方法是而不是使用普通列表来对列表进行包装,当 获取(位置)执行方法来获取创建 View 的对象,你做这样的事情 get(pos % numberOfViews) 当它询问列表的大小时,您输入的列表是 整数.MAX_VALUE 并且你在它的中间开始你的列表,所以你可以说几乎不可能有错误,除非他们实际上向同一侧滑动直到到达列表的末尾。如果时间允许,我将尝试稍后发布一个概念证明,这个很弱。

    编辑:

    我已经尝试过这段代码,我知道每个 View 上都显示了一个简单的文本框,但事实是它工作得很好,根据 View 的总量,它可能会变慢,但概念证明在这里。我所做的是 MAX_NUMBER_VIEWS 表示用户在停止之前可以完全给出的最大次数。正如您所看到的,我在数组的长度处启动了 viewpager,这将是它第二次出现,因此您可以向左和向右多转一圈,但您可以根据需要更改它。我希望我不会因为一个实际上有效的解决方案而得到更多的负面评价。

    Activity :

    pager = (ViewPager)findViewById(R.id.viewpager);
    String[] articles = {"ARTICLE 1","ARTICLE 2","ARTICLE 3","ARTICLE 4"};
    pager.setAdapter(new ViewPagerAdapter(this, articles));
    pager.setCurrentItem(articles.length);

    适配器:
    public class ViewPagerAdapter extends PagerAdapter {

    private Context ctx;
    private String[] articles;
    private final int MAX_NUMBER_VIEWS = 3;

    public ViewPagerAdapter(Context ctx, String[] articles) {
    this.ctx = ctx;
    this.articles = articles.clone();
    }

    @Override
    public int getCount() {
    return articles.length * this.MAX_NUMBER_VIEWS;
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
    TextView view = new TextView(ctx);
    view.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
    LayoutParams.MATCH_PARENT));
    int realPosition = position % articles.length;
    view.setText(this.articles[realPosition]);
    ((ViewPager) container).addView(view);
    return view;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
    ((ViewPager) container).removeView((View) object);
    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
    return view == ((View) object);
    }

    @Override
    public Parcelable saveState() {
    return null;
    }

    }

    关于android - 修复圆形 ViewPager 的动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11622544/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com