【问题标题】:How to add scrolling for a custom view in Android如何在 Android 中为自定义视图添加滚动
【发布时间】:2016-09-03 14:48:46
【问题描述】:

我刚刚开始(第一次)在 Android 中编写自定义视图,我意识到我需要实现滚动功能。

自定义视图还使用包含一些文本的标题(应该保持固定而不是滚动)。

我已经阅读了有关 GestureDetector.SimpleOnGestureListenerScroller 的文档。我还阅读了 Animating a Scroll Gesture 上的文档,但我发现这些示例很难理解。我还查看了有关 Stack Overflow 的其他问题,这对我有所帮助。

使用我从带有the Stack Overflow answer 的文档中了解的内容作为指导我的参考,我已将以下内容添加到我的自定义视图中:

变量和字段:

private OverScroller mScroller;
private final GestureDetector mGestureDetector =
        new GestureDetector(getContext(), new GestureDetector.SimpleOnGestureListener() {

            @Override
            public boolean onScroll(MotionEvent e1, MotionEvent e2,
                                    float distanceX, float distanceY) {
                // Note 0 as the x-distance to prevent horizontal scrolling
                scrollBy(0, (int) distanceY);
                return true;
            }

            @Override
            public boolean onFling(MotionEvent e1, MotionEvent e2,
                                   float velocityX, float velocityY) {
                final int maxScrollX = 0;

                // wholeViewHeight is height of everything that is drawn
                int wholeViewHeight =  calculateWholeHeight(); 
                int visibleHeight = getHeight();
                final int maxScrollY = wholeViewHeight - visibleHeight;

                mScroller.forceFinished(true);

                mScroller.fling(0, // No startX as there is no horizontal scrolling
                        getScrollY(),
                        0, // No velocityX as there is no horizontal scrolling
                        - (int) velocityY,
                        0,
                        maxScrollX,
                        0,
                        maxScrollY);

                invalidate();

                return true;
            }

            @Override
            public boolean onDown(MotionEvent e) {
                if (!mScroller.isFinished()) {
                    mScroller.forceFinished(true);
                }
                return true;
            }
        });

mScroller的初始化:

// Called from the constructor
private void init() {  
    mScroller = new OverScroller(getContext(), new FastOutLinearInInterpolator());

    ...
}

onDraw():

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    ...

    if (mScroller.computeScrollOffset()) {
        scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
    }
}

onTouchEvent()

@Override
public boolean onTouchEvent(MotionEvent event) {
    return mGestureDetector.onTouchEvent(event);
}

这些添加的结果是一个可以垂直(而不是水平)滚动的自定义视图,但是有一些问题:

  1. 我可以滚动超过所绘制的内容
  2. 当我到达自定义视图的末尾时,没有边缘发光效果(我的意思是像 RecyclerViewScrollView
  3. 所有自定义视图都会滚动,而不仅仅是其中的一部分
  4. 我不完全明白发生了什么

有人能解释一下滚动在自定义视图中的工作原理以及如何使用这些功能正确实现它吗?

【问题讨论】:

  • 你好,法博德·萨拉马特-扎德。你有没有找到任何解决方案?我也遇到了同样的问题,即; “我可以滚动到更远的地方”
  • @AdeelShahzad 还没有。如果您想出解决方案,请告诉我。 :)
  • 嗨,法博德。我想不出一个解决方案,所以我只是在 ViewPager 中扔了一个 ScrollView。

标签: android android-custom-view gesturedetector


【解决方案1】:

我可以提供一个简单的布局,它有一个固定的标题和垂直滚动的内容,听起来就像它会做你想要的并且不需要复杂的编程?从长远来看,它可能会让您不必花费数小时的研究和编程:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <FrameLayout
        android:id="@+id/header"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

    <android.support.v4.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:fillViewport="true">

        <FrameLayout
            android:id="@+id/scrolling_content"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
    </android.support.v4.widget.NestedScrollView>

</LinearLayout>

使用此布局,您可以使用固定的标题视图替换或插入 ID 为“header”的FrameLayout。然后,您可以将 scolling 内容放入 ID 为“scrolling_content”的FrameLayout 中。 NestedScrollingView 将直接位于您的固定标题下方,并自动为您提供所需的滚动行为,而无需任何进一步的代码。

【讨论】:

  • 感谢您的回答。我可以用我的自定义视图的一部分替换第二个FrameLayout 以使其能够滚动吗?
  • 是的,但请记住 NestedScrollView 只能有一个直接子级。只要您不尝试将 2 个视图直接放入 NestedScrollView 中,它就可以正常工作。还要记住,垂直滚动的 NestedScrollView 中的任何视图的 layout_height 都不能为“match_parent”,就好像遵守这个值一样,它会创建一个无限长的滚动。
  • 感谢您的澄清。我会尝试使用NestedScrollView,看看它对我有什么作用。但是,我仍然想知道如何为自定义视图实现它(使用GestureDetectorOverScroller 等)。我已经为此开始了赏金,所以如果您有其他答案,请发布。 :)
  • 谢谢,看看我有什么办法。
猜你喜欢
  • 1970-01-01
  • 2014-09-04
  • 2021-09-19
  • 1970-01-01
  • 2011-09-06
  • 2023-03-08
  • 2011-09-13
  • 1970-01-01
  • 2019-12-02
相关资源
最近更新 更多