Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add scrolling for a custom view in Android

I've just started writing a custom view in Android (for the first time) and I've realised that I need to implement a scrolling feature.

The custom view also uses a header containing some text (which should stay fixed and not scroll).

I've read through the documentation on GestureDetector.SimpleOnGestureListener and Scroller. I also read the documentation on Animating a Scroll Gesture but I found the examples difficult to understand. I've also looked at other questions on Stack Overflow which helped a little.

Using what I understood from the documentation with the Stack Overflow answer as a reference to guide me, I have added the following to my custom view:

Variables and fields:

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;
            }
        });

Initialization of mScroller:

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

    ...
}

Stuff in onDraw():

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

    ...

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

Stuff in onTouchEvent():

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

The result of these additions is a custom view which can scroll vertically (and not horizontally), however there are a few issues:

  1. I can scroll further past what is drawn
  2. There is no edge glow effect as I reach the end of the custom view (I mean like a RecyclerView or ScrollView)
  3. All of the custom view scrolls as opposed to just a certain part of it
  4. I don't fully understand what is going on

Could someone explain how scrolling works in a custom view and how to implement it properly with these features?

like image 529
Farbod Salamat-Zadeh Avatar asked Sep 03 '16 14:09

Farbod Salamat-Zadeh


People also ask

How do I create a scroll view?

In order to place multiple views in the scroll view, one needs to make a view group(like LinearLayout) as a direct child and then we can define many views inside it. A ScrollView supports Vertical scrolling only, so in order to create a horizontally scrollable view, HorizontalScrollView is used.

Is GridView scrollable Android?

Grid view requires an adapter to fetch data from the resources. This view can be scrolled both horizontally and vertically. The scrolling ability of the GridView by default is set to enabled.

What is nested scrolling Android?

NestedScrollView is just like ScrollView , but it supports acting as both a nested scrolling parent and child on both new and old versions of Android. Nested scrolling is enabled by default.

What is horizontal scroll view in Android?

HorizontalScrollView is used to scroll the child elements or views in a horizontal direction. HorizontalScrollView only supports horizontal scrolling. For vertical scroll, android uses ScrollView. Let's implement simple example of HorizontalScrollView.


1 Answers

May I offer a simple layout that has a fixed header and vertically scrolling content that sounds like it will do what you want and does not require complex programming? It may save you from having to spend hours of research and programming in the long run:

<?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>

Using this layout, you would replace or insert inside the FrameLayout with ID "header" with your fixed header view. You would then put your scolling content inside of the FrameLayout with ID "scrolling_content". The NestedScrollingView would be located directly below your fixed header and automatically give you the scrolling behavior you want without any further code.

like image 100
happydude Avatar answered Oct 02 '22 10:10

happydude