【问题标题】:auto scroll a Gallery widget自动滚动图库小部件
【发布时间】:2011-11-16 16:36:02
【问题描述】:

我需要实现一个画廊,它一次滚动一个项目,并且可以执行“自动滚动”:即每隔几秒钟,它会自动滚动到下一个项目。

根据这个线程:Android: Programmatically animate between images in Gallery widget,我扩展了 Gallery,覆盖了 onFling 以忽略投掷事件,而是模拟向左或向右的 DPAD 箭头,以便一次移动单个项目:

@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
          int kEvent;
          if(isScrollingLeft(e1, e2)){ //Check if scrolling left
            kEvent = KeyEvent.KEYCODE_DPAD_LEFT;
          }
          else{ //Otherwise scrolling right
            kEvent = KeyEvent.KEYCODE_DPAD_RIGHT;
          }
          onKeyDown(kEvent, null);

          return true; 
    }

这很好用。 对于自动滚动,我创建了一个处理程序并 postDelayed 一个 runnable,它以相同的方式模拟相同的 DPAD 按键:

handler.postDelayed(new Runnable() {
    public void run() { 
        onKeyDown(KeyEvent.KEYCODE_DPAD_RIGHT, null);
    }
}, AUTO_SCROLL_INTERVAL);

但这并没有做任何事情!

我知道 runnable 会以正确的时间间隔按预期执行,因为我记录了它并确认了这一点,但 onKeyDown 不会导致画廊滚动或切换项目。 为什么这会以一种方法而不是另一种方法起作用?我试图改为调用我的 onFling,但无济于事。也尝试dispatchKeyEvent,但没有成功。

我真的需要做这件事,但我也真的很想了解为什么相同的代码在两个不同的地方不会产生相同的结果...这与 Android 视图如何处理输入事件有关吗?我查看了画廊代码以寻找线索,但一无所获!似乎它应该可以工作。

拜托,我很难过……有什么想法吗?

谢谢

【问题讨论】:

    标签: android android-widget android-gallery


    【解决方案1】:

    所以,我原来的逻辑确实有效。 实现该逻辑但在我的班级(下)中剥离了所有其他内容的自定义画廊按预期工作,因此它一定是我班级中的其他东西导致了这个问题。

    感谢您的帮助 HighFlyer :)

    至少我了解了反射......这是 Java 的一个非常酷的特性。

    public class CustomGallery extends Gallery {
    
        private Handler handler;
    
        public CustomGallery(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
            handler = new Handler();
            postDelayedScrollNext();
        }
    
        private void postDelayedScrollNext() {
            handler.postDelayed(new Runnable() {
                public void run() {
                    postDelayedScrollNext();
                    Log.d("CustomGallery", "dpad RIGHT");
                    onKeyDown(KeyEvent.KEYCODE_DPAD_RIGHT, null);
                }
            }, 1000);
        }
    
        private boolean isScrollingLeft(MotionEvent e1, MotionEvent e2) {
            return e2.getX() > e1.getX();
        }
    
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            int kEvent;
            if (isScrollingLeft(e1, e2)) {
                Log.d("CustomGallery", "fling LEFT");
                kEvent = KeyEvent.KEYCODE_DPAD_LEFT;
            } else {
                Log.d("CustomGallery", "fling LEFT");
                kEvent = KeyEvent.KEYCODE_DPAD_RIGHT;
            }
            onKeyDown(kEvent, null);
            return true;
        }
    

    【讨论】:

    • 完全不懂。请解释在 onFling 方法中调用 onKeyDown 的结果。您的实施结果是一次只有一项滚动。我只能在 10 小时后编写资源。
    • @noobler 一旦到达最后一张图片,它就会停在那里。如何再次使其移动到第一张图像?我的意思是像画廊中图像的圆周运动。请帮我怎么做。
    【解决方案2】:

    未来访问者请注意:在这种情况下(全视图库),更好的解决方案是使用ViewPager。它像画廊一样工作,但正确地实现了setCurrentItem() 平滑滚动的方法。通过兼容包,它适用于 API 4(Android 1.6!)及更高版本,因此每个人都可以使用它。

    【讨论】:

      【解决方案3】:

      您似乎调用了活动的 onKeyDown 方法,而不是图库。 尝试调用

      gallery.onKeyDown(KeyEvent.KEYCODE_DPAD_RIGHT, null)
      

      相反。 如果我错了,请纠正我

      【讨论】:

      • 抱歉,我的帖子不清楚。处理程序和可运行对象都在我的扩展库中,因此自动滚动逻辑封装在我的自定义视图中。
      • 你说重写 onFling 效果很好。这是什么意思?如果你写 onFling 只返回 true,你仍然可以手动滚动图像。查看 Gallery 小部件codesearch.google.com/codesearch#uX1GffpyOZk/core/java/android/… 的来源并考虑通过反射调用 mFlingRunnable.startUsingDistance 方法
      • 你是对的,滚动仍然以默认方式移动项目,但这对我来说不是问题,因为我的画廊一次显示一个完整的项目(因此用户无法在一个手势中滚动多个项目)。感谢关于反射的建议!我从来没有使用过反射,也不认为可以访问私有方法和类型,但是在谷歌搜索之后,这是可能的!我会尝试走这条路……并发布我的结果。谢谢:)
      • 很高兴为您提供帮助。等待你的结果。
      • 感谢您的帮助 HighFlyer.. 我在上面发布了答案。如果可以的话,我会给你投票:)
      猜你喜欢
      • 1970-01-01
      • 2019-05-23
      • 2011-11-18
      • 2011-01-23
      • 1970-01-01
      • 2012-05-17
      • 1970-01-01
      • 2021-10-18
      • 1970-01-01
      相关资源
      最近更新 更多