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

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

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

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

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

 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 (просмотр дочернего элемента, просмотр сфокусирован)

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

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

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

  mTextView.requestFocus(); 

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

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

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

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

Мой 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(); 

Другое изменение:

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

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

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

После этого работала намного лучше.

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

Изучив исходный код Android, вы можете обнаружить, что уже существует функция-член ScrollViewscrollToChild(View) – это точно то, что scrollToChild(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: просмотр вложенных прокруток в recyclerview последней позиции добавил данные записи.

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

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

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

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

Ниже приводится то, что я использую:

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

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