Есть ли способ программно прокрутить представление прокрутки до определенного текста редактирования? - PullRequest
173 голосов
/ 26 июля 2011

У меня очень долгая активность с прокруткой.Это форма с различными полями, которые пользователь должен заполнить. У меня есть флажок на полпути вниз по моей форме, и когда пользователь проверяет его, я хочу прокрутить до определенной части представления.Есть ли способ программно прокрутить объект EditText (или любой другой объект представления)?

Кроме того, я знаю, что это возможно с использованием координат X и Y, но я хочу избежать этого, так как форма может измениться сот пользователя к пользователю.

Ответы [ 19 ]

408 голосов
/ 26 июля 2011
private final void focusOnView(){
        your_scrollview.post(new Runnable() {
            @Override
            public void run() {
                your_scrollview.scrollTo(0, your_EditBox.getBottom());
            }
        });
    }
50 голосов
/ 31 марта 2013

Ответ Шерифа эль-Хатиба может быть значительно улучшен, если вы хотите прокрутить вид к центру вида прокрутки .Этот метод многократного использования обеспечивает плавную прокрутку вида до видимого центра HorizontalScrollView.

private final void focusOnView(final HorizontalScrollView scroll, final View view) {
    new Handler().post(new Runnable() {
        @Override
        public void run() {
            int vLeft = view.getLeft();
            int vRight = view.getRight();
            int sWidth = scroll.getWidth();
            scroll.smoothScrollTo(((vLeft + vRight - sWidth) / 2), 0);
        }
    });
}

Для вертикального ScrollView измените положение x и y входов smoothScroll.И используйте view.getTop() вместо view.getLeft() и view.getBottom() вместо v.getRight().

:)

45 голосов
/ 01 августа 2015

Для меня это хорошо работает:

  targetView.getParent().requestChildFocus(targetView,targetView);

public void RequestChildFocus (Просмотреть ребенка, Просмотреть фокус)

child - Childэтого ViewParent, который хочет сосредоточиться.Это представление будет содержать сфокусированное представление.Это не обязательно представление, которое на самом деле имеет фокус.

сосредоточено - Представление, которое является потомком ребенка, которое на самом деле имеет фокус

24 голосов
/ 21 апреля 2016

На мой взгляд, лучший способ прокрутки к данному прямоугольнику - через View.requestRectangleOnScreen(Rect, Boolean). Вы должны вызвать его на View, к которому вы хотите прокрутить и передать локальный прямоугольник, который вы хотите видеть на экране. Второй параметр должен быть false для плавной прокрутки и true для немедленной прокрутки.

final Rect rect = new Rect(0, 0, view.getWidth(), view.getHeight());
view.requestRectangleOnScreen(rect, false);
12 голосов
/ 30 июля 2014

Я создал небольшой служебный метод на основе ответа от WarrenFaith, этот код также учитывает, если это представление уже видно в просмотре прокрутки, нет необходимости в прокрутке.

public static void scrollToView(final ScrollView scrollView, final View view) {

    // View needs a focus
    view.requestFocus();

    // Determine if scroll needs to happen
    final Rect scrollBounds = new Rect();
    scrollView.getHitRect(scrollBounds);
    if (!view.getLocalVisibleRect(scrollBounds)) {
        new Handler().post(new Runnable() {
            @Override
            public void run() {
                scrollView.smoothScrollTo(0, view.getBottom());
            }
        });
    } 
}
10 голосов
/ 26 июля 2011

Вы должны сфокусировать ваш TextView запрос:

    mTextView.requestFocus();
6 голосов
/ 27 августа 2014

Мой EditText был вложен в несколько слоев внутри моего ScrollView, который сам по себе не является корневым представлением макета. Поскольку getTop () и getBottom (), по-видимому, сообщали о координатах в пределах содержащего их представления, я сделал так, чтобы он вычислял расстояние от вершины ScrollView до вершины EditText, просматривая родительские элементы EditText.

// Scroll the view so that the touched editText is near the top of the scroll view
new Thread(new Runnable()
{
    @Override
    public
    void run ()
    {
        // Make it feel like a two step process
        Utils.sleep(333);

        // Determine where to set the scroll-to to by measuring the distance from the top of the scroll view
        // to the control to focus on by summing the "top" position of each view in the hierarchy.
        int yDistanceToControlsView = 0;
        View parentView = (View) m_editTextControl.getParent();
        while (true)
        {
            if (parentView.equals(scrollView))
            {
                break;
            }
            yDistanceToControlsView += parentView.getTop();
            parentView = (View) parentView.getParent();
        }

        // Compute the final position value for the top and bottom of the control in the scroll view.
        final int topInScrollView = yDistanceToControlsView + m_editTextControl.getTop();
        final int bottomInScrollView = yDistanceToControlsView + m_editTextControl.getBottom();

        // Post the scroll action to happen on the scrollView with the UI thread.
        scrollView.post(new Runnable()
        {
            @Override
            public void run()
            {
                int height =m_editTextControl.getHeight();
                scrollView.smoothScrollTo(0, ((topInScrollView + bottomInScrollView) / 2) - height);
                m_editTextControl.requestFocus();
            }
        });
    }
}).start();
4 голосов
/ 13 апреля 2014

Другое изменение будет:

scrollView.postDelayed(new Runnable()
{
    @Override
    public void run()
    {
        scrollView.smoothScrollTo(0, img_transparent.getTop());
    }
}, 2000);

или вы можете использовать метод post().

2 голосов
/ 06 января 2015

ссылка: https://stackoverflow.com/a/6438240/2624806

Следование сработало намного лучше.

mObservableScrollView.post(new Runnable() {
            public void run() { 
                mObservableScrollView.fullScroll([View_FOCUS][1]); 
            }
        });
2 голосов
/ 29 августа 2018

Приведенные выше ответы будут работать нормально, если ScrollView является прямым родителем ChildView. Если ваш ChildView переносится в другую ViewGroup в ScrollView, это вызовет неожиданное поведение, потому что View.getTop () получит позицию относительно своего родителя. В таком случае вам нужно реализовать это:

public static void scrollToInvalidInputView(ScrollView scrollView, View view) {
    int vTop = view.getTop();

    while (!(view.getParent() instanceof ScrollView)) {
        view = (View) view.getParent();
        vTop += view.getTop();
    }

    final int scrollPosition = vTop;

    new Handler().post(() -> scrollView.smoothScrollTo(0, scrollPosition));
}
...