Stoppen Sie ScrollView vom automatischen Scrollen zu einem EditText

Scheint ein gemeinsames Problem ohne eine tolle Lösung zu sein, die ich gefunden habe Ziel ist es, eine ScrollView von Auto-Scrolling zu einem EditText (oder eine beliebige Ansicht für diese Angelegenheit) zu stoppen, die Fokus hat.

Sie haben eine Reihe von Ansichten (Schaltflächen, Textbilder, etc.) in einer Scrollview, von denen einer ein EditText ist. Wenn du in der Scrollview eine Schaltfläche anklickst, blättert die Scrollview hinunter zum EditText (aus dem Bildschirm). Dies ist nicht erwünscht, da es noch andere Elemente gibt, die du nicht aus dem Bildschirm scrollen möchtest.

  • Wie kann man dem Layout eine benutzerdefinierte Ansicht hinzufügen?
  • Android Download Fortschritt
  • Wie man SlidingPaneLayout auf der rechten Seite zeigt
  • Wie lautet der Lesermodus in Firefox ausgelöst?
  • Programmgesteuertes Wifi Passwort?
  • Wie kann man Raw Socket in Android erstellen?
  • Jetzt kann ich dies aufhören, wenn der Bildschirm zuerst zeigt, indem er andere fokussierbare Elemente in der Scrollview hat. Allerdings besteht das allgemeine Problem noch. Der Benutzer scrollt manuell in den EditText, gibt einige Zahlen ein und scrollt dann bis zum Anfang (EditText off screen now), sie klicken auf eine Schaltfläche im ScrollView und erraten, was? Die ScrollView blättert hinunter zu diesem verdammten EditText.

    Ich denke über die Unterklassen der Scrollview und übergebe einige der privaten Methoden dort wie findFocusableViewInBounds, aber ich habe ein Gefühl, dass ich mich nur in Schwierigkeiten bringen werde.

    Bitte helfen Sie, wenn Sie können.

    Ich habe herum gespielt mit Sachen wie mit einem 0-height EditText an der Spitze meiner Scrollview, Hinzufügen von Next Focusable Element Eigenschaften zu den anderen Elementen in der ScrollView, etc. Ich vermute, ein "Hack" könnte sein, um die EditText zu verlieren Fokus zu bekommen Wenn die virtuelle oder manuelle Tastatur versteckt wird oder etwas.

  • Android-String-Codierung und HTML-Entities Konvertierung
  • Android-SDK-Komponenten ohne Android-SDK-Manager herunterladen
  • Retrofit: Server gibt sowohl ETag als auch Cache-Control zurück: max-age = 60. Sollte nicht der Cache verwendet werden, wenn request <60s?
  • Android und Reflexion
  • Wie kann ich eine Android-HTTP-Anfrage abbrechen?
  • Amazon App Store und Android Lizenzierung LVL
  • 19 Solutions collect form web for “Stoppen Sie ScrollView vom automatischen Scrollen zu einem EditText”

    Nach dem Kämpfen mit diesem Problem seit einiger Zeit, habe ich eine Lösung gefunden, die zu arbeiten scheint, ohne zu hässlich zu sein. Zuerst stellen Sie sicher, dass alles, was ViewGroup (direkt) enthält, Ihr EditText hat DescendantFocusability auf "Before Descendants" eingestellt, fokussierbar auf "true" gesetzt und FocusableInTouchMode auf "true" gesetzt. Dies ist nicht die ScrollView selbst, sondern das Layout im Inneren, wo Sie Ihre verschiedenen Ansichten haben. Als nächstes füge ein onTouchListener zu deinem ScrollView hinzu, das den Fokus aus dem EditText entfernt, wenn es so berührt wird:

    ScrollView scroll = (ScrollView)findViewById(R.id.scrollView1); scroll.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (myEditText.hasFocus()) { myEditText.clearFocus(); } return false; } }); 

    Sag mir, wenn das nicht regelt. Was passieren sollte, ist, dass das Layout Fokus statt der EditText bekommt, also kein Scrollen sollte passieren.

    Erstellen Sie einfach eine leere Ansicht an der Spitze der linearlayout

     <View android:layout_width="fill_parent" android:id="@+id/focus_view" android:layout_height="0dp" android:focusable="true" android:focusableInTouchMode="true"><requestFocus/></View> 

    Einzeilig löst das Problem

    Ich hatte das gleiche Problem. Es gibt einen Trick, den ich verwende, um mit diesem Problem umzugehen:

     public void onClick(View v) { button.requestFocusFromTouch(); //prevents from loosing focus and scrolling view down .... } 

    Das Problem ist nicht auf dem Java-Code, sondern auf dem Manifest-Code.

    In deinem AndroidManifest.xml füge ein Attribut zur Aktivität hinzu:

      <activity android:name=".MyActivity" android:windowSoftInputMode="adjustPan"> </activity> 

    Hier ist was ich tat

      <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" style="@style/measurementTableRowStyle" android:focusable="true" android:layout_height="fill_parent"> <requestFocus></requestFocus> <LinearLayout android:id="@+id/linearLayout1" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/desc_text" android:text="Value : " style="@style/attributeNameTextStyle" android:layout_width="wrap_content" android:focusable="true" android:layout_height="wrap_content"> <requestFocus></requestFocus> </TextView> <TextView style="@style/attributeValueStyle" android:id="@+id/value_text" android:text="TextView" android:layout_width="wrap_content" android:layout_height="wrap_content"></TextView> </LinearLayout> 

    Der Grund ist in solchen Fällen müssen Sie alle anderen Ansichten fokussierbar innerhalb der scrollview durch eine explizite android:focusable="true" und dann <requestFocus></requestFocus> . Dies sollte jedes Mal IMO funktionieren

    Durch Hinzufügen von 2 Parametern in:

     android:focusable="true" android:focusableInTouchMode="true" 

    In welchem ​​Hauptlayout ist da.

     <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/layMain" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/background" android:focusable="true" android:focusableInTouchMode="true"> 

    Von diesem EditText wird nicht automatisch fokussiert.

    Thomas88wp antwort, https://stackoverflow.com/a/6486348/528746 arbeitete für mich. Aber ich hatte zwei Probleme: 1. Beim Scrollen wollte ich die Tastatur verstecken
    2. Ich hatte viele EditText-Ansichten und wollte es nicht für jeden von ihnen schreiben
    (Ich bekommeActivity (), da ich das in einem Fragment schreibe und nicht eine Aktivität)

      ScrollView scroll = (ScrollView)view.findViewById(R.id.layout_scroll); scroll.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { // Check if the view with focus is EditText if (getActivity().getCurrentFocus() instanceof EditText) { EditText ed = (EditText)getActivity().getCurrentFocus(); if (ed.hasFocus()) { // Hide the keyboard InputMethodManager inputManager = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE); inputManager.hideSoftInputFromWindow(getActivity().getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); // Clear the focus ed.clearFocus(); } } return false; } }); 

    Mein Fix zu diesem schrecklichsten Bug, (erwähnenswert, dass dies vor API11 nur dort ist, wo sie die Fling-Methode geändert haben, um nicht dumm zu sein).

    Die alte Fling-Methode findet den nächsten Fokus, den es bekommen wird .. was nicht wirklich so hilfreich ist. Andere Versionen dieser Klasse funktionieren nicht wirklich, da sie den Fokus beenden, wenn der Benutzer das Formular wirklich von der Tastatur durchquert.

     public class NonFocusingScrollView extends ScrollView { private boolean mBlockRequestFocusOnFling = false; public NonFocusingScrollView(Context context) { super(context); } public NonFocusingScrollView(Context context, AttributeSet attrs) { super(context, attrs); } public NonFocusingScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override public ArrayList<View> getFocusables(int direction) { if(mBlockRequestFocusOnFling) return new ArrayList<View>(); return super.getFocusables(direction); } @Override public void requestChildFocus(View child, View focused) { if(!mBlockRequestFocusOnFling) super.requestChildFocus(child, focused); } @Override public void fling(int velocityY) { mBlockRequestFocusOnFling = true; super.fling(velocityY); mBlockRequestFocusOnFling = false; } } 

    Wir können eine benutzerdefinierte ScrollView schreiben und die onScrollChanged- Methode überschreiben und den Fokus aus der fokussierten Ansicht löschen und optional die Tastatur ausblenden.

     @Override protected void onScrollChanged(int l, int t, int oldl, int oldt) { View v = getFocusedChild(); if (v != null) { InputMethodManager imm = (InputMethodManager) getContext() .getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(v.getWindowToken(), 0); v.clearFocus(); } super.onScrollChanged(l, t, oldl, oldt); } 

    Eine andere Version von thomas88wp's Code:

     ScrollView scroll = (ScrollView)getActivity().findViewById(R.id.scrollView_addNewBill); scroll.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View arg0, MotionEvent arg1) {    View focussedView = getCurrentFocus(); if( focussedView != null ) focussedView.clearFocus();       return false; } }); 

    Ich habe ein Testprojekt gemacht, um mit den verschiedenen Lösungen zu experimentieren, wenn jemand mit ihm spielen will. https://github.com/marchold/EditText-ErrorPopup-Scroll-View

    Ich hatte ein ähnliches Problem und habe es schließlich zur Arbeit gebracht. Meine Scroll-Ansicht enthält eine Reihe von benutzerdefinierten Schaltflächen, gefolgt von einem EditText (was normalerweise Fokus hat, aber ich möchte nicht, dass es den Fokus verliert). Jedes Mal, wenn die Tasten geklickt wurden, EditText die Scroll-Ansicht automatisch auf den fokussierten EditText . Overriding public boolean requestChildRectangleOnScreen(final View child, final Rect rectangle, final boolean immediate) und immer false (Standardverhalten einer ViewGroup ) hat den Trick gemacht. Hoffe, es hilft bei deiner Situation auch.

    Nur dieser Code funktioniert für mich:

     public static void preventScrollViewFromScrollingToEdiText(ScrollView view) { view.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS); view.setFocusable(true); view.setFocusableInTouchMode(true); view.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { v.requestFocusFromTouch(); return false; } }); } 

    Alle Credits gehen auf diese ursprüngliche Antwort .

    Ich habe oft dieses Problem, wenn meine Apps die Ausrichtung ändern.

    In diesem Fall verwende ich die folgende Art von Code:

     @Override protected void onCreate(Bundle savedInstanceState) { ... // to avoid the scrollview to scroll to this element automatically mEditTextSearch.setFocusable(false); // Get the saved scroll position final int scrolly = savedInstanceState.getInt("scrolly"); mScrollView.post(new Runnable() { @Override public void run() { mScrollView.scrollTo(0, scrolly); // Restore the initial state of the EditText mEditTextSearch.setFocusable(true); mEditTextSearch.setFocusableInTouchMode(true); mEditTextSearch.setClickable(true); } }); ... } 

    Erstellen Sie eine benutzerdefinierte ScrollView (erstellen Sie eine Klasse und haben es erweitern horizontaleScrollView) und machen Sie einen Getter-Setter für scrollable. Dann überschreiben Sie computeScrollDeltaToGetChildRectOnScreen.

    Wie es funktioniert: Jedes Mal, wenn Android einen Bearbeitungstext hat oder etwas im Fokus, das aus dem Bildschirm ist, ruft es die Methode computeScrollDeltaToGetChildRectOnScreen auf, um es in die Ansicht zu bringen. Wenn Sie es überschreiben und 0 zurückgeben, wenn es deaktiviert ist, als es nicht scrollen wird …

    So haben Sie eine benutzerdefinierte Scroll-Ansicht wie folgt:

      public class TrackableHorizontalScrollView extends HorizontalScrollView { // true if we can scroll (not locked) // false if we cannot scroll (locked) private boolean mScrollable = true; public TrackableHorizontalScrollView(Context context) { super(context); } public TrackableHorizontalScrollView(Context context, AttributeSet attrs) { super(context, attrs); } public TrackableHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public void setScrollingEnabled(boolean enabled) { mScrollable = enabled; } public boolean isScrollable() { return mScrollable; } @Override public boolean onTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: // if we can scroll pass the event to the superclass if (mScrollable) return super.onTouchEvent(ev); // only continue to handle the touch event if scrolling enabled return mScrollable; // mScrollable is always false at this point default: return super.onTouchEvent(ev); } } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { // Don't do anything with intercepted touch events if // we are not scrollable if (!mScrollable) return false; else return super.onInterceptTouchEvent(ev); } @Override public void scrollTo(int x, int y){ if (!mScrollable) return; super.scrollTo(x, y); } //Custom smooth scroll method since norm is final and cannot be overridden public final void smooothScrollToIfEnabled(int x, int y){ if (!mScrollable) return; smoothScrollTo(x, y); } @Override protected int computeScrollDeltaToGetChildRectOnScreen(android.graphics.Rect rect){ if (!mScrollable) return 0; return super.computeScrollDeltaToGetChildRectOnScreen(rect); } } 

    Sie können diese in Ihrem XML wie folgt verwenden:

     <com.your.package.ui.widget.TrackableHorizontalScrollView android:id="@+id/wi_et_credit_scroller" android:layout_toRightOf="@id/wi_et_credit_iv" android:layout_width="fill_parent" android:scrollbars="none" android:layout_height="wrap_content" android:paddingRight="5dp" android:layout_gravity="center_vertical"> <!--Whatever you have inside the scrollview--> </com.your.package.ui.widget.TrackableHorizontalScrollView> 

    Für mich hat es nicht gearbeitet, um ScrollView onTouch zu überschreiben. Auch nicht funktioniert android: descendantFocusability = "beforeDescendants" android: focusableInTouchMode = "true" Diese und andere erwähnte Lösungen funktionierten nur zum ersten Mal – nur wenn EditText nicht ausgewählt ist, aber sobald du es ausgewählt hast, scrollview autoscrolls wieder.

    Weil ich schon einen Code geschrieben habe, um eine Tastatur zu verbergen, wenn ich andere Ansichten berührst, habe ich gerade zwei Zeilen Code hinzugefügt und es funktionierte wie ein Champion:

     public static void setupUI(final Activity activity, final View view) { //view is the parent view in your layout OnTouchListener mTouchListener = new OnTouchListener() { public boolean onTouch(View v, MotionEvent event) { try { View vFocused = null; vFocused = activity.getCurrentFocus(); if (vFocused != null) { hideSoftKeyboard(activity, v); if (vFocused instanceof EditText) { vFocused.clearFocus();//this is the trick to avoid ScrollView autoscroll } } } catch (Exception e) { } return false; } }; // Set up touch listener for non-text box views to hide keyboard. if (!(view instanceof EditText) && !(view instanceof ViewGroup)) { view.setOnTouchListener(mTouchListener); } // If a layout container, iterate over children and seed recursion. if (view instanceof ViewGroup) { view.setOnTouchListener(mTouchListener); for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) { View innerView = ((ViewGroup) view).getChildAt(i); setupUI(activity, innerView); } } } public static void hideSoftKeyboard(Context context, View v) { InputMethodManager inputMethodManager = (InputMethodManager) context .getSystemService(Activity.INPUT_METHOD_SERVICE); inputMethodManager.hideSoftInputFromWindow(v.getWindowToken(), 0); } 

    Fügte dies auch in der root-Ansicht hinzu:

     android:descendantFocusability="beforeDescendants" android:focusableInTouchMode="true" 

    Vielleicht ist es nicht wirklich schöne Lösung, aber seine Arbeit.

    Die beste Lösung ist es, Fokusoptionen für das Kind deiner Scrollview hinzuzufügen:

     android:descendantFocusability="beforeDescendants" android:focusable="true" android:focusableInTouchMode="true" 

    Dann sieht deine XML-Datei wie folgt aus:

     <?xml version="1.0" encoding="utf-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/scrollView" android:layout_width="match_parent" android:layout_height="match_parent" > <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginRight="50dp" android:descendantFocusability="beforeDescendants" android:focusable="true" android:focusableInTouchMode="true" android:orientation="vertical" > <EditText android:id="@+id/editText_one" android:layout_width="match_parent" android:layout_height="100dp" android:text="TestApp 1" /> <EditText android:id="@+id/editText_two" android:layout_width="match_parent" android:layout_height="100dp" android:text="TestApp 2" /> <EditText android:id="@+id/editText_three" android:layout_width="match_parent" android:layout_height="100dp" android:text="TestApp 3" /> </LinearLayout> </ScrollView> 

    Meine Lösung ist unten, um den Quellcode zu verfolgen und eine Funktion zu überschreiben, um das automatische Scrollen durch fokussiertes Element zu stoppen.

    Sie können überprüfen, ob das focusedView TextView oder sein Kind TextView ist, indem Sie focusedView.findViewById(R.id.textview_id_you_defined) != null oder focusedView instanceof TextView == true .

     public class StopAutoFocusScrollView extends ScrollView { private View focusedView; private ScrollMonitorListener listener; public interface ScrollMonitorListener { public boolean enableScroll(View view); } public StopAutoFocusScrollView(Context context) { super(context); } public StopAutoFocusScrollView(Context context, AttributeSet attrs) { super(context, attrs); } public StopAutoFocusScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public void setScrollMonitorListener(ScrollMonitorListener listener) { this.listener = listener; } @Override public void requestChildFocus(View child, View focused) { focusedView = focused super.requestChildFocus(child, focused); } //flow : requestChildFocus -> scrollToChild -> scrollBy //Therefore, you can give listener to determine you want scroll to or not @Override public void scrollBy(int x, int y) { if (listener == null || listener.enableScroll(focusedView)) { super.scrollBy(x, y); } } } 

    Ich hatte einen etwas anderen Einwand gegen diesen ärgerlichen Mangel. Immer wenn ich eine von einer Anzahl von RadioButtons unterhalb der EditTexts klopfte, sprang die Scroll-Position, um zu passen, was Android als das sichtbare und fokussierte EditText entschieden wurde.

    Alle Versuche, die aktuelle gewünschte Runnable über einen Runnable zu behalten, der ScrollView.scrollTo(x,y) ausgestellt hat, wurde von Android pflichtbewusst IGNORED!

    Ich teile meine Lösung in der Hoffnung, dass es jemand anderes retten kann 8 (acht) verschwendete Stunden.

     /* This interesting little 'hack' prevents unwanted scroll 'jump' occurring when user touches a RadioButton for example [ Causes focus to change - but maybe this is a lesser evil! ] */ mScrollView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (event.getAction() != MotionEvent.ACTION_UP) return false; mScrollView.clearFocus(); return false; } }); 
    Das Android ist ein Google Android Fan-Website, Alles ├╝ber Android Phones, Android Wear, Android Dev und Android Spiele Apps und so weiter.