Android: Dialog में EditText सॉफ्ट कीबोर्ड को नहीं खींचता है


82

इसलिए मुझे लगता है कि जो एक आम समस्या लगती है, वह यह है कि मेरे संवाद बॉक्स में EditText फोकस होने पर दिखाई नहीं देता है। मैंने कई वर्कअराउंड्स देखे हैं, जैसे कि इस थ्रेड में , यह एक और यह एक (और कई और अधिक), लेकिन मैंने कभी भी इसके लिए संतोषजनक स्पष्टीकरण नहीं देखा कि यह पहले स्थान पर क्यों हो रहा है।

मैं अपने खुद के निर्माण की तुलना में EditTexts के लिए अपने स्वयं के डिफ़ॉल्ट व्यवहार का उपयोग करना पसंद करूंगा, लेकिन ऐसा लगता है कि सभी (उन थ्रेड्स में) ने स्वीकार किया है कि Dialogs में EditTexts के लिए डिफ़ॉल्ट व्यवहार सिर्फ एक कर्सर देने के लिए है और कोई कीबोर्ड नहीं है। ऐसा क्यों होगा?

रिकॉर्ड के लिए, इनमें से कोई भी वर्कअराउंड मेरे लिए काम नहीं करता है - निकटतम मैं आने में सक्षम हूं जो संवाद बॉक्स के नीचे दिखाई देने के लिए एक कीबोर्ड को मजबूर कर रहा है (InputMethodManager.toggleSoftKeyboard (*) का उपयोग करके)। मेरा विशेष कॉन्फ़िगरेशन API15 है, EditText एक AlertDialog के भीतर एक ListView पर पाद लेख में दिखाता है। EditText Android: focusable = "true" सेट किया गया है, और onFocusChangeListener पर फोकस ईवेंट्स प्राप्त हो रहे हैं।

संपादित करें:

जैसा कि अनुरोध किया गया है, यहां विशिष्ट कोड स्निपेट है, जिसके साथ मैं काम कर रहा हूं। मैं पूरे लेआउट के साथ परेशान नहीं करूँगा, लेकिन इस विशिष्ट अनुप्रयोग में, EditText डायलॉग पर एक बटन दबाने के लिए ( एक एक्शन दृश्य के समान ) दिखाई देता है। यह एक RelativeLayout में निहित है जो डिफ़ॉल्ट रूप से दृश्यता "चला गया" है:

 <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>

इसे बनाने वाला कोड सापेक्ष दृश्य की दृश्यता को "दृश्यमान" सेट करता है (और अन्य UI तत्वों को छुपाता है)। EditText के साथ मेरे अनुभव के आधार पर जब EditText केंद्रित हो जाता है, तो कीबोर्ड को खींचने के लिए यह पर्याप्त होना चाहिए । हालाँकि, किसी कारण से यह मामला नहीं है। मैं निम्नलिखित onFocusChangeListener सेट कर सकते हैं:

    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."));
                }
            }
        });

इस कॉन्फ़िगरेशन का उपयोग करते हुए, जब मैं पहली बार EditText दर्ज करता हूं , onFocusChangedListener ट्रिगर करता है, और एक लॉग बनाता है जो हमेशा इस तरह दिखता है:

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

कीबोर्ड दिखाता है और फिर गायब हो जाता है, शायद इसलिए कि मैं इसे दो बार टॉगल करता हूं, लेकिन जब भी मैं यह सुनिश्चित करता हूं कि यह ऊपर रहता है, तो यह संवाद विंडो (एक ग्रे आउट क्षेत्र) के पीछे है, और संवाद को बंद किए बिना इसे प्राप्त करने का कोई तरीका नहीं है। ।

उस ने कहा, मैं इस बात पर जोर देना चाहता हूं कि भले ही मैं इस काम को करने में सक्षम हो जाऊं , लेकिन मैं मुख्य रूप से एक साधारण कारण खोजने में दिलचस्पी रखता हूं कि एडिट टेक्स्ट पहले स्थान पर क्यों नहीं चल रहा है, और यह क्यों इतनी आम बात लगती है!


क्या आप संबंधित कोड स्निपेट (जहां आप फोकस सेट करते हैं, फोकस श्रोता आदि) पोस्ट करने का मन करेंगे?
अलेक्जेंडर लुकास

मैं (और जब मैं किसी कंप्यूटर पर वापस जाऊंगा), लेकिन मुझे लगता है कि मेरा व्यापक प्रश्न एक फोकस श्रोता को शामिल नहीं करता है। मैं सोच रहा हूं कि यह एक आम समस्या क्यों लगती है कि एक संवाद में पाठ को संपादित करने से कीबोर्ड नहीं खुलता है। हालांकि मैं एक kluge का उपयोग करने के लिए खुश हूँ अगर ऐसा करने का तरीका है, लेकिन मैं जानना चाहूंगा कि ऐसा क्यों आवश्यक है।
पॉल

जवाबों:


188

ठीक है, इसलिए बहुत पढ़ने के बाद, मुझे पता चला है कि यह एक समस्या क्यों है, और मुझे किसी भी वर्कअराउंड का उपयोग करने की आवश्यकता नहीं है।

यह समस्या कम से कम (मेरे मामले में) प्रतीत होती है, कि चूंकि आप जिस जगह पर पाठ दर्ज करते हैं, वह शुरू में (या नेस्टेड या कुछ और) छिपा होता है, AlertDialog स्वचालित रूप से झंडा WindowManager.LayoutParams.FLAG_ALP_FOCUSABLE_IM (या उस और WindowManager का कुछ संयोजन) सेट कर रहा है .LayoutParams.FLAG_NOT_FOCUSABLE) ताकि चीजें दिखाने के लिए एक नरम इनपुट को ट्रिगर न करें।

जिस तरह से मैंने इसे ठीक करने के लिए पाया है वह संवाद बनने के बाद निम्नलिखित पंक्ति को जोड़ना है:

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

एक बार यह हो जाने के बाद, EditText एक सामान्य EditText की तरह काम करता है, कोई कीचड़ या वर्कअराउंड आवश्यक नहीं है।


83
जब मैंने झंडे को साफ़ करने की कोशिश की उसके बाद बनाएँ ने काम नहीं किया। यह केवल तभी काम करता है जब मैंने इसे इस तरह इस्तेमाल किया: डायलॉग = बिल्डर.क्रीट (); Dialog.show (); Dialog.getWindow ()। ClearFlags (WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE -IMIM); । Dialog.getWindow () setSoftInputMode (WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
एलेक्स फ्रैगोटिस

1
@AlexanderFragotsis stackoverflow पर इतने सारे अलग अलग समाधानों की कोशिश करने के बाद, आपकी टिप्पणी केवल एक ही काम करती है! धन्यवाद!
ब्रूस

20
SOFT_INPUT_STATE_-VISIBLE ने मेरे लिए काम नहीं किया। मैंने SOFT_INPUT_STATE_ALWAYS_VISIBLE का उपयोग किया और फिर इसने काम किया। अगर किसी और को भी यही समस्या है तो इसे बाहर
रखें

हाँ, मैं काम करने के लिए SOFT_INPUT_STATE_VISIBLE नहीं पा सका, लेकिन _ALWAYS_VISIBLE काम करता है। किसी को पता है कि वहाँ क्या हो रहा है?
बोगी

के clearFlags()बाद करने के लिए बहुत महत्वपूर्ण है show(), धन्यवाद @AlexanderFragotsis
जेवियर मेंडोंका

17

मेरे अपने ऐप में भी यही समस्या है। यदि आप API स्तर> = 8 के लिए विकसित कर रहे हैं, तो आप इस स्निपेट का उपयोग कर सकते हैं:

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

मुझे निम्न API स्तरों का समाधान नहीं मिला है ...

BTW: यह स्निपेट हमेशा एमुलेटर पर काम नहीं करता है। मुझे पता नहीं क्यों।


2
मुझे इस विशिष्ट वर्कअराउंड में इतनी दिलचस्पी नहीं है क्योंकि मुझे इसमें दिलचस्पी है कि यह पहली जगह में क्यों काम नहीं कर रहा है। इसके अतिरिक्त, मैं वास्तव में कीबोर्ड को डायलॉग के साथ नहीं दिखाना चाहता हूं, मैं चाहता हूं कि यह तब दिखाई दे, जब एडिटटेक्स्ट को फोकस होता है, जैसे एक सामान्य एडिट टेक्स्ट का व्यवहार।
पॉल

1
इसने मेरे लिए काम किया। बस का उपयोग AlertDialog dialog = builder.create();करने से पहले और dialog.show();AlertDialog.Builder आप उपयोग कर रहे ऊपर अगर के बाद
मैट कोनोली

1
यह एकमात्र ऐसा है जिसने मेरे लिए काम किया। मुझे यह भी नहीं लगता कि यह वर्कअराउंड है, यह तब समझ में आता है जब आप इसे एंड्रॉइड डॉक्स से उद्धृत करते हुए नीचे दिए गए उत्तर के साथ पढ़ते हैं कि आप डायलॉग वास्तव में दिखाने तक ध्यान केंद्रित करने का अनुरोध क्यों नहीं कर सकते।
मिक बायरन

17

यदि आप AlertDialog प्रलेखन को पढ़ेंगे, तो आप वहां पाएंगे:

AlertDialog वर्ग स्वचालित रूप से स्थापित करने का ख्याल रखता है * WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM * के लिए के आधार पर आप चाहे संवाद बदले में किसी भी विचारों की वजह से सच View.onCheckIsTextEditor () । आम तौर पर आप इस सेट को टेक्स्ट एडिटर के बिना डायलॉग के लिए चाहते हैं , ताकि इसे वर्तमान इनपुट विधि UI के शीर्ष पर रखा जाए। आप onCreate पर कॉल करने के बाद ध्वज को अपने इच्छित मोड पर मजबूर करके इस व्यवहार को संशोधित कर सकते हैं ।

आपके द्वारा डायलॉग के अंदर ListView में EditText के साथ उल्लिखित समस्या थी। मैंने इसे कस्टम व्यू क्लास (मेरे मामले में लिस्ट व्यू में) को अपने फ़ोकसेबल लाइस्टव्यू के साथ लिखकर, केवल एक तरीके से ओवरराइट करके तय किया:

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;
    }
}

तो मैं इसे लेआउट फ़ाइल में उपयोग कर रहा हूं:

<?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" />

आप अपने मामले में RelativeLayout को उसी तरह से अधिलेखित कर सकते हैं और इसे काम करना चाहिए।


सही काम कर रहा है, लेकिन एंड्रॉइड स्टूडियो (संस्करण 1.5.1) पूर्वावलोकन लेआउट को प्रस्तुत नहीं करता है
चोलत्स्की

9

इसी से मेरा काम बना है। AlertDialog.Builder, सेट शीर्षक, पॉजिटिवButton, negativeButton। ऐसा करने के बाद:

    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();

आपको उपयोग करने की आवश्यकता नहीं है builder.show();


धन्यवाद आंद्रे, तुम आदमी हो। मैंने एसओ पर यहां कई समाधानों की कोशिश की। यह केवल वही है जो काम कर रहा है
प्रोडक्शनकोडर

8

ऊपर दिया गया कोड बहुत सहायक है। लेकिन आपको "बनाएं" विधि के बाद "शो" विधि को कॉल करना होगा (मुझे नहीं पता कि क्यों, लेकिन यह केवल लिस्ट में EditText के साथ मेरे संवाद में काम करता है)। ऑनक्रिएट डिअलॉग में विधि:

@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;
}

क्या वह कोड वास्तव में काम करता है? a को AlertDialog के रूप में इनिशियलाइज़ किया गया है लेकिन कंस्ट्रक्टर एक बिल्डर है। बिल्डरों के पास एक बनाने की विधि होती है जो एक संवाद को लौटाता है, संवादों को दिखाने के लिए एक शो विधि है
पॉल

@Paul क्षमा करें। एक बिल्डर द्वारा संवाद निर्माण के भाग में कोड को गलत तरीके से लिखा गया था। मैंने इसे ठीक किया।
ILya2IK

7

धन्यवाद! मेरे पास चेतावनी संवाद टुकड़े में एम्बेडेड ListView की अंतिम पंक्ति में एक एम्बेडेड TextEdit है। मैंने झंडे को पोस्ट रन करने योग्य के रूप में साफ़ करने के आपके समाधान का उपयोग किया और अब यह पूरी तरह से काम करता है।

    @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

यहाँ यह करने का एक तरीका है:

    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

मैं पॉल के जवाब और अलेक्जेंडर की टिप्पणी पर जोड़ना चाहूंगा ।

मेरे पास स्वयं एक ऐसा संवाद है onCreateDialog()जो विधि में बनाया गया है , जो (लगता है) को वापस लौटने की आवश्यकता है, जिसमें dialog.show();आप उस लेआउटप्रेम को संवाद में नहीं जोड़ सकते जहां संवाद बनाया जाता है। इसके आस-पास काम करने के लिए, बस अपनी onCreateDialog()विधि समान रखें, और एक onResume()विधि इस प्रकार जोड़ें :

@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);
}

यह चाल चलनी चाहिए, यह मेरे लिए काम करती है, शुक्र है। काफी समय से इस मामले पर हैं।


0

डायलॉग में कीबोर्ड दिखाने के लिए पूरा कोड:

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
अपना जवाब समझाने की कोशिश कर रहा है। केवल कोड मत डालो। संबंधित कोड पर विशिष्ट उत्तर और स्पष्टीकरण दें ...
संदीप आर्मल पाटिल

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

बस नीचे जोड़ें कोड:

// स्वचालित रूप से कीबोर्ड दिखाने के लिए जब editText डायलॉग डायलॉग .getWindow () में सेट किया गया है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.