¿Hay una manera de desplazarse mediante programación una vista de desplazamiento a un texto de edición específico?

Tengo una actividad muy larga con un scrollview. Es un formulario con varios campos que el usuario debe rellenar. Tengo una casilla de verificación a la mitad de mi formulario y cuando el usuario lo comprueba, quiero desplazarme a una parte específica de la vista. ¿Hay alguna forma de desplazarse a un objeto EditText (o cualquier otro objeto de vista) de forma programática?

Además, sé que esto es posible utilizando X e Y coords pero quiero evitar hacer esto como el formulario puede cambiar de usuario a usuario.

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

La respuesta de Sherif elKhatib se puede mejorar mucho, si desea desplazar la vista al centro de la vista de desplazamiento . Este método reutilizable lisa desplaza la vista al centro visible de una 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); } }); } 

Para un ScrollView vertical, cambie la posición y de las entradas de smoothScroll . Y use view.getTop() lugar de view.getLeft() y view.getBottom() lugar de v.getRight() .

🙂

Esto funciona bien para mi :

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

Public void RequestChildFocus (Ver niño, Ver enfocado)

Child – El hijo de este ViewParent que quiere concentrarse. Esta vista contendrá la vista enfocada. No es necesariamente la opinión que realmente tiene foco.

Enfocado – La visión que es un descendiente del niño que realmente tiene foco

Debe hacer su petición de TextView enfoque:

  mTextView.requestFocus(); 

En mi opinión la mejor manera de desplazarse a un rectángulo dado es a través de View.requestRectangleOnScreen(Rect, Boolean) . Deberá llamarla en una View que desee desplazarse y pasar un rectángulo local que desea que esté visible en la pantalla. El segundo parámetro debe ser false para desplazamiento suave y true para desplazamiento inmediato.

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

Hice un pequeño método de utilidad basado en la respuesta de WarrenFaith, este código también tiene en cuenta si esa vista ya es visible en el scrollview, no hay necesidad de scroll -> UX mal.

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

Mi EditText se anidó varias capas dentro de mi ScrollView, que no es la vista raíz de la disposición. Debido a que getTop () y getBottom () parecían reportar las coordenadas dentro de su vista que contenía, tuve que calcular la distancia desde la parte superior de la ScrollView a la parte superior de la EditText iterando a través de los padres de la 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(); 

Otra variante sería:

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

O puede usar el método post() .

Referencia: https://stackoverflow.com/a/6438240/2624806

Seguir funcionó mucho mejor.

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

Examinando el código fuente de Android, puede encontrar que ya hay una función de miembro de ScrollViewscrollToChild(View) – que hace exactamente lo que se solicita. Desgraciadamente, esta función es por alguna razón oscura marcada private . Sobre la base de esa función he escrito siguiente función que encuentra el primer ScrollView encima de la View especificada como un parámetro y lo desplaza para que se vuelve visible en el 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; } } 

En mi caso, eso no es EditText , que es googleMap . Y funciona con éxito como esto.

  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: ¿Hay una manera de desplazarse mediante programación una vista de desplazamiento a un edittext específico?

Resp: Vista de desplazamiento anidada en recyclerview última posición agregó datos de registro.

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

¿Hay una manera de desplazarse mediante programación una vista de desplazamiento a un texto de edición específico?

Creo que he encontrado más elegante y solución propensa a errores utilizando

ScrollView.requestChildRectangleOnScreen

No hay matemáticas involucradas, y al contrario de otras soluciones propuestas, manejará correctamente el desplazamiento hacia arriba y hacia abajo.

 /** * 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 } 

Es una buena idea envolverlo en postDelayed para hacerlo más fiable, en caso de que el ScrollView esté siendo cambiado en este momento

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

Mi solución es:

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

Lo siguiente es lo que estoy usando:

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

Esto obtiene la cantidad de desplazamiento necesaria para mostrar la parte inferior de la vista, incluyendo cualquier margen en la parte inferior de esa vista.

  • Manejo de la rotación de la pantalla en WebView
  • Expanda todos los niños en la vista de lista expandible
  • Android recibe actividad de alojamiento desde una vista
  • ¿Cómo ampliar la vista sin problemas en Android?
  • Android Webview goback () problema con el método loadDataWithBaseURL
  • Cómo iniciar una actividad desde la vista personalizada
  • archivo interno del HTML de la demostración del androide
  • Vista web de Android ui
  • Fragmento de la fuerza de Android para reconstruir Ver
  • Poner cualquier vista sobre un VideoView en Android
  • Cabezal / artículo pegajoso en la vista de reciclaje
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.