Ich möchte das Layout basierend darauf ändern, ob die virtuelle Tastatur angezeigt wird oder nicht. Ich habe die API und verschiedene Blogs durchsucht, kann aber anscheinend nichts Nützliches finden.
Ist es möglich?
Vielen Dank!
Ich möchte das Layout basierend darauf ändern, ob die virtuelle Tastatur angezeigt wird oder nicht. Ich habe die API und verschiedene Blogs durchsucht, kann aber anscheinend nichts Nützliches finden.
Ist es möglich?
Vielen Dank!
Antworten:
Diese Lösung funktioniert nicht für Softtastaturen und
onConfigurationChanged
wird nicht für Softtastaturen (virtuelle Tastaturen) aufgerufen.
Sie müssen Konfigurationsänderungen selbst vornehmen.
http://developer.android.com/guide/topics/resources/runtime-changes.html#HandlingTheChange
Stichprobe:
// from the link above
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Checks whether a hardware keyboard is available
if (newConfig.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO) {
Toast.makeText(this, "keyboard visible", Toast.LENGTH_SHORT).show();
} else if (newConfig.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_YES) {
Toast.makeText(this, "keyboard hidden", Toast.LENGTH_SHORT).show();
}
}
Ändern Sie dann einfach die Sichtbarkeit einiger Ansichten, aktualisieren Sie ein Feld und ändern Sie Ihre Layoutdatei.
newConfig.keyboardHidden == Configuration.KEYBOARDHIDDEN_NO
~ Chris
Dies ist möglicherweise nicht die effektivste Lösung. Aber das hat bei mir jedes Mal funktioniert ... Ich rufe diese Funktion überall dort auf, wo ich das softKeyboard hören muss.
boolean isOpened = false;
public void setListenerToRootView() {
final View activityRootView = getWindow().getDecorView().findViewById(android.R.id.content);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
int heightDiff = activityRootView.getRootView().getHeight() - activityRootView.getHeight();
if (heightDiff > 100) { // 99% of the time the height diff will be due to a keyboard.
Toast.makeText(getApplicationContext(), "Gotcha!!! softKeyboardup", 0).show();
if (isOpened == false) {
//Do two things, make the view top visible and the editText smaller
}
isOpened = true;
} else if (isOpened == true) {
Toast.makeText(getApplicationContext(), "softkeyborad Down!!!", 0).show();
isOpened = false;
}
}
});
}
Hinweis: Dieser Ansatz verursacht Probleme, wenn der Benutzer eine schwebende Tastatur verwendet.
android:windowSoftInputMode="adjustPan"
oder adjustResize
mit einem Vollbildfenster festgelegt wurden, da die Größe des Layouts niemals geändert wird.
Wenn Sie das Ein- / Ausblenden des (virtuellen) IMM-Tastaturfensters in Ihrer Aktivität behandeln möchten, müssen Sie Ihr Layout in Unterklassen unterteilen und die onMesure-Methode überschreiben (damit Sie die gemessene Breite und die gemessene Höhe Ihres Layouts bestimmen können). Danach legen Sie mit setContentView () das untergeordnete Layout als Hauptansicht für Ihre Aktivität fest. Jetzt können Sie IMM-Fensterereignisse ein- und ausblenden. Wenn das kompliziert klingt, ist es nicht wirklich so. Hier ist der Code:
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >
<EditText
android:id="@+id/SearchText"
android:text=""
android:inputType="text"
android:layout_width="fill_parent"
android:layout_height="34dip"
android:singleLine="True"
/>
<Button
android:id="@+id/Search"
android:layout_width="60dip"
android:layout_height="34dip"
android:gravity = "center"
/>
</LinearLayout>
Deklarieren Sie jetzt in Ihrer Aktivität die Unterklasse für Ihr Layout (main.xml).
public class MainSearchLayout extends LinearLayout {
public MainSearchLayout(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.main, this);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Log.d("Search Layout", "Handling Keyboard Window shown");
final int proposedheight = MeasureSpec.getSize(heightMeasureSpec);
final int actualHeight = getHeight();
if (actualHeight > proposedheight){
// Keyboard is shown
} else {
// Keyboard is hidden
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
Sie können dem Code entnehmen, dass wir das Layout für unsere Aktivität im Unterklassenkonstruktor aufblasen
inflater.inflate(R.layout.main, this);
Und jetzt legen Sie einfach die Inhaltsansicht des untergeordneten Layouts für unsere Aktivität fest.
public class MainActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MainSearchLayout searchLayout = new MainSearchLayout(this, null);
setContentView(searchLayout);
}
// rest of the Activity code and subclassed layout...
}
android:windowSoftInputMode="adjustPan"
oder adjustResize
mit einem Vollbildfenster festgelegt wurden, da die Größe des Layouts niemals geändert wird.
Ich habe es so gemacht:
OnKeyboardVisibilityListener
Schnittstelle hinzufügen .
public interface OnKeyboardVisibilityListener {
void onVisibilityChanged(boolean visible);
}
HomeActivity.java :
public class HomeActivity extends Activity implements OnKeyboardVisibilityListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sign_up);
// Other stuff...
setKeyboardVisibilityListener(this);
}
private void setKeyboardVisibilityListener(final OnKeyboardVisibilityListener onKeyboardVisibilityListener) {
final View parentView = ((ViewGroup) findViewById(android.R.id.content)).getChildAt(0);
parentView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
private boolean alreadyOpen;
private final int defaultKeyboardHeightDP = 100;
private final int EstimatedKeyboardDP = defaultKeyboardHeightDP + (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? 48 : 0);
private final Rect rect = new Rect();
@Override
public void onGlobalLayout() {
int estimatedKeyboardHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, EstimatedKeyboardDP, parentView.getResources().getDisplayMetrics());
parentView.getWindowVisibleDisplayFrame(rect);
int heightDiff = parentView.getRootView().getHeight() - (rect.bottom - rect.top);
boolean isShown = heightDiff >= estimatedKeyboardHeight;
if (isShown == alreadyOpen) {
Log.i("Keyboard state", "Ignoring global layout change...");
return;
}
alreadyOpen = isShown;
onKeyboardVisibilityListener.onVisibilityChanged(isShown);
}
});
}
@Override
public void onVisibilityChanged(boolean visible) {
Toast.makeText(HomeActivity.this, visible ? "Keyboard is active" : "Keyboard is Inactive", Toast.LENGTH_SHORT).show();
}
}
Hoffe das würde dir helfen.
Basierend auf dem Code von Nebojsa Tomcic habe ich die folgende RelativeLayout-Unterklasse entwickelt:
import java.util.ArrayList;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.RelativeLayout;
public class KeyboardDetectorRelativeLayout extends RelativeLayout {
public interface IKeyboardChanged {
void onKeyboardShown();
void onKeyboardHidden();
}
private ArrayList<IKeyboardChanged> keyboardListener = new ArrayList<IKeyboardChanged>();
public KeyboardDetectorRelativeLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public KeyboardDetectorRelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public KeyboardDetectorRelativeLayout(Context context) {
super(context);
}
public void addKeyboardStateChangedListener(IKeyboardChanged listener) {
keyboardListener.add(listener);
}
public void removeKeyboardStateChangedListener(IKeyboardChanged listener) {
keyboardListener.remove(listener);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int proposedheight = MeasureSpec.getSize(heightMeasureSpec);
final int actualHeight = getHeight();
if (actualHeight > proposedheight) {
notifyKeyboardShown();
} else if (actualHeight < proposedheight) {
notifyKeyboardHidden();
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
private void notifyKeyboardHidden() {
for (IKeyboardChanged listener : keyboardListener) {
listener.onKeyboardHidden();
}
}
private void notifyKeyboardShown() {
for (IKeyboardChanged listener : keyboardListener) {
listener.onKeyboardShown();
}
}
}
Dies funktioniert ganz gut ... Markieren Sie, dass diese Lösung nur funktioniert, wenn der Soft Input-Modus Ihrer Aktivität auf "WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE" eingestellt ist.
android:windowSoftInputMode="adjustPan"
oder adjustResize
mit einem Vollbildfenster festgelegt wurden, da die Größe des Layouts niemals geändert wird.
Registrieren Sie wie bei @ amalBits Antwort einen Listener für das globale Layout und berechnen Sie die Differenz zwischen dem sichtbaren Boden von dectorView und dem vorgeschlagenen Boden. Wenn der Unterschied größer als ein Wert ist (geschätzte IME-Höhe), denken wir, dass IME oben ist:
final EditText edit = (EditText) findViewById(R.id.edittext);
edit.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
if (keyboardShown(edit.getRootView())) {
Log.d("keyboard", "keyboard UP");
} else {
Log.d("keyboard", "keyboard Down");
}
}
});
private boolean keyboardShown(View rootView) {
final int softKeyboardHeight = 100;
Rect r = new Rect();
rootView.getWindowVisibleDisplayFrame(r);
DisplayMetrics dm = rootView.getResources().getDisplayMetrics();
int heightDiff = rootView.getBottom() - r.bottom;
return heightDiff > softKeyboardHeight * dm.density;
}
Die Höhenschwelle 100 ist die geschätzte Mindesthöhe von IME.
Dies funktioniert sowohl für adjustPan als auch für adjustResize.
Nebojsas Lösung hat bei mir fast funktioniert. Als ich in einen mehrzeiligen EditText klickte, wusste ich, dass die Tastatur angezeigt wurde, aber als ich anfing, in den EditText zu tippen, waren die tatsächliche Höhe und die vorgeschlagene Höhe immer noch gleich, sodass nicht bekannt war, dass die Tastatur noch angezeigt wurde. Ich habe eine geringfügige Änderung vorgenommen, um die maximale Höhe zu speichern, und es funktioniert einwandfrei. Hier ist die überarbeitete Unterklasse:
public class CheckinLayout extends RelativeLayout {
private int largestHeight;
public CheckinLayout(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.checkin, this);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int proposedheight = MeasureSpec.getSize(heightMeasureSpec);
largestHeight = Math.max(largestHeight, getHeight());
if (largestHeight > proposedheight)
// Keyboard is shown
else
// Keyboard is hidden
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
Ich bin mir nicht sicher, ob jemand dies postet. Fand diese Lösung einfach zu bedienen! . Die SoftKeyboard-Klasse befindet sich auf gist.github.com . Aber während der Tastatur-Popup / Hide-Ereignis-Rückruf benötigen wir einen Handler, um die Dinge auf der Benutzeroberfläche richtig zu machen:
/*
Somewhere else in your code
*/
RelativeLayout mainLayout = findViewById(R.layout.main_layout); // You must use your root layout
InputMethodManager im = (InputMethodManager) getSystemService(Service.INPUT_METHOD_SERVICE);
/*
Instantiate and pass a callback
*/
SoftKeyboard softKeyboard;
softKeyboard = new SoftKeyboard(mainLayout, im);
softKeyboard.setSoftKeyboardCallback(new SoftKeyboard.SoftKeyboardChanged()
{
@Override
public void onSoftKeyboardHide()
{
// Code here
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
// Code here will run in UI thread
...
}
});
}
@Override
public void onSoftKeyboardShow()
{
// Code here
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
// Code here will run in UI thread
...
}
});
}
});
Ich löse dieses Problem, indem ich onKeyPreIme (int keyCode, KeyEvent-Ereignis) in meinem benutzerdefinierten EditText überschreibe.
@Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
//keyboard will be hidden
}
}
Ich habe eine Art Hack, um das zu tun. Es gibt zwar keine Möglichkeit zu erkennen , zu sein scheint , wenn die Soft - Tastatur angezeigt oder verborgen hat, Sie können in der Tat erkennen , wenn es etwa indem eine ein- oder ausgeblendet werden , OnFocusChangeListener
auf das EditText
gerade hören , dass Sie an.
EditText et = (EditText) findViewById(R.id.et);
et.setOnFocusChangeListener(new View.OnFocusChangeListener()
{
@Override
public void onFocusChange(View view, boolean hasFocus)
{
//hasFocus tells us whether soft keyboard is about to show
}
});
HINWEIS: Eine Sache, die Sie bei diesem Hack beachten sollten, ist, dass dieser Rückruf sofort ausgelöst wird, wenn der EditText
Fokus gewinnt oder verliert. Dies wird tatsächlich ausgelöst, bevor die Softtastatur angezeigt oder ausgeblendet wird. Der beste Weg, etwas zu tun, nachdem die Tastatur Handler
angezeigt oder ausgeblendet wurde, besteht darin, a zu verwenden und etwas ~ 400 ms zu verzögern, wie folgt:
EditText et = (EditText) findViewById(R.id.et);
et.setOnFocusChangeListener(new View.OnFocusChangeListener()
{
@Override
public void onFocusChange(View view, boolean hasFocus)
{
new Handler().postDelayed(new Runnable()
{
@Override
public void run()
{
//do work here
}
}, 400);
}
});
OnFocusChangeListener
Gibt nur an, ob EditText
der Fokus nach einer Statusänderung geändert wurde. Aber das IME
kann versteckt sein, wenn EditText
Fokus hat, wie man diesen Fall erkennt?
Sander, ich glaube, Sie versuchen, die von der Softtastatur blockierte Ansicht anzuzeigen. Versuchen Sie dies http://android-developers.blogspot.com/2009/04/updating-applications-for-on-screen.html .
Ich habe das Problem bei der einzeiligen Textansicht-Rückcodierung gelöst.
package com.helpingdoc;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
public class MainSearchLayout extends LinearLayout {
int hieght = 0;
public MainSearchLayout(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.main, this);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Log.d("Search Layout", "Handling Keyboard Window shown");
if(getHeight()>hieght){
hieght = getHeight();
}
final int proposedheight = MeasureSpec.getSize(heightMeasureSpec);
final int actualHeight = getHeight();
System.out.println("....hieght = "+ hieght);
System.out.println("....actualhieght = "+ actualHeight);
System.out.println("....proposedheight = "+ proposedheight);
if (actualHeight > proposedheight){
// Keyboard is shown
} else if(actualHeight<proposedheight){
// Keyboard is hidden
}
if(proposedheight == hieght){
// Keyboard is hidden
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
Sie können auch nach der untergeordneten Polsterung von DecorView suchen. Es wird auf einen Wert ungleich Null gesetzt, wenn die Tastatur angezeigt wird.
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
View view = getRootView();
if (view != null && (view = ((ViewGroup) view).getChildAt(0)) != null) {
setKeyboardVisible(view.getPaddingBottom() > 0);
}
super.onLayout(changed, left, top, right, bottom);
}
Hide | Show-Ereignisse für die Tastatur können durch einfachen Hack in OnGlobalLayoutListener abgehört werden:
final View activityRootView = findViewById(R.id.top_root);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
public void onGlobalLayout() {
int heightDiff = activityRootView.getRootView().getHeight() - activityRootView.getHeight();
if (heightDiff > 100) {
// keyboard is up
} else {
// keyboard is down
}
}
});
Hier ist activityRootView die Stammansicht Ihrer Aktivität.
Verwenden von viewTreeObserver zum einfachen Abrufen des Tastaturereignisses.
layout_parent.viewTreeObserver.addOnGlobalLayoutListener {
val r = Rect()
layout_parent.getWindowVisibleDisplayFrame(r)
if (layout_parent.rootView.height - (r.bottom - r.top) > 100) { // if more than 100 pixels, its probably a keyboard...
Log.e("TAG:", "keyboard open")
} else {
Log.e("TAG:", "keyboard close")
}
}
** layout_parent ist deine Ansicht wieedit_text.parent
Die Antwort von Nebojsa Tomcic war für mich nicht hilfreich. Ich habe RelativeLayout
mit TextView
und AutoCompleteTextView
drin. Ich muss nach TextView
unten scrollen , wenn die Tastatur angezeigt wird und wenn sie ausgeblendet ist. Um dies zu erreichen, habe ich die onLayout
Methode überschrieben und es funktioniert gut für mich.
public class ExtendedLayout extends RelativeLayout
{
public ExtendedLayout(Context context, AttributeSet attributeSet)
{
super(context, attributeSet);
LayoutInflater inflater = (LayoutInflater)
context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.main, this);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b)
{
super.onLayout(changed, l, t, r, b);
if (changed)
{
int scrollEnd = (textView.getLineCount() - textView.getHeight() /
textView.getLineHeight()) * textView.getLineHeight();
textView.scrollTo(0, scrollEnd);
}
}
}