English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Einleitung
Nachdem man lange genug entwickelt hat, kann man nicht umhin, verschiedene Probleme zu begegnen.
Auf dem Weg der Android-Entwicklung ist der Fehler "Der Soft-Keyboard blockiert das Eingabefeld" ein alter und tiefes Graben - Komm, wir schauen uns das langsam an.
Einführung
Am einfachsten ist es, wie im Bild gezeigt: Unten auf der Seite befindet sich ein EditText, wenn nichts behandelt wird, könnte der Soft-Keyboard den EditText blockieren.
Die Verarbeitung dieser Situation ist eigentlich sehr einfach, es genügt, im AndroidManifest-Datei die activity-Einstellungen zu setzen: den Wert von android:windowSoftInputMode auf adjustPan oder adjustResize zu stellen, wie folgt:
<activity> android:name=".MainActivity" android:windowSoftInputMode="adjustPan" > ... </activity>
Generally speaking, they can solve the problem, of course, the effect of adjustPan and adjustResize is slightly different.
adjustPan is to shift the entire interface upwards, making the input box visible without changing the layout of the interface;
adjustResize is to recalculate the size of the interface after the soft keyboard pops up, which is equivalent to displaying the content with less interface area, so the input box is naturally included.
↑↑↑ OK, this is just an introduction, basically all Android engineers on Earth can handle it.
Don't worry, see below~
Try adding WebView? The pit is here……
In the introduction above, the soft keyboard is triggered to pop up by the native EditText. In the H5When Hybrid has almost become the standard configuration of App, we often encounter another situation: the soft keyboard is triggered to pop up by web elements in the WebView.
Situation Description
At this point, the situation will become complex:
Firstly, when the page is not in full-screen mode, setting adjustPan for the activity will fail.
Secondly, when the page is in full-screen mode, both adjustPan and adjustResize will fail.
——Let me explain, the full-screen mode here refers to the page being full-screen, including the Application or activity using the Fullscreen theme, using 'status color shading', 'immersive status bar', 'Immersive Mode', etc.——in short, basically, as long as the App takes control of the status bar, this kind of problem will occur.
The following table can simply list the specific situations.
Why is it said to be a pit?”issue 5497”
The situation in the table above is not what Google expected; the ideal situation would of course be that they all work normally——so this is actually a BUG in the Android system itself.
Why did the article say it was a pit at the beginning?
——because this BUG has been from Android1.x era(2009Year) was reported, and it has been until today's Android7.0(2016Year) has not been fixed……/(ㄒoㄒ)/
It can be said that this is not only a pit, but also an officially dug pit~
“issue 5497”,Details can be found here ☞ Fehler 5497 - android -WebView adjustResize windowSoftInputMode bricht, wenn activity im Vollbildmodus ist - Android Open Source Projekt - Fehlerverfolgung - Google Project Hosting
Natürlich, egal, wer das Loch gegraben hat, am Ende muss es der Entwickler lösen.
Nachdem man das Loch getroffen hat, gibt es zwei Methoden, um darüber zu gelangen: umgehen oder füllen.
Vermeidungsposition
Wie im vorherigen Abschnitt gezeigt, sind die Bedingungen für das Auftreten des Lochs: activity mit WebView verwendet Vollbildmodus oder adjustPan-Modus.
Dadurch wird die Art und Weise, das Loch zu vermeiden, sehr einfach -
Verwenden Sie kein Vollbildmodus, wenn im activity ein WebView vorhanden ist, und stellen Sie dessen windowSoftInputMode-Wert auf adjustResize ein.
Wie finden Sie es, ist es nicht einfach?
Aber es gibt manchmal, wenn man Vollbildmodus und WebView gleichzeitig haben muss, dann funktioniert das Verstecken nicht mehr, wir benötigen eine neue Art, das Loch zu füllen. Zum Glück ist die Weisheit der Entwickler unerschöpflich, dieser Bach hat so viele Jahre hindurch existiert, und jemand hat dennoch einige Lösungen gefunden.
AndroidBug5497Workaround
Meiner Meinung nach ist die beste Lösung diese:AndroidBug5497Workaroundbedarf nur eines magischen AndroidBug5497Workaround-Klasse.
Nach dem Namen zu urteilen, ist es speziell zum Bekämpfen da:5497Die, bei der die Verwendungsschritte ebenfalls sehr einfach sind:
Den AndroidBug5497Die Workaround-Klasse in das Projekt kopieren
Fügen Sie in der onCreate-Methode der activity, in der ein Loch gefüllt werden muss, einen AndroidBug hinzu5497Workaround.assistActivity(this) verwenden.
Nach Tests ist er auf den meisten Android-Versionen verfügbar und die Wirkung ist ähnlich wie die Einstellung von adjustResize.
Sehen Sie sich ein Vergleichsbild an:
Von einer Activity-Seite mit WebView in vollbildigem Modus unserer App, von links nach rechts: ohne Tastatur, die Tastatur blockiert das Eingabefeld und die Verwendung von AndroidBug5497Die endgültige Wirkung nach dem Workaround.
Was ist sein Prinzip?
Dieser aufregende AndroidBug5497Die Workaround-Klasse ist im Grunde nicht sehr komplex, sie besteht nur aus einigen Dutzend Zeilen Code, ich füge sie hier zunächst hinzu:
public class AndroidBug5497Workaround { // Für weitere Informationen siehe https://code.google.com/p/android/issues/detail?id=5497 // Um diese Klasse zu verwenden, rufen Sie einfach assistActivity() auf einer Activity auf, die bereits ihren Inhalt view gesetzt hat. public static void assistActivity (Activity activity) { new AndroidBug5497Workaround(activity); } private View mChildOfContent; private int usableHeightPrevious; private FrameLayout.LayoutParams frameLayoutParams; private AndroidBug5497Workaround(Activity activity) { FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content); mChildOfContent = content.getChildAt(0); mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { public void onGlobalLayout() { possiblyResizeChildOfContent(); } }); frameLayoutParams = (FrameLayout.LayoutParams) mChildOfContent.getLayoutParams(); } private void possiblyResizeChildOfContent() { int usableHeightNow = computeUsableHeight(); if (usableHeightNow != usableHeightPrevious) { int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight(); int heightDifference = usableHeightSansKeyboard - usableHeightNow; if (heightDifference > (usableHeightSansKeyboard/4)) { // Die Tastatur wurde wahrscheinlich sichtbar frameLayoutParams.height = usableHeightSansKeyboard - heightDifference; sonst { // Die Tastatur wurde wahrscheinlich ausgeblendet frameLayoutParams.height = usableHeightSansKeyboard; } mChildOfContent.requestLayout(); usableHeightPrevious = usableHeightNow; } } private int computeUsableHeight() { Rect r = new Rect(); mChildOfContent.getWindowVisibleDisplayFrame(r); return (r.bottom - r.top);// Im Vollbildmodus: return r.bottom } }
Der Code macht im Grunde genommen folgende Dinge:
1.Finden Sie den Wurzel-View der activity
Schauen wir uns den Eingangscode an:
FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content); mChildOfContent = content.getChildAt(0);
Dabei bezieht sich der View, der durch android.R.id.content in der ersten Zeile angegeben ist, auf den Wurzel-View, den Entwickler auf allen Activity-Oberflächen von Android steuern können.
如果Activity是全屏模式,那么android.R.id.content就占满了整个屏幕区域。
如果Activity是普通的非全屏模式,那么android.R.id.content就占满了除状态栏之外的所有区域。
其他情况,如Activity是弹窗、或者7.0以后的分屏样式等,android.R.id.content也是弹窗的范围或分屏所在的半个屏幕——这些情况较少,就暂且不考虑了。
我们经常使用的setContentView(View view)/setContent(int layRes)实际上就是把我们指定的View或layRes放入android.R.id.content中,成为它的子View。
因此,然后,第二行content.getChildAt(0)获取到的mChildOfContent,实际上也就是用来获取我们用setContentView放入的View。
2.设置一个监听器来监听View树的变化
mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener({ //简化了写法 possiblyResizeChildOfContent(); });
View.getViewTreeObserver()可以获取一个ViewTreeObserver对象——这个对象是一个观察者,专门用来监听当前View树所发生的一些变化。这里所注册的addOnGlobalLayoutListener,就是会在当前的View树的全局布局(GlobalLayout)发生变化、或者其中的View可视状态有变化时,进行通知回调。
——‘软键盘弹出’,是触发此事件的一个来源。(软键盘弹出会使GlobalLayout发生变化)
也就是说,现在可以监听到“软键盘弹出”的事件了。
3.界面变化后,获取“可用高度”
当软键盘弹出后,接下来的事情是获取改变后的界面的可用高度(可以被开发者用来显示内容的高度)。
直接看代码:
private int computeUsableHeight() { Rect rect = new Rect(); mChildOfContent.getWindowVisibleDisplayFrame(rect); // rect.top ist die Höhe des Statusbalkens. Wenn es sich um ein Vollbildthema handelt, reicht es aus, direkt return rect.bottom zu verwenden return (rect.bottom - rect.top); }
View.getWindowVisibleDisplayFrame(Rect rect), diese Zeile Code kann获得的Rect - das ist der Bereich des Interfaces, abgesehen vom Titel, abgesehen vom Teil, der von der Tastatur verdeckt wird, der verbleibende Rechteckbereich - wie gezeigt, im roten Rahmen.
Schematische Darstellung des Rect-Bereichs
Man kann auch erkennen:
rect.top ist die Höhe des Titelleisten. (Dies wird auch oft als Methode zur Erteilung der Höhe des Titelleisten verwendet)
Bildschirmhöhe-rect.bottom, ist die Höhe der Tastatur. (Auch der Weg, um die Höhe der Tastatur zu erhalten, ist aufgetaucht)
Daher haben wir:
Im Vollbildmodus beträgt die verfügbare Höhe = rect.bottom
Im Nicht-Vollbildmodus beträgt die verfügbare Höhe = rect.bottom - rect.top
4.Letzter Schritt: Setzen Sie die Höhe neu
Die von uns berechnete verfügbare Höhe ist die aktuelle sichtbare Oberfläche im visuellen Effekt. Aber die tatsächliche Höhe des aktuellen Interfaces ist höher als die verfügbare Höhe um den Abstand der Tastatur.
Daher ist der letzte Schritt, die Oberfläche auf die verfügbare Höhe zu setzen - das Werk ist vollendet.
private void possiblyResizeChildOfContent() { int usableHeightNow = computeUsableHeight(); if (usableHeightNow != usableHeightPrevious) { int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight(); int heightDifference = usableHeightSansKeyboard - usableHeightNow; if (heightDifference > (usableHeightSansKeyboard/4)) { // Die Tastatur wurde wahrscheinlich sichtbar frameLayoutParams.height = usableHeightSansKeyboard - heightDifference; sonst { // Die Tastatur wurde wahrscheinlich ausgeblendet frameLayoutParams.height = usableHeightSansKeyboard; } mChildOfContent.requestLayout(); usableHeightPrevious = usableHeightNow; } }
Im obigen Code wurde eine Bedingung "heightDifference > (usableHeightSansKeyboard/4Die Überprüfung der Klammer ) ist, um unnötige Störungen zu beseitigen. Da es viele Gründe gibt, die das Erscheinen des OnGlobalLayout-Ereignisses auslösen können, nicht nur die Änderung des Erscheinens des Tastaturfelds, sondern auch die Änderungen der Anzeige der verschiedenen Unteransichten, die geringen Einfluss auf die Höhe der Oberfläche haben. Nach der Addition dieser Überprüfung wird nur die Änderung der Höhe der Oberfläche, die über1/4Die Höhe des Bildschirms, bevor eine Neukonfiguration der Höhe durchgeführt wird, kann sicherstellen, dass der Code nur auf das Erscheinen der Tastatur reagiert.
Zusammenfassung
Zusammengefasst, ist es so:
Normale Activity (ohne WebView), verwenden Sie direkt adjustpan oder adjustResize
Wenn WebView enthalten ist:
a) Wenn es sich nicht um den Vollbildmodus handelt, kann adjustResize verwendet werden
b) Wenn es sich um den Vollbildmodus handelt, verwenden Sie AndroidBug5497Workaround behandeln.
Die oben genannten sind die endgültigen Lösungen, die der Redakteur den Lesern vorgestellt hat, um das Problem, dass das Android-Tastaturfeld den Eingabefeldern im Wege steht, zu lösen. Hoffentlich hilft dies den Lesern. Wenn Sie Fragen haben, hinterlassen Sie bitte eine Nachricht, der Redakteur wird rechtzeitig antworten. Ich danke auch sehr für die Unterstützung der Website Anleitungshub.
Erklärung: Der Inhalt dieses Artikels wurde aus dem Internet entnommen und gehört dem Urheberrechtinhaber. Der Inhalt wurde von Internetnutzern freiwillig beigesteuert und hochgeladen. Diese Website besitzt keine Eigentumsrechte und hat den Inhalt nicht manuell bearbeitet. Sie übernimmt auch keine rechtlichen Verantwortlichkeiten. Wenn Sie verdächtige urheberrechtliche Inhalte finden, sind Sie herzlich eingeladen, eine E-Mail an notice#w zu senden.3codebox.com (Bitte ersetzen Sie # durch @ beim Senden von E-Mails, um eine Meldung zu erstatten und relevante Beweise bereitzustellen. Sobald nachgewiesen wird, dass die Inhalte urheberrechtlich geschützt sind, wird diese Website die fraglichen Inhalte sofort löschen.