Есть ли способ программно прокрутить представление прокрутки в конкретный текст редактирования?

StackOverflow https://stackoverflow.com/questions/6831671

Вопрос

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

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

Это было полезно?

Решение

private final void focusOnView(){
        your_scrollview.post(new Runnable() {
            @Override
            public void run() {
                your_scrollview.scrollTo(0, your_EditBox.getBottom());
            }
        });
    }

Другие советы

Ответ Шерифа Элхатиба может быть значительно улучшен, если хотите Прокрутите вид на центр вида свитка. Анкет Этот многоразовый метод гладкий прокручивает вид на видимый центр горизонтальсколвилл.

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().

:)

Это хорошо работает для меня:

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

public void requestChildfocus (просмотреть ребенка, взглянуть на фокусировку)

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

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

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

final Rect rect = new Rect(0, 0, view.getWidth(), view.getHeight());
view.requestRectangleOnScreen(rect, false);

Я сделал небольшой метод утилиты, основанный на ответе от Warrenfaith, этот код также принимает учетную запись, если эта точка зрения уже видна в Scrollview, не нужно в Scroll.

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

Вы должны сделать свой TextView Запрос фокус:

    mTextView.requestFocus();

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

// 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();

Еще один вариант будет:

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

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

Я знаю, что это может быть слишком поздно для лучшего ответа, но желаемое идеальное решение должно быть такой системой, как позиционер. Я имею в виду, когда System делает позиционирование для поля редактора, она ставит поле прямо на клавиатуру, поэтому, как правила UI/UX, это идеально.

То, что ниже кода делает плавное положение Android. Прежде всего, мы сохраняем текущую точку прокрутки в качестве эталонной точки. Во -вторых, чтобы найти лучшую точку прокрутки позиционирования для редактора, чтобы сделать это, мы прокручиваем вверх, а затем попросите поля редактора сделать компонент ScrollView для лучшего позиционирования. Гатча! Мы узнали лучшую позицию. Теперь, что мы сделаем, так это плавно прокручивать от предыдущего пункта до такой степени, что мы нашли вновь. Если вы хотите, вы можете опустить плавную прокрутку, используя Спрольто вместо Smoothscrollto Только.

ПРИМЕЧАНИЕ: Основным контейнером ScrollView является поле участника с именем ScrollViewSignup, потому что моим примером был экран регистрации, так как вы можете многое выяснить.

view.setOnFocusChangeListener(new View.OnFocusChangeListener() {
        @Override
        public void onFocusChange(final View view, boolean b) {
            if (b) {
                scrollViewSignup.post(new Runnable() {
                    @Override
                    public void run() {
                        int scrollY = scrollViewSignup.getScrollY();
                        scrollViewSignup.scrollTo(0, 0);
                        final Rect rect = new Rect(0, 0, view.getWidth(), view.getHeight());
                        view.requestRectangleOnScreen(rect, true);

                        int new_scrollY = scrollViewSignup.getScrollY();
                        scrollViewSignup.scrollTo(0, scrollY);
                        scrollViewSignup.smoothScrollTo(0, new_scrollY);
                    }
                });
            }
        }
    });

Если вы хотите использовать этот блок для всех Редактировать текст экземпляры и быстро интегрируйте его с вашим кодом экрана. Вы можете просто сделать обход, как ниже. Для этого я сделал главным OnfocuschangeListener полем участника, названного FOCUSCHANGELISTERERTOScrolleditor, и назовите это во время Create, как ниже.

traverseEditTextChildren(scrollViewSignup, focusChangeListenerToScrollEditor);

И реализация метода, как показано ниже.

private void traverseEditTextChildren(ViewGroup viewGroup, View.OnFocusChangeListener focusChangeListenerToScrollEditor) {
    int childCount = viewGroup.getChildCount();
    for (int i = 0; i < childCount; i++) {
        View view = viewGroup.getChildAt(i);
        if (view instanceof EditText)
        {
            ((EditText) view).setOnFocusChangeListener(focusChangeListenerToScrollEditor);
        }
        else if (view instanceof ViewGroup)
        {
            traverseEditTextChildren((ViewGroup) view, focusChangeListenerToScrollEditor);
        }
    }
}

Итак, то, что мы сделали здесь, это заставляет всех детей EditText, чтобы называть слушателя в фокусе.

Чтобы добраться до этого решения, я проверил его все решения здесь и сгенерировал новое решение для лучшего результата пользовательского интерфейса/UX.

Many thanks to all other answers inspiring me much.

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

Следуя сработало гораздо лучше.

mObservableScrollView.post(new Runnable() {
            public void run() { 
                mObservableScrollView.fullScroll([View_FOCUS][1]); 
            }
        });

Приведенные выше ответы будут работать нормально, если ScrollView является прямым родителем ChildView. Если ваш Childview завершен в другую группу View в 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));
}

Я думаю, что я нашел более элегантное и меньше склонности к ошибкам, используя решение

Scrollview.requestchildrectangleonscreen

Нет никакой математики, и вопреки другим предлагаемым решениям, она будет правильно прокручивать как вверх, так и вниз.

/**
 * Will scroll the {@code scrollView} to make {@code viewToScroll} visible
 * 
 * @param scrollView parent of {@code scrollableContent}
 * @param scrollableContent a child of {@code scrollView} whitch holds the scrollable content (fills the viewport).
 * @param viewToScroll a child of {@code scrollableContent} to whitch will scroll the the {@code scrollView}
 */
void scrollToView(ScrollView scrollView, ViewGroup scrollableContent, View viewToScroll) {
    Rect viewToScrollRect = new Rect(); //coordinates to scroll to
    viewToScroll.getHitRect(viewToScrollRect); //fills viewToScrollRect with coordinates of viewToScroll relative to its parent (LinearLayout) 
    scrollView.requestChildRectangleOnScreen(scrollableContent, viewToScrollRect, false); //ScrollView will make sure, the given viewToScrollRect is visible
}

Это хорошая идея, чтобы обернуть его в postDelayed Чтобы сделать это более надежным, в случае ScrollView в данный момент меняется

/**
 * Will scroll the {@code scrollView} to make {@code viewToScroll} visible
 * 
 * @param scrollView parent of {@code scrollableContent}
 * @param scrollableContent a child of {@code scrollView} whitch holds the scrollable content (fills the viewport).
 * @param viewToScroll a child of {@code scrollableContent} to whitch will scroll the the {@code scrollView}
 */
private void scrollToView(final ScrollView scrollView, final ViewGroup scrollableContent, final View viewToScroll) {
    long delay = 100; //delay to let finish with possible modifications to ScrollView
    scrollView.postDelayed(new Runnable() {
        public void run() {
            Rect viewToScrollRect = new Rect(); //coordinates to scroll to
            viewToScroll.getHitRect(viewToScrollRect); //fills viewToScrollRect with coordinates of viewToScroll relative to its parent (LinearLayout) 
            scrollView.requestChildRectangleOnScreen(scrollableContent, viewToScrollRect, false); //ScrollView will make sure, the given viewToScrollRect is visible
        }
    }, delay);
}

Мое решение:

            int[] spinnerLocation = {0,0};
            spinner.getLocationOnScreen(spinnerLocation);

            int[] scrollLocation = {0, 0};
            scrollView.getLocationInWindow(scrollLocation);

            int y = scrollView.getScrollY();

            scrollView.smoothScrollTo(0, y + spinnerLocation[1] - scrollLocation[1]);

Изучение исходного кода Android, вы можете обнаружить, что уже есть функция участника ScrollViewscrollToChild(View) - Это делает именно то, что просят. К сожалению, эта функция по какой -то неясной причине отмечена private. Анкет На основе этой функции, которую я написал следующая функция, которая находит первую ScrollView над View указан как параметр и прокручивать его так, чтобы он становился видимым в ScrollView:

 private void make_visible(View view)
 {
  int vt = view.getTop();
  int vb = view.getBottom();

  View v = view;

  for(;;)
     {
      ViewParent vp = v.getParent();

      if(vp == null || !(vp instanceof ViewGroup))
         break;

      ViewGroup parent = (ViewGroup)vp;

      if(parent instanceof ScrollView)
        {
         ScrollView sv = (ScrollView)parent;

         // Code based on ScrollView.computeScrollDeltaToGetChildRectOnScreen(Rect rect) (Android v5.1.1):

         int height = sv.getHeight();
         int screenTop = sv.getScrollY();
         int screenBottom = screenTop + height;

         int fadingEdge = sv.getVerticalFadingEdgeLength();

         // leave room for top fading edge as long as rect isn't at very top
         if(vt > 0)
            screenTop += fadingEdge;

         // leave room for bottom fading edge as long as rect isn't at very bottom
         if(vb < sv.getChildAt(0).getHeight())
            screenBottom -= fadingEdge;

         int scrollYDelta = 0;

         if(vb > screenBottom && vt > screenTop) 
           {
            // need to move down to get it in view: move down just enough so
            // that the entire rectangle is in view (or at least the first
            // screen size chunk).

            if(vb-vt > height) // just enough to get screen size chunk on
               scrollYDelta += (vt - screenTop);
            else              // get entire rect at bottom of screen
               scrollYDelta += (vb - screenBottom);

             // make sure we aren't scrolling beyond the end of our content
            int bottom = sv.getChildAt(0).getBottom();
            int distanceToBottom = bottom - screenBottom;
            scrollYDelta = Math.min(scrollYDelta, distanceToBottom);
           }
         else if(vt < screenTop && vb < screenBottom) 
           {
            // need to move up to get it in view: move up just enough so that
            // entire rectangle is in view (or at least the first screen
            // size chunk of it).

            if(vb-vt > height)    // screen size chunk
               scrollYDelta -= (screenBottom - vb);
            else                  // entire rect at top
               scrollYDelta -= (screenTop - vt);

            // make sure we aren't scrolling any further than the top our content
            scrollYDelta = Math.max(scrollYDelta, -sv.getScrollY());
           }

         sv.smoothScrollBy(0, scrollYDelta);
         break;
        }

      // Transform coordinates to parent:
      int dy = parent.getTop()-parent.getScrollY();
      vt += dy;
      vb += dy;

      v = parent;
     }
 }

В моем случае это не EditText, это googleMap. Анкет И это работает успешно так.

    private final void focusCenterOnView(final ScrollView scroll, final View view) {
    new Handler().post(new Runnable() {
        @Override
        public void run() {
            int centreX=(int) (view.getX() + view.getWidth()  / 2);
            int centreY= (int) (view.getY() + view.getHeight() / 2);
            scrollView.smoothScrollBy(centreX, centreY);
        }
    });
}

QUE: Есть ли способ программно прокрутить представление прокрутки до определенного EditText?

ANS: вложенное представление прокрутки в переработке последней позиции Добавлены данные записи.

adapter.notifyDataSetChanged();
nested_scroll.setScrollY(more Detail Recycler.getBottom());

Есть ли способ программно прокрутить представление прокрутки в конкретный текст редактирования?

Ниже я использую:

int amountToScroll = viewToShow.getBottom() - scrollView.getHeight() + ((LinearLayout.LayoutParams) viewToShow.getLayoutParams()).bottomMargin;
// Check to see if scrolling is necessary to show the view
if (amountToScroll > 0){
    scrollView.smoothScrollTo(0, amountToScroll);
}

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

Вертикальная свиток, хорошо для форм. Ответ основан на горизонтальном свитке Ахмадалибалох.

private final void focusOnView(final HorizontalScrollView scroll, final View view) {
    new Handler().post(new Runnable() {
        @Override
        public void run() {
            int top = view.getTop();
            int bottom = view.getBottom();
            int sHeight = scroll.getHeight();
            scroll.smoothScrollTo(0, ((top + bottom - sHeight) / 2));
        }
    });
}

Вы можете использовать ObjectAnimator как это:

ObjectAnimator.ofInt(yourScrollView, "scrollY", yourView.getTop()).setDuration(1500).start();

Если Scrlmain - это ваш вложенный

scrlMain.post(new Runnable() {
                    @Override
                    public void run() {
                        scrlMain.fullScroll(View.FOCUS_UP);

                    }
                });
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top