android中过度滚动的视觉指示
Posted
技术标签:
【中文标题】android中过度滚动的视觉指示【英文标题】:visual indication of over scroll in android 【发布时间】:2012-06-02 03:59:49 【问题描述】:我正在尝试添加一些视觉指示,即在 ViewPager 中没有更多页面位于所需的投掷方向。但是,我正在努力寻找放置相关代码的地方。
我尝试使用以下代码扩展 ViewPager 类,但 Toast 未显示(ev.getOrientation()
始终返回 0)。我也尝试过使用历史记录点,但ev.getHistorySize()
也返回 0。
我错过了什么?
类示例:
public class CustomViewPager extends ViewPager
public CustomViewPager(Context context)
super(context);
public CustomViewPager(Context context, AttributeSet attrs)
super(context, attrs);
/**
* @see android.support.v4.view.ViewPager#onTouchEvent(android.view.MotionEvent)
*/
@Override
public boolean onTouchEvent(MotionEvent ev)
boolean result = super.onTouchEvent(ev);
switch (ev.getAction() & MotionEventCompat.ACTION_MASK)
case MotionEvent.ACTION_MOVE:
if (ev.getOrientation() > 0)
Toast.makeText(getContext(), "left", 0).show();
return result;
【问题讨论】:
【参考方案1】:如果您查看 v4 支持库,您会看到 ViewPager 使用了一个名为 EdgeEffectCompat 的类(当您到达 ICS+ 中视图寻呼机的开头或结尾时,它会提供发光效果)如果您查看实现在兼容库中,您将看到它有一个 if 语句来查看构建版本是否为 14+ (ICS)。如果是,那么它最终会使用 ICS 中引入的普通 EdgeEffect 类结束(如果您跟踪足够长的时间)。否则它使用 BaseEdgeEffectImpl ,它基本上没有任何内容。
如果您愿意,您可以制作自己的自定义 ViewPager,使用您自己的 EdgeEffect。您可以查看 android 源代码以了解他们如何实现 EdgeEffect here,您几乎可以复制它(只需确保将 AOSP /res/drawable 目录中的 overscroll_edge 和 overscroll_glow drawables 复制到您自己的项目中因为它们是 android 内部的)或继续创建您自己的版本。
祝你好运。
(顺便说一句,这就是他们如何在 ICS 的启动器菜单中创建看起来很酷的边缘倾斜效果......所以你几乎可以尽情发挥创意;)
【讨论】:
这看起来应该这样做!谢谢。【参考方案2】:我试图获得与此问题中提出的完全相同的效果。我为此苦苦挣扎,然后我阅读了@wnafee 的答案(没有它我无法做到)。
但是我很难实现从答案中听起来很简单的东西。 我在实现它时遇到了很多麻烦,以至于我可能没有正确理解答案,但是由于我没有在兼容库的同一个包中工作,所以存在太多无法访问的 API 问题。
在我尝试了一些方法后(没有一个成功,而且它们非常复杂),我转向了一个稍微不同的方向,现在它就像一个魅力。我用了一些反射,没用过的人不用担心,这真的是反射的基础。
我不确定它是否是目前最好的解决方案,但它对我有用,所以如果您想使用它,欢迎您。请阅读 Wnafee 示例,因为它解释了我所做的一些事情。
为了完成这项任务,您只需遵循我的三部分解决方案即可。 (需要 3-10 分钟)
第一部分:
正如 Wnafee 所说,我刚刚通过复制粘贴 here 的源代码制作了自己的 EdgeEffect 类,
(只要确保复制 overscroll_edge 和 overscroll_glow AOSP /res/drawable 目录中的drawables 到你自己的项目 因为它们是 android 内部的)
我只做了 2 个非常小的改动:
-
我声明该类扩展了 EdgeEffectCompat(我将我的类称为
EdgeEffectForEarlyVersions
)。 public class EdgeEffectForEarlyVersions extends EdgeEffectCompat
。进行此更改的原因是 mLeftEdge
和 mRightEdge
的类型为 EdgeEffectCompat
。
在“我的”新类的构造函数的第一行,我添加了对父构造函数super(context);
的调用。由于EdgeEffectCompat
没有默认构造函数,因此您必须显式调用构造函数。
第二部分
除此之外,我还编写了另一个函数。该函数的目的是在早期版本(ICS 之前)的情况下,我们希望使用我们刚刚复制的EdgeEffectForEarlyVersions
。为了达到这个目的,我使用了反射。
这是函数:
private static void changeEdgeEffectCompactOnEarlyVersions(ViewPager viewPager, Context context)
/* In case that the version is earlier than 14 there is only empty implementation for the edge effect, therefore we change it.
* for more information look on the following links:
* 1. http://***.com/questions/10773565/visual-indication-of-over-scroll-in-android
* 2. http://grepcode.com/file/repo1.maven.org/maven2/com.google.android/support-v4/r7/android/support/v4/view/ViewPager.java#ViewPager.0mLeftEdge
* 3. http://grepcode.com/file/repo1.maven.org/maven2/com.google.android/support-v4/r7/android/support/v4/widget/EdgeEffectCompat.java#EdgeEffectCompat
*/
if (Build.VERSION.SDK_INT < 14)
try
Class<ViewPager> viewPagerClass = ViewPager.class;
//Get the left edge field, since it is private we used getDeclaredField and not getDeclared
Field leftEdge = viewPagerClass.getDeclaredField("mLeftEdge");
leftEdge.setAccessible(true);
//Get the right edge field, since it is private we used getDeclaredField and not getDeclared
Field rightEdge = viewPagerClass.getDeclaredField("mRightEdge");
rightEdge.setAccessible(true);
EdgeEffectForEarlyVersions leftEdgeEffect = new EdgeEffectForEarlyVersions(context);
EdgeEffectForEarlyVersions rightEdgeEffect = new EdgeEffectForEarlyVersions(context);
//Set the mLeftEdge memeber of viewPager not to be the default one, but to be "our" edgeEffect
leftEdge.set(viewPager, leftEdgeEffect);
//Set the mRightEdge memeber of viewPager not to be the default one, but to be "our" edgeEffect
rightEdge.set(viewPager, rightEdgeEffect);
catch (Exception ex)
Log.e("refelection", ex.getMessage());
第三部分
现在剩下要做的就是在拥有 ViewPager 实例之后调用该函数,仅此而已。
我希望它会对某人有所帮助。
【讨论】:
这不适用于 API 【参考方案3】:wnafee 很好地解释了解决方案,但对于我们当中的懒惰者,我在很久以前就做了一个实际的工作实现。
https://github.com/inovex/ViewPager3D
如果您只想过度滚动,请看这里:
https://github.com/inovex/ViewPager3D/issues/1
【讨论】:
【参考方案4】:您有很多选择,可以显示 Toast、显示 Dialog、在 UI 上显示 TextView 或图像等。或者因为您知道 ViewPager 中 View 项目的数量,您可以添加不同的在位置 0 和/或 n + 1 处查看消息并使其反弹到实际包含您的数据的最后一个视图。
你可以实现:
viewPager.setOnPageChangeListener(new OnPageChangeListener()
public void onPageSelected(int position)
//TODO If position is the 0 or n item, add a view at 0 or at n+1 to indicate there is no more pages with data.
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels)
// TODO Show a Toast, View or do anything you want when position = your first/last item;
public void onPageScrollStateChanged(int state)
);
【讨论】:
当您尝试滚动到 ViewPager 的末尾时,会出现系统标准的发光效果,这与滚动到列表底部的顶部时相同。我想要这样的东西 - 但它应该适用于所有版本(当前的发光是 ICS-only)。您的建议会使 UI 变得笨拙,如果这些确实是唯一的选择,那么我将坚持不做任何指示。 我知道这对我的应用程序来说已经足够了,但如果@ekramus 问,我认为是因为他需要更多的东西。 :)【参考方案5】:只是为了补充@goBeepit 开发人员的答案,当您创建自己的 edgeffect 类并从 EdgeEffectCompat 扩展时,某些方法需要是布尔值。您可以将这些方法更改为布尔类型,然后在任何情况下都返回 true,这样一切正常
【讨论】:
【参考方案6】:您可以在片段中重载 setUserVisibleHint(boolean) 函数。伪代码:
void setUserVisibleHint(boolean isVisibleToUser)
// If this fragment is becoming visible
if (isVisibleToUser == true)
// Check if it is the last fragment in the viewpager
if (indexOfThis == getActivity().indexOfLast)
// Display right limit reached
Toast(..., "No more Frags to right",...)
// Check if it is the first fragment in the viewpager
else if (indexOfThis == getActivity().indexOfFirst)
// Display Left Limit reached
Toast(..., "No more Frags to left",...)
我没有为此目的使用此功能,但出于其他原因使用它并且它确实可以正常触发。希望这会有所帮助...
【讨论】:
这与 Oscar 的答案具有相同的 UI 含义,只是它覆盖了一个不打算被覆盖的方法,而不是使用侦听器,这似乎很危险。【参考方案7】:我已经基于 Renard 的 ViewPager3D 实现了反弹效果:https://***.com/a/17425468/973379
【讨论】:
【参考方案8】:通常使用 ViewPager,使用 PagerAdapter
(例如 FragmentPagerAdapter
或 FragmentStatePagerAdapter
)来让 ViewPager 充满内容(您的内容将成为视图)。
现在,当您使用PagerAdapter
时,您有一个名为getCount()
、http://developer.android.com/reference/android/support/v4/view/PagerAdapter.html#getCount%28%29 的方法,它将为您提供内容的大小。
从现在开始,知道可以使用 if 控制语句轻松显示消息的大小。
试试这个代码:http://developer.android.com/reference/android/support/v4/view/ViewPager.html
注意:我认为您不需要自定义 ViewPager。您还需要了解 ViewPager 的片段。查看 ApiDemos 中的示例。它是一个很好的来源。
【讨论】:
他不是这么问的。他特别想知道如何在 ios 上制作像橡皮筋一样的过度滚动效果,至少在 ICS 之前,ViewPager 中都没有这种效果。以上是关于android中过度滚动的视觉指示的主要内容,如果未能解决你的问题,请参考以下文章
android - 过度绘制布局允许通过 LinearLayout 进行触摸