it-swarm.com.de

Gibt es eine Möglichkeit, eine Bildlaufansicht programmgesteuert zu einem bestimmten Bearbeitungstext zu verschieben?

Ich habe eine sehr lange Aktivität mit einer Scrollansicht. Es ist ein Formular mit verschiedenen Feldern, die der Benutzer ausfüllen muss. In der Mitte meines Formulars befindet sich ein Kontrollkästchen. Wenn der Benutzer es aktiviert, möchte ich zu einem bestimmten Teil der Ansicht scrollen. Gibt es eine Möglichkeit, programmgesteuert zu einem EditText-Objekt (oder einem anderen Ansichtsobjekt) zu scrollen?

Ich weiß auch, dass dies mit X- und Y-Koordinaten möglich ist, aber ich möchte dies vermeiden, da sich das Formular von Benutzer zu Benutzer ändern kann.

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

Die Antwort von Sherif elKhatib kann stark verbessert werden, wenn Sie scrollen Sie die Ansicht in die Mitte der Scroll-Ansicht. Mit dieser wiederverwendbaren Methode wird die Ansicht sanft in die sichtbare Mitte einer HorizontalScrollView verschoben.

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

Ändern Sie für ein vertikales ScrollView die x und y Position der Eingaben von smoothScroll. Und verwenden Sie view.getTop() anstelle von view.getLeft() und view.getBottom() anstelle von v.getRight().

:)

52
ahmadalibaloch

Das funktioniert gut für mich:

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

public void RequestChildFocus (View child, View focused)

child - Das Kind dieses ViewParents, das den Fokus haben möchte. Diese Ansicht enthält die fokussierte Ansicht. Es ist nicht unbedingt die Ansicht, die tatsächlich den Fokus hat.

fokussiert - Die Ansicht, die von einem Kind abstammt, das tatsächlich fokussiert ist

46
Swas_99

Meiner Meinung nach ist der beste Weg, zu einem bestimmten Rechteck zu scrollen, über View.requestRectangleOnScreen(Rect, Boolean) . Sie sollten es auf einem View aufrufen, zu dem Sie scrollen möchten, und ein lokales Rechteck passieren, das auf dem Bildschirm sichtbar sein soll. Der zweite Parameter sollte false für einen reibungslosen Bildlauf und true für einen sofortigen Bildlauf sein.

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

Ich habe eine kleine Dienstprogrammmethode basierend auf Answer von WarrenFaith erstellt. Dieser Code berücksichtigt auch, ob diese Ansicht bereits in der Bildlaufansicht angezeigt wird, ohne dass ein Bildlauf erforderlich ist.

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

Sie sollten Ihren TextView -Anforderungsfokus setzen:

    mTextView.requestFocus();
10
Ovidiu Latcu

Mein EditText war in meiner ScrollView, die selbst nicht die Stammansicht des Layouts ist, in mehreren Ebenen verschachtelt. Da getTop () und getBottom () die Koordinaten in der enthaltenen Ansicht zu melden schienen, ließ ich den Abstand vom oberen Rand der ScrollView zum oberen Rand des EditText durch Iteration durch die übergeordneten Elemente des EditText berechnen.

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

Eine andere Variante wäre:

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

oder Sie können die Methode post() verwenden.

4

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

Das Folgen funktionierte viel besser.

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

Die obigen Antworten funktionieren einwandfrei, wenn die ScrollView das direkte übergeordnete Element der ChildView ist. Wenn Ihre ChildView in eine andere ViewGroup in der ScrollView eingebunden wird, führt dies zu unerwartetem Verhalten, da View.getTop () die Position relativ zu ihrer übergeordneten ViewGroup erhält. In diesem Fall müssen Sie Folgendes implementieren:

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));
}
2
Sam Fisher

Ich denke, ich habe eine elegantere und weniger fehleranfällige Lösung gefunden

ScrollView.requestChildRectangleOnScreen

Es ist keine Mathematik erforderlich, und im Gegensatz zu anderen vorgeschlagenen Lösungen funktioniert das Scrollen sowohl nach oben als auch nach unten ordnungsgemäß.

/**
 * 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 ist eine gute Idee, es in postDelayed zu packen, um es zuverlässiger zu machen, falls das ScrollView gerade geändert wird

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

Sie können ObjectAnimator folgendermaßen verwenden:

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

Que: Gibt es eine Möglichkeit, programmgesteuert einen Bildlauf zu einem bestimmten Edittext durchzuführen?

Antwort: In der verschachtelten Bildlaufansicht in der Recycling-Übersicht wurden zuletzt hinzugefügte Datensatzdaten angezeigt.

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

Gibt es eine Möglichkeit, eine Bildlaufansicht programmgesteuert zu einem bestimmten Bearbeitungstext zu verschieben?

0
Ravi Bhalala

Vertikale Schriftrolle, gut für Formulare. Die Antwort basiert auf Ahmadalibalochs horizontaler Schriftrolle.

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

Wenn scrlMain Ihre NestedScrollView ist, verwenden Sie Folgendes:

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

                    }
                });
0
Ashwin Balani

Wenn Sie den Android Quellcode untersuchen, können Sie feststellen, dass es bereits eine Member-Funktion von ScrollViewscrollToChild(View) gibt - die genau das tut, was angefordert wird Die Funktion ist aus einem unbekannten Grund mit private markiert. Basierend auf dieser Funktion habe ich die folgende Funktion geschrieben, die den ersten ScrollView über dem View findet, der als Parameter angegeben ist, und diesen so scrollt dass es im ScrollView sichtbar wird:

 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;
     }
 }
0
Jaromír Adamec

Folgendes verwende ich:

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

Dadurch wird der Bildlaufbetrag abgerufen, der zum Anzeigen des unteren Bereichs der Ansicht erforderlich ist, einschließlich aller Ränder am unteren Rand dieser Ansicht.

0
LukeWaggoner

Meine Lösung lautet:

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

In meinem Fall ist das nicht EditText, das ist googleMap. Und so funktioniert es erfolgreich.

    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);
        }
    });
}
0
Zin Win Htet