Sanal klavyenin gösterilip gösterilmemesine bağlı olarak düzeni değiştirmek istiyorum. API ve çeşitli bloglarda arama yaptım ancak yararlı bir şey bulamıyorum.
Mümkün mü?
Teşekkürler!
Sanal klavyenin gösterilip gösterilmemesine bağlı olarak düzeni değiştirmek istiyorum. API ve çeşitli bloglarda arama yaptım ancak yararlı bir şey bulamıyorum.
Mümkün mü?
Teşekkürler!
Yanıtlar:
Bu çözüm, yumuşak klavyeler için çalışmaz ve
onConfigurationChanged
yumuşak (sanal) klavyeler için çağrılmaz.
Konfigürasyon değişikliklerini kendiniz halletmelisiniz.
http://developer.android.com/guide/topics/resources/runtime-changes.html#HandlingTheChange
Örneklem:
// 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();
}
}
Ardından, bazı görünümlerin görünürlüğünü değiştirin, bir alanı güncelleyin ve düzen dosyanızı değiştirin.
newConfig.keyboardHidden == Configuration.KEYBOARDHIDDEN_NO
~ Chris
Bu en etkili çözüm olmayabilir. Ama bu benim için her zaman işe yaradı ... SoftKeyboard'u dinlemem gereken her yerde bu işlevi çağırıyorum.
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;
}
}
});
}
Not: Bu yaklaşım, kullanıcı kayan bir klavye kullanıyorsa sorunlara neden olacaktır.
android:windowSoftInputMode="adjustPan"
veya adjustResize
tam ekran penceresiyle ayarlanan Etkinlikler için de çalışmaz .
IMM (sanal) klavye penceresinin Etkinliğinizden gösterilmesini / gizlenmesini istiyorsanız, mizanpajınızı alt sınıflandırmanız ve onMesure yöntemini geçersiz kılmanız gerekir (böylece mizanpajınızın ölçülen genişliğini ve ölçülen yüksekliğini belirleyebilirsiniz). Bundan sonra setContentView () ile Faaliyetiniz için alt sınıf düzeni ana görünüm olarak ayarlayın. Artık IMM pencere olaylarını göster / gizle işlemlerini yapabileceksiniz. Bu karmaşık görünüyorsa, o kadar da değil. İşte kod:
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>
Şimdi Etkinliklerinize göre düzeniniz için alt sınıf bildirin (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);
}
}
Alt sınıf yapıcısındaki Etkinliğimiz için düzeni şişirdiğimiz koddan görebilirsiniz
inflater.inflate(R.layout.main, this);
Ve şimdi Faaliyetimiz için alt sınıf düzeninin içerik görünümünü ayarlayın.
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"
veya adjustResize
tam ekran penceresiyle ayarlanan Etkinlikler için çalışmaz .
Bu şekilde yaptım:
OnKeyboardVisibilityListener
Arayüz ekle .
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();
}
}
Umarım bu sana yardımcı olur.
Nebojsa Tomcic koduna dayanarak aşağıdaki RelativeLayout-Subclass yazılımını geliştirdim:
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();
}
}
}
Bu gayet iyi çalışıyor ... İşaretle, bu çözüm sadece Faaliyetinizin Yumuşak Giriş Modu "WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE" olarak ayarlandığında çalışır
android:windowSoftInputMode="adjustPan"
veya adjustResize
tam ekran penceresiyle ayarlanan Etkinlikler için de çalışmaz .
@ AmalBit'in cevabı gibi, bir dinleyiciyi global düzene kaydedin ve dectorView'ın görünür alt ve önerilen alt farkını hesaplayın, eğer fark bir değerden daha büyükse (tahmin edilen IME'nin yüksekliği), IME'nin yükseldiğini düşünüyoruz:
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;
}
yükseklik eşiği 100, IME'nin tahmin edilen minimum yüksekliğidir.
Bu, adjustPan ve adjustResize için çalışır.
Nebojsa'nın çözümü neredeyse benim için çalıştı. Çok satırlı bir EditText'i tıklattığımda klavyenin görüntülendiğini biliyordu, ancak EditText'in içine yazmaya başladığımda, actualHeight ve recommendedHeight hala aynıydı, bu yüzden klavyenin hala görüntülendiğini bilmiyorlardı. Maksimum yüksekliği saklamak için küçük bir değişiklik yaptım ve iyi çalışıyor. Gözden geçirilmiş alt sınıf:
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);
}
}
Kimsenin bunu gönderip göndermediğinden emin değilim. Bulunan bu çözüm basit kullanımı ile! . SoftKeyboard sınıf gist.github.com üzerindedir . Ancak klavye açılır / olay geri aramasını gizle, kullanıcı arayüzünde işleri düzgün bir şekilde yapmak için bir işleyiciye ihtiyacımız var:
/*
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
...
}
});
}
});
Bu benim özel EditText onKeyPreIme (int keyCode, KeyEvent olay) geçersiz kılarak çözmek.
@Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
//keyboard will be hidden
}
}
Bunu yapmak için bir çeşit kesmek var. Yumuşak klavye görünür veya gizli algılayan bir yol olarak görünmüyor olsa da, olabilir o zaman aslında algılamak yaklaşık bir ayarlayarak gösterilen veya gizlenecek şekilde OnFocusChangeListener
üzerine EditText
size bu konum dinleme.
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
}
});
NOT: Bu hack ile dikkat edilmesi gereken bir şey, EditText
kazançlar veya odak kaybedildiğinde bu geri aramanın hemen tetiklenmesidir . Bu , yumuşak klavye gösterilmeden veya gizlenmeden hemen önce patlar. Klavye gösterdikten veya gizlendikten sonra bir şey yapmanın en iyi yolu , bir şeyi kullanmak Handler
ve ~ 400ms geciktirmektir, şöyle:
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
sadece EditText
devlet değiştikten sonra odaklanıp odaklanmadığını söyler . Ama odak IME
olduğunda gizli olabilir EditText
, bu dava nasıl tespit edilir?
Sander, yumuşak klavye tarafından engellenen görünümü göstermeye çalıştığına inanıyorum. Bu http://android-developers.blogspot.com/2009/04/updating-applications-for-on-screen.html adresini deneyin .
Tek satırlı textview geri kodlamada sorunu çözdüm.
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);
}
}
Ayrıca ilk DecorView alt alt dolgusunu da kontrol edebilirsiniz. Klavye gösterildiğinde sıfırdan farklı bir değere ayarlanır.
@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);
}
Gizle | Klavye için olayları göster OnGlobalLayoutListener'da basit bir saldırı ile dinlenebilir:
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
}
}
});
Burada activityRootView, Etkinliğinizin kök görünümüdür.
klavye olayını kolayca almak için viewTreeObserver kullanarak .
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 sizin görünümünüzedit_text.parent
Nebojsa Tomcic'in cevabı bana yardımcı olmadı. Ben RelativeLayout
ile TextView
ve AutoCompleteTextView
onun içinde. TextView
Klavye gösterildiğinde ve gizlendiğinde alt kısmına kaydırmam gerekiyor . Bunu başarmak için onLayout
yöntemi aştım ve benim için iyi çalışıyor.
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);
}
}
}