किसी अन्य नियंत्रण पर ध्यान केंद्रित किए बिना फ़ोकस को हटाने के लिए कैसे?


95

मैं अपने UI को सहज होना पसंद करता हूं; प्रत्येक स्क्रीन को स्वाभाविक रूप से और विनीत रूप से उपयोगकर्ता को ऐप में अगले चरण पर मार्गदर्शन करना चाहिए। इस पर रोक लगाते हुए, मैं चीजों को यथासंभव भ्रमित और भ्रमित करने का प्रयास करता हूं।

मजाक कर रहा हूं :-)

मुझे तीन TableRowएस मिले हैं, जिनमें से प्रत्येक में केवल पढ़ने योग्य और गैर-फोकस करने योग्य EditText नियंत्रण है और फिर इसके दाईं ओर एक बटन है। प्रत्येक बटन एक ही गतिविधि शुरू करता है लेकिन एक अलग तर्क के साथ। उपयोगकर्ता वहां चयन करता है और उप-गतिविधि खत्म हो जाती है, EditTextजो उपयोगकर्ता के चयन के साथ उपयुक्त है ।

यह क्लासिक कैस्केडिंग मान तंत्र है; प्रत्येक चयन अगले चयन के लिए उपलब्ध विकल्पों को बताता है, आदि। इस प्रकार मैं अगली पंक्तियों में से प्रत्येक पर दोनों नियंत्रणों को अक्षम कर रहा हूं जब तक कि वर्तमान पंक्ति पर EditText का मान नहीं होता है।

इस वरीयता क्रम में मुझे दो में से एक काम करने की आवश्यकता है:

  1. जब एक बटन पर क्लिक किया जाता है, तो फ़ोकस को अलग बटन पर सेट किए बिना तुरंत फोकस हटा दें
  2. गतिविधि शुरू होने पर पहले बटन पर ध्यान केंद्रित करें

उप-गतिविधि रिटर्न के बाद समस्या प्रकट होती है; जो बटन क्लिक किया गया था, वह फोकस बनाए रखता है।

पुन :: # 1 ऊपर - वहाँ एक removeFocus()विधि, या कुछ इसी तरह प्रतीत नहीं होता है

पुन: # 2 ऊपर - मैं requestFocus()अगली पंक्ति पर बटन पर ध्यान केंद्रित करने के लिए सेट करने के लिए उपयोग कर सकता हूं , और यह सब-एक्टिविटी रिटर्न के बाद काम करता है, लेकिन किसी कारण से यह पैरेंट गतिविधि में काम नहीं करता है onCreate()

मुझे किसी भी दिशा में यूआई स्थिरता की आवश्यकता है - या तो कोई बटन उप-गतिविधि समाप्त होने के बाद फोकस नहीं करता है या प्रत्येक बटन किसी भी चयन से पहले बहुत पहले (और केवल) सक्रिय बटन सहित तर्क प्रवाह में अपनी जगह पर ध्यान केंद्रित करता है।

जवाबों:


173

ClearFocus () का उपयोग करना मेरे लिए काम नहीं कर रहा था जैसा कि आपने पाया (किसी अन्य उत्तर में टिप्पणियों में देखा), लेकिन अंत में मेरे लिए जो काम कर रहा था वह जोड़ रहा था:

<LinearLayout 
    android:id="@+id/my_layout" 
    android:focusable="true" 
    android:focusableInTouchMode="true" ...>

मेरे बहुत ही शीर्ष स्तर के लेआउट दृश्य (एक रैखिक लेआउट) के लिए। सभी बटन / EditTexts आदि से ध्यान हटाने के लिए, आप तब बस कर सकते हैं

LinearLayout myLayout = (LinearLayout) activity.findViewById(R.id.my_layout);
myLayout.requestFocus();

जब तक मैंने ध्यान केंद्रित करने के लिए दृश्य सेट नहीं किया, तब तक ध्यान केंद्रित करने का अनुरोध करने से कुछ नहीं हुआ।


क्षणभंगुर क्षण के लिए मुझे लगा कि यह काम कर सकता है। "अपनी सादगी में कितना सुंदर!" मैंने स्वयं से कहा। हाय, ऐसा नहीं होना था। यहां तक ​​कि जब मैं requestFocus () को हटाता हूं तो अगली पंक्ति के बटन पर ध्यान केंद्रित हो जाता है। यह दूसरी प्राथमिकता के रूप में ठीक होगा, लेकिन केवल तभी जब मैं किसी तरह ऑनक्रीट () में पहले बटन पर ध्यान केंद्रित कर सकता हूं।
इंटेक्सएक्सएक्स

@InteXX: मैं आज फिर से इस समस्या के सामने आया और एक समाधान पाया। मुझे पता है कि आप अब एक अलग मार्ग से नीचे चले गए हैं, लेकिन इसे कभी भी अपने आप को एक ही नाव में खोजने की कोशिश करें!
एक्शनश्रीम

"मुझे पता है कि आप अब एक अलग मार्ग से नीचे चले गए हैं" यह अभी भी बहुत देर तक वापस नहीं आया है :-) मैं कोशिश करूँगा कि आपको पता चल जाए, धन्यवाद।
इंटेक्सएक्सएक्सएक्स

अरे। लगभग, लेकिन काफी नहीं। हां, यह अंतिम-क्लिक किए गए बटन पर ध्यान केंद्रित करता है, लेकिन फिर यह किसी भी बटन को फोकस प्राप्त करने से रोकता है। इसका मतलब यह होगा कि मेरे गैर-स्पर्श उपयोगकर्ता एक बटन पर क्लिक नहीं कर पाएंगे। क्या आपके लिए भी ऐसा ही हो रहा है?
InteXX

6
यह स्क्रॉल दृश्य पर काम नहीं करेगा। यदि आपका शीर्ष दृश्य स्क्रॉलव्यू है, तो इसका उपयोग उसके बच्चे पर करें।
यूरोक पॉडक्रिकनिक

79

पुराना सवाल है, लेकिन मैं इसे भर में आया था जब मेरे पास एक समान मुद्दा था और मैंने सोचा था कि मैं जो कर रहा हूं उसे साझा करूंगा।

ध्यान केंद्रित करने वाला दृश्य हर बार अलग होता था इसलिए मैंने बहुत सामान्य इस्तेमाल किया:

View current = getCurrentFocus();
if (current != null) current.clearFocus();

12
ऐसा करने का सुरुचिपूर्ण तरीका। क्लियरफोकस () कॉल करने से पहले getCurrentFocus () से वैल्यू को चेक करने के लिए कोई व्यक्ति चाहता हो सकता है
Vering

4
+1 हाँ, आपको उस अशक्त जाँच में फेंकना होगा! - जावा केवल एक सुरक्षित-ट्रैवर्सल-ऑपरेटर क्यों लागू नहीं कर सकता है? यह उतना ही सरल होगा getCurrentFocus()?.clearFocus();, जितना अच्छा और सुरुचिपूर्ण: - /
लेविते

1
@willlma: हाँ, यह वही था जो मेरा मतलब था।
Vering

5
@Levit बहुत स्विफ्ट की तरह। :-) लेकिन अगर जावा ने इस तरह के ऑपरेटर को लागू किया है, तब भी इसे पकड़ने में Android 4 साल लगेंगे।
ग्रेग ब्राउन

2
@ लव, आपने शायद इसे अब तक ढूंढ लिया है, लेकिन कोटलिन।
19

9
  1. आप उपयोग कर सकते हैं View.clearFocus()

  2. उपयोग View.requestFocus()से कहा जाता है onResume()


@siliconeagle: अब यह बहुत बहुत अजीब है। (पॉइंटर टू क्लियरफोकस के लिए धन्यवाद () btw - मुझे इसकी जानकारी नहीं थी।) जब मैं पहला बटन क्लिक करता हूं, तो एक चयन करता हूं, और फिर वापस लौटता हूं, पहला बटन अब फोकस प्राप्त नहीं कर सकता है। मैं इस बटन के लिए अपने कोड में कहीं भी फ़ोकस करने योग्य नहीं हूं। मैं आपको अपना कोड दिखाना चाहता हूं, लेकिन इस संपादन विंडो में पर्याप्त वर्ण उपलब्ध नहीं हैं और SO के लिए नया होने के नाते मुझे यकीन नहीं है कि क्या मुझे कोड पोस्ट करने में सक्षम होने के लिए एक और उत्तर दर्ज करना चाहिए।
इंटेक्सएक्सएक्सएक्स

@siliconeagle: दुर्भाग्य से, क्लियरफोकस () काम नहीं करता है - उप-गतिविधि के वापस आने पर बटन फोकस बनाए रखते हैं।
इंटेक्सएक्सएक्स

@siliconeagle: ठीक है, उस पहली टिप्पणी के बारे में कभी भी दिमाग न लगाएं। मैं बटन के क्लिक इवेंट में setFocusable (झूठा) का उपयोग कर रहा था और उप-गतिविधि वापस आने के बाद इसे चालू करना भूल गया। clearFocus () का अभी भी कोई प्रभाव नहीं है - मुझे आश्चर्य है कि क्यों? मैं इसे onActivityResult () से सभी बटन पर कॉल कर रहा हूं, लेकिन क्लिक किया गया बटन अभी भी फोकस बनाए रखता है। अजीब।
इंटेक्सएक्सएक्स

@siliconeagle: @actionshrimp: मैंने सभी फ़ोकस-संबंधित कमांड और सेटिंग्स के साथ दूर करने का फैसला किया है। मेरा मूल इरादा विकलांग बटनों पर ध्यान केंद्रित करने से रोकना था, लेकिन अगर ऐसा है तो इसकी कीमत इसके लायक नहीं है। रिक्वेस्टफोकस (), क्लियरफोकस () या सेटफोकसबल () के साथ, कोई भी बटन सब-एक्टिविटी रिटर्न के बाद फोकस को बरकरार नहीं रखता है। यह दो घुनों से कम है - मुझे लगता है कि मुझे एक अक्षम बटन पर ध्यान केंद्रित करने में सक्षम होने के लिए उपयोगकर्ता के साथ रहना होगा।
इंटेक्सएक्सएक्स

विकलांग तत्वों फ़ोकस करने योग्य AFAIK ... उपयोग (गलत) setEnabled नहीं कर रहे हैं
siliconeagle

8

android:descendantFocusability="beforeDescendants"

नीचे दिए गए कुछ लेआउट विकल्पों के साथ गतिविधि में निम्नलिखित का उपयोग करना वांछित के रूप में काम करने लगा।

 getWindow().getDecorView().findViewById(android.R.id.content).clearFocus();

रूट दृश्य पर निम्नलिखित मापदंडों के संबंध में।

<?xml
    android:focusable="true"
    android:focusableInTouchMode="true"
    android:descendantFocusability="beforeDescendants" />

https://developer.android.com/reference/android/view/ViewGroup#attr_android:descendantFocusability

उत्तर के लिए धन्यवाद: https://forums.xamarin.com/discussion/1856/how-to-disable-auto-focus-on-edit-text

WindowSoftInputMode के बारे में

ध्यान देने के लिए विवाद का एक और बिंदु है। डिफ़ॉल्ट रूप से, Android स्वचालित रूप से आपकी गतिविधि में पहले EditText या फ़ोकस करने योग्य नियंत्रण पर प्रारंभिक ध्यान केंद्रित करेगा। यह स्वाभाविक रूप से इस प्रकार है कि InputMethod (आमतौर पर सॉफ्ट कीबोर्ड) फोकस इवेंट को स्वयं दिखा कर जवाब देगा। AndroidManifest.xml में windowSoftInputMode विशेषता, जब StateAlwaysHidden पर सेट किया जाता है, तो यह स्वचालित रूप से असाइन किए गए प्रारंभिक फ़ोकस को अनदेखा करने के लिए कीबोर्ड को निर्देश देता है।

<activity
    android:name=".MyActivity"
    android:windowSoftInputMode="stateAlwaysHidden"/>

महान संदर्भ


6
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:app="http://schemas.android.com/apk/res-auto"
          android:id="@+id/ll_root_view"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:orientation="vertical">

LinearLayout llRootView = findViewBindId(R.id.ll_root_view);
llRootView.clearFocus();

मैं इसका उपयोग तब करता हूं जब पहले से ही अद्यतन प्रोफ़ाइल जानकारी समाप्त हो जाती है और अपने लेआउट में EditText से सभी ध्यान हटाते हैं

====> अद्यतन: मूल लेआउट सामग्री में मेरा EditText ऐड लाइन:

android:focusableInTouchMode="true"

3

के बारे में क्या सिर्फ android:windowSoftInputMode="stateHidden"अपनी गतिविधि को जोड़ने में प्रकट होता है।

इस पर टिप्पणी करने वाले एक स्मार्ट आदमी से लिया गया: https://stackoverflow.com/a/2059394/956975


2

सबसे पहले, यह 100% काम करेगा ........

  1. onResume()विधि बनाएँ ।
  2. इसके अंदर onResume()वह दृश्य खोजें जो बार-बार ध्यान केंद्रित कर रहा है findViewById()
  3. इस दृश्य के अंदर onResume()सेट requestFocus()करें।
  4. इस दृश्य के अंदर onResume()सेट clearFocusकरें।
  5. उसी लेआउट के xml में जाएं और उस शीर्ष दृश्य को ढूंढें जिसे आप केंद्रित करना चाहते हैं और focusableसही और focusableInTuchवास्तविक सेट करते हैं ।
  6. इसके अंदर onResume()उपरोक्त शीर्ष दृश्य को खोजेंfindViewById
  7. इस दृश्य के अंदर इस दृश्य को अंतिम पर onResume()सेट requestFocus()करें।
  8. और अब आनंद लें ......

2

मैंने देखने के लिए ध्यान केंद्रित को अक्षम करने और सक्षम करने की कोशिश की और इसने मेरे लिए काम किया (फोकस रीसेट था):

focusedView.setFocusable(false);
focusedView.setFocusableInTouchMode(false);
focusedView.setFocusable(true);
focusedView.setFocusableInTouchMode(true);

1

आप अपने राज्य को बचाने के लिए मुख्य गतिविधि की क्षमता को बंद करने की कोशिश कर सकते हैं (इस प्रकार यह भूल जाते हैं कि नियंत्रण में क्या पाठ था और क्या ध्यान केंद्रित था)। आपको यह याद रखने की आवश्यकता होगी कि आपके EditText के पास क्या है और उन्हें फिर से चालू करने के लिए कुछ और तरीका है। StartActivityForResult () के साथ अपनी उप-गतिविधियाँ लॉन्च करें और अपनी मुख्य गतिविधि में एक onActivityResult () हैंडलर बनाएँ जो EditText के सही रूप से अद्यतन करेगा। इस तरह से आप उचित बटन सेट कर सकते हैं जिस पर आप ध्यान केंद्रित करना चाहते हैं (उसी समय जब आप एक MyButton.post (नए Runnable) () {रन () {myButton .requestFocus ()}} का उपयोग करके EditText को फिर से खोलते हैं;

View.post () विधि प्रारंभ में फ़ोकस सेट करने के लिए उपयोगी है क्योंकि विंडो के बनने के बाद रननीय को निष्पादित किया जाएगा और चीजें बस जाती हैं, फ़ोकस तंत्र को उस समय तक ठीक से काम करने की अनुमति देता है। OnCreate / Start / Resume () के दौरान फ़ोकस सेट करने का प्रयास आमतौर पर समस्याएँ हैं, मैंने पाया है।

कृपया ध्यान दें कि यह छद्म कोड और गैर-परीक्षण है, लेकिन यह एक संभव दिशा है जिसे आप आज़मा सकते हैं।


दूसरे विचार पर ... गतिविधि की सहेजी स्थिति को बंद करने के बजाय पहले View.post () सामान का उपयोग करने का प्रयास करें। हो सकता है कि यह सब आप ही के लिए हो।
चाचा कोड बंदर

काश मैं अब हमारे लिए यह परीक्षण करने का एक आसान तरीका नहीं है। मैंने तब से देशी कोड मॉडल को छोड़ने और मोबाइल एप्लिकेशन के लिए HTML5 / CSS3 के साथ जाने का फैसला किया है, और इस तरह से मेरे सिस्टम को फिर से चुना है। लेकिन जो बहुत गहराई से जवाब देने के लिए प्रतीत होता है उसके लिए धन्यवाद। मैंने इसे वोट दिया।
InteXX

1
android:focusableInTouchMode="true"
android:focusable="true"
android:clickable="true"

उन्हें अपने ViewGroup में शामिल करें जिसमें आपका EditTextView शामिल है। यह मेरे बाधा लेआउट के लिए ठीक से काम करता है। उममीद है कि इससे मदद मिलेगी


0

निम्नलिखित का प्रयास करें (बुला clearAllEditTextFocuses();)

private final boolean clearAllEditTextFocuses() {
    View v = getCurrentFocus();
    if(v instanceof EditText) {
        final FocusedEditTextItems list = new FocusedEditTextItems();
        list.addAndClearFocus((EditText) v);

        //Focus von allen EditTexten entfernen
        boolean repeat = true;
        do {
            v = getCurrentFocus();
            if(v instanceof EditText) {
                if(list.containsView(v))
                    repeat = false;
                else list.addAndClearFocus((EditText) v);
            } else repeat = false;
        } while(repeat);

        final boolean result = !(v instanceof EditText);
        //Focus wieder setzen
        list.reset();
        return result;
    } else return false;
}

private final static class FocusedEditTextItem {

    private final boolean focusable;

    private final boolean focusableInTouchMode;

    @NonNull
    private final EditText editText;

    private FocusedEditTextItem(final @NonNull EditText v) {
        editText = v;
        focusable = v.isFocusable();
        focusableInTouchMode = v.isFocusableInTouchMode();
    }

    private final void clearFocus() {
        if(focusable)
            editText.setFocusable(false);
        if(focusableInTouchMode)
            editText.setFocusableInTouchMode(false);
        editText.clearFocus();
    }

    private final void reset() {
        if(focusable)
            editText.setFocusable(true);
        if(focusableInTouchMode)
            editText.setFocusableInTouchMode(true);
    }

}

private final static class FocusedEditTextItems extends ArrayList<FocusedEditTextItem> {

    private final void addAndClearFocus(final @NonNull EditText v) {
        final FocusedEditTextItem item = new FocusedEditTextItem(v);
        add(item);
        item.clearFocus();
    }

    private final boolean containsView(final @NonNull View v) {
        boolean result = false;
        for(FocusedEditTextItem item: this) {
            if(item.editText == v) {
                result = true;
                break;
            }
        }
        return result;
    }

    private final void reset() {
        for(FocusedEditTextItem item: this)
            item.reset();
    }

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