Android: İletişim Kutusundaki Metni Düzenle yazılım klavyesini açmıyor


82

Bu yüzden, ortak bir sorun gibi görünen bir şeye sahibim, o da iletişim kutumdaki EditText odaklandığında görünmüyor. Bu konu , bu ve bu (ve daha fazlası) gibi birkaç geçici çözüm gördüm , ancak bunun neden ilk başta olduğuna dair tatmin edici bir açıklama görmedim .

Android'in EditTexts için kendi varsayılan davranışını kullanmasını tercih ederim, ancak görünüşe göre herkes (bu konulardaki) Dialogs'taki EditTexts için varsayılan davranışın sadece bir imleç vermek ve klavye vermemek olduğunu kabul etti. Bu neden olur?

Kayıt için, bu geçici çözümlerin hiçbiri benim için işe yaramıyor - gelebildiğim en yakın şey, bir klavyeyi iletişim kutusunun altında görünmeye zorlamaktır (InputMethodManager.toggleSoftKeyboard (*) kullanarak). Benim özel konfigürasyonum API15, EditText bir AlertDialog içindeki ListView üzerinde bir altbilgide görünüyor. "True" odaklanabilir = ayarlanır ve onFocusChangeListener: EditText android olan odak olayları alma.

Düzenle:

İstendiği gibi, üzerinde çalıştığım özel kod parçacığı burada. Tüm düzen ile uğraşmayacağım, ancak bu özel uygulamada, iletişim kutusundaki bir düğmeye basıldığında ( bir işlem görünümüne benzer ) EditText görünür . Varsayılan olarak görünürlüğü "gitmiş" olan bir RelativeLayout içinde bulunur:

 <RelativeLayout 
       android:id="@+id/relLay"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:layout_centerVertical="true"
       android:visibility="gone"
       android:layout_marginTop="5dp"
       android:layout_marginBottom="5dp">

        <ImageButton
            android:id="@+id/cancelBut"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:background="@color/transparent"
            android:src="@drawable/cancelButton" 
            android:layout_margin="5dp"/>

        <ImageButton
            android:id="@+id/okBut"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_toLeftOf="@id/cancelBut"
            android:background="@color/transparent"
            android:src="@drawable/okButton"
            android:layout_margin="5dp" />

        <EditText 
            android:id="@+id/editText"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:inputType="text"
            android:focusable="true"
            android:layout_toLeftOf="@id/okBut"/>
   </RelativeLayout>

Bunu oluşturan kod, relativeLayout'un görünürlüğünü "Visible" olarak ayarlar (ve diğer UI öğelerini gizler). Bu , EditText deneyimime dayalı olarak EditText odaklandığında klavyeyi açmak için yeterli olmalıdır . Ancak, bazı nedenlerden dolayı durum böyle değil. Aşağıdakileri onFocusChangeListener ayarlayabilirim:

    edit_text.setOnFocusChangeListener(new OnFocusChangeListener() {

            @Override
            public void onFocusChange(View v, boolean hasFocus) {
                // For whatever reason we need to request a soft keyboard.
                    InputMethodManager imm = (InputMethodManager)dlg.getWindow().getContext().getSystemService(_Context.INPUT_METHOD_SERVICE);
                    if(hasFocus)
                        imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
                    Log.v("DialogProblem", "Focus requested, " + (hasFocus?"has focus.":"doesn't have focus."));
                }
            }
        });

Bu yapılandırmayı kullanarak , EditText'e ilk girdiğimde, onFocusChangedListener tetiklenir ve her zaman şuna benzeyen bir günlük oluşturur:

Focus requested, has focus.
Focus requested, doesn't have focus.
Focus requested, has focus.

Klavye ortaya çıkıyor ve sonra kayboluyor, muhtemelen iki kez değiştirdiğim için, ancak açık kaldığından emin olsam bile , iletişim penceresinin arkasında (grileşmiş bir alanda) ve iletişim kutusunu kapatmadan ona ulaşmanın bir yolu yok .

Bununla birlikte, bu geçici çözümün işe yaramasına rağmen, öncelikle EditText'in neden ilk etapta tetiklenmediğinin ve bunun neden basit bir nedenini bulmakla ilgilendiğimi vurgulamak isterim. çok sıradan görünüyor!


İlgili kod parçacığını (odağı ayarladığınız, odak dinleyicisi eklediğiniz vb.) Yayınlayabilir misiniz?
Alexander Lucas

Yapabilirim (ve bir bilgisayara döndüğümde yapacağım), ancak daha geniş sorumun odak dinleyicisi içermediğini düşünüyorum. Bir iletişim kutusundaki metni düzenlemenin klavyeyi açmamasının neden yaygın bir sorun olduğunu merak ediyorum. Bunu yapmanın yolu buysa bir kluge kullanmaktan mutlu olsam da, böyle bir şeyin neden gerekli olduğunu bilmek isterim.
Paul

Yanıtlar:


190

Tamam, çok okuduktan sonra, ben bu sorunun neden anladım ettim ve do not herhangi bir geçici çözüm kullanmak gerekir.

Sorun şu ki (en azından benim durumumda), metin girdiğiniz yer başlangıçta gizlendiğinden (veya iç içe veya başka bir şey olduğundan), AlertDialog otomatik olarak WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM (veya bunun ve WindowManager'ın bazı kombinasyonlarını) .LayoutParams.FLAG_NOT_FOCUSABLE) böylece şeyler bir soft girdinin ortaya çıkmasını tetiklemez.

Bunu düzeltmenin yolu, iletişim kutusu oluşturulduktan sonra aşağıdaki satırı eklemektir:

dialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);

Bu yapıldıktan sonra, EditText normal bir EditText gibi davranır, herhangi bir kesinti veya geçici çözüm gerekmez.


84
Oluşturduktan sonra bayrakları temizlemeye çalıştığımda işe yaramadı. Yalnızca şu şekilde kullandığımda işe yaradı: Dialog = builder.create (); Dialog.show (); Dialog.getWindow (). ClearFlags (WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); Dialog.getWindow (). SetSoftInputMode (WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
Alex Fragotsis

1
@AlexanderFragotsis stackoverflow üzerinde o kadar çok farklı çözümü denedikten sonra, yorumunuz işe yarayan tek çözümdür! Teşekkür ederim!
Bruce

21
SOFT_INPUT_STATE_‌ VISIBLE benim için çalışmadı. SOFT_INPUT_STATE_ALWAYS_VISIBLE kullandım ve sonra çalıştı. Aynı sorunu
yaşayan

Evet, SOFT_INPUT_STATE_VISIBLE'ı da çalıştıramadım ama _ALWAYS_VISIBLE çalışıyor. orada neler olduğunu bilen var mı?
bwoogie

Yapmak için çok önemli clearFlags()SONRA show(), teşekkür @AlexanderFragotsis
Javier Mendonça

17

Kendi uygulamamda da aynı sorunu yaşıyorum. API seviyesi> = 8 için geliştirme yapıyorsanız bu pasajı kullanabilirsiniz:

dialog.setOnShowListener(new OnShowListener() {
    @Override
     public void onShow(DialogInterface dialog) {
         InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
         imm.showSoftInput(textEdit, InputMethodManager.SHOW_IMPLICIT);
    }
});

Daha düşük API seviyeleri için bir çözüm bulamadım ...

BTW: Bu snippet her zaman emülatörde çalışmaz. Neden bilmiyorum


2
Bu özel çözümle pek ilgilenmiyorum, çünkü neden ilk etapta işe yaramadığıyla ilgileniyorum. Ek olarak, klavyenin iletişim kutusu ile birlikte görünmesini istemiyorum, normal bir EditText davranışı gibi, EditText odak kazandığında görünmesini istiyorum.
Paul

1
Bu benim için çalıştı. AlertDialog.Builder kullanıyorsanız yukarıdakilerden AlertDialog dialog = builder.create();önce ve dialog.show();sonra kullanın
Matt Connolly

1
Bu benim için çalışan tek kişi. Ayrıca bunun bir geçici çözüm olduğunu düşünmüyorum, Android dokümanlarından alıntı yaparak aşağıdaki cevapla okuduğunuzda, diyalog gerçekten görünene kadar neden odak isteyemeyeceğiniz konusunda mantıklı.
Mick Byrne

17

AlertDialog belgelerini okursanız, orada bulacaksınız:

AlertDialog sınıfı otomatik ayarlama ilgilenir * WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM * için dayalı, ister gelen gerçek iletişim karşılığında herhangi görünümler View.onCheckIsTextEditor () . Genel olarak, bu seti metin düzenleyicileri olmayan bir İletişim Kutusu için istersiniz , böylece mevcut giriş yöntemi kullanıcı arayüzünün üstüne yerleştirilir. OnCreate'i çağırdıktan sonra bayrağı istediğiniz moda zorlayarak bu davranışı değiştirebilirsiniz .

Bir Dialog içinde ListView'da EditText ile bahsettiğiniz sorunu yaşadım. Özel görünüm sınıfının (benim durumumda ListView) üzerine kendi FocusableListView ile, üzerine yazılan tek bir yöntemle üzerine yazarak bunu düzelttim:

public class FocusableListView extends ListView {

    public FocusableListView(Context context) {
        super(context);
    }

    public FocusableListView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public FocusableListView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public boolean onCheckIsTextEditor() {
        // this is where the magic happens
        return true;
    }
}

Sonra bunu düzen dosyasında şu şekilde kullanıyorum:

<?xml version="1.0" encoding="UTF-8"?>
<com.myexample.wiget.FocusableListView 
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:descendantFocusability="beforeDescendants"
android:layout_height="wrap_content" />

Sizin durumunuzdaki RelativeLayout'un üzerine aynı şekilde yazabilirsiniz ve çalışmalıdır.


mükemmel çalışıyor, ancak Android Studio (sürüm 1.5.1) önizleme düzenini oluşturmuyor
Choletski

9

Bu benim için çalıştı. AlertDialog.Builder'ı oluşturun, title, positiveButton, negativeButton'ı ayarlayın. Bunu yaptıktan sonra:

    AlertDialog dialog = builder.create();
    dialog.getWindow().clearFlags( WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
    dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
    dialog.show();
    editText.requestFocus();

Kullanmanıza gerek yok builder.show();.


Teşekkürler André, adam sensin. SO'da burada çok fazla çözüm denedim. Bu çalışan tek kişi
productioncoder

8

Yukarıdaki kod çok yardımcıdır. Ancak "create" yönteminden sonra "show" yöntemini çağırmalısınız (nedenini bilmiyorum, ancak yalnızca bu, ListView'daki EditText ile iletişimimde çalışır). OnCreateDialog yönteminde:

@Override
protected Dialog onCreateDialog(int id) {
  switch (id) {
    case YOUR_DIALOG_ID: {
        //...
        AlertDialog a = new AlertDialog.Builder(this)./*
        ... set the properties here
        */
        .create();
        a.show(); //!!! this is very important to call the "show" method
        a.getWindow().clearFlags(
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
        return a;
    }
  //...
  }
  return null;
}

Bu kod gerçekten çalışıyor mu? a bir AlertDialog olarak başlatılır, ancak yapıcı bir oluşturucudur. İnşaatçıların bir iletişim kutusu döndüren bir oluşturma yöntemi vardır, iletişim kutuları bunları göstermek için bir göster yöntemine sahiptir.
Paul

@Paul Affedersiniz. Kod, bir inşaatçı tarafından yapılan bir diyalog oluşturma kısmında gerçekten yanlıştı. Düzelttim.
iLya2IK

7

Teşekkür ederim! Uyarı iletişim kutusu parçasına gömülü ListView'ın son satırında gömülü bir TextEdit var. Bayrakları temizleme çözümünüzü post runnable olarak kullandım ve şimdi mükemmel çalışıyor.

    @Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
    builder.setTitle("My Title");
    m_adapter = new MyAdapter(getContext());
    builder.setAdapter(m_adapter, new OnClickListener() {

        @Override
        public void onClick(DialogInterface dialog, int which) {
            // TODO Auto-generated method stub

        }
    }); 

    final AlertDialog dialog = builder.create();
    final ListView listView = dialog.getListView();
    listView.setOnItemClickListener(new OnItemClickListener() {

        @Override
        public void onItemClick(AdapterView<?> parent, View view,
                int position, long id) {

        }
    });

    listView.post(new Runnable() {

        @Override
        public void run() {
            dialog.getWindow().clearFlags(
                    WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
                    WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);              
        }
    });
    return dialog;
}

4

İşte bunu yapmanın bir yolu:

    final Window dialogWindow = dialog.getWindow();
    dialogWindow.clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
    dialogWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);

2

Paul'un cevabına ve İskender'in yorumuna eklemek istiyorum .

Benim de onCreateDialog()yöntemde oluşturulmuş bir iletişim kutusuna sahibim dialog.show();, bu da geri dönmeyi gerektiriyor , bu nedenle düzen parametrelerini diyalogun oluşturulduğu iletişim kutusuna ekleyemezsiniz. Bunu aşmak için, onCreateDialog()yönteminizi aynı tutun ve onResume()aşağıdaki gibi bir yöntem ekleyin :

@Override
public void onResume() {
    super.onResume();
    Dialog dialog = getDialog();
    dialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
    dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
}

Bu hile yapmalı, şükür benim için çalışıyor. Bir süredir bu davayla ilgileniyorlar.


0

klavyeyi iletişim kutusunda göstermek için tam kod:

public void onFocusChange(View v, boolean hasFocus) {
    Log.v("onFocusChange", hasFocus + " " + showkeyboard);
    if (hasFocus) {
        if (showkeyboard++ == 0) {
            alertDialog.getWindow().clearFlags(
                    WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                    | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
            alertDialog.getWindow().setSoftInputMode(
                    WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
        } else {
            showkeyboard = 1;
        }
    }
}

1
cevabınızı açıklamaya çalışıyorum. Yalnızca kod koymayın. İlgili kod hakkında özel bir cevap verin ve açıklama yapın ...
Sandip Armal Patil

0
This worked for me ----
editText.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
//dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
//dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
//dialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
InputMethodManager mgr = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
mgr.showSoftInput(v, InputMethodManager.SHOW_FORCED);
editText.setFocusable(true);
}
});

0

kod satırının altına eklemeniz yeterli:

// editText iletişim kutusundayken klavyeyi otomatik olarak göstermek için dialog.getWindow (). setSoftInputMode (WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.