Odağı başka bir kontrole ayarlamadan odak nasıl kaldırılır?


98

Kullanıcı arayüzlerimin sezgisel olmasını seviyorum; her bir ekran, kullanıcıyı uygulamadaki bir sonraki adıma doğal ve dikkat çekmeden yönlendirmelidir. Bunun dışında işleri olabildiğince kafa karıştırıcı ve kafa karıştırıcı hale getirmeye çalışıyorum.

Şaka yapıyorum :-)

TableRowHer biri salt okunur ve odaklanılamayan bir EditText denetimi ve ardından sağında bir düğme içeren üç tane s var . Her düğme aynı aktiviteyi ancak farklı bir argümanla başlatır. Kullanıcı orada bir seçim yapar ve alt aktivite EditText, kullanıcının seçimiyle uygun olanı doldurarak biter .

Klasik basamaklı değerler mekanizmasıdır; her seçim, bir sonraki seçim vb. için mevcut seçenekleri daraltır. Bu nedenle, geçerli satırdaki Metni Düzenle bir değer içerene kadar sonraki satırların her birinde her iki kontrolü de devre dışı bırakıyorum.

Bu tercih sırasına göre iki şeyden birini yapmam gerekiyor:

  1. Bir düğmeye tıklandığında, odağı farklı bir düğmeye ayarlamadan hemen odağı kaldırın
  2. Aktivite başladığında odağı ilk düğmeye ayarlayın

Alt aktivite geri döndükten sonra problem kendini gösterir; tıklanan düğme odağı korur.

Re: # 1 yukarıda - Bir removeFocus()yöntem veya benzeri bir şey görünmüyor

Yukarıdaki Re: # 2 - requestFocus()Odağı bir sonraki satırdaki düğmeye ayarlamak için kullanabilirim ve bu, alt aktivite döndükten sonra çalışır, ancak bazı nedenlerden dolayı ana aktivitede çalışmaz onCreate().

Her iki yönde de UI tutarlılığına ihtiyacım var - ya alt etkinlik bittikten sonra hiçbir düğme odaklanmaz ya da herhangi bir seçimden önceki ilk (ve yalnızca) etkin düğme dahil olmak üzere, mantık akışındaki yerine bağlı olarak her düğme odak alır.

Yanıtlar:


178

Bulduğunuz gibi clearFocus () kullanmak benim için de işe yaramıyor gibi görünmüyordu (başka bir cevaba yapılan yorumlarda görüldü), ama sonunda benim için işe yarayan şey eklemek oldu:

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

en üst düzey Düzen Görünümüme (doğrusal bir düzen). Odağı tüm Buttons / EditTexts vb. Öğelerinden kaldırmak için,

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

Görünümü odaklanabilir olarak ayarlamadıkça odak istemek hiçbir şey yapmadı.


Kısa bir an için bunun işe yarayacağını düşündüm. "Sadeliği ne kadar güzel!" Dedim kendi kendime. Ne yazık ki, olmayacaktı. RequestFocus () işlevini kaldırdığımda bile sonraki satırın düğmesi odaklanıyor. Bu, ikinci bir tercih olarak tamam olabilir, ancak yalnızca onCreate () içindeki ilk düğmeye bir şekilde odak ayarlayabilirsem.
InteXX

@InteXX: Bu problemle bugün tekrar karşılaştım ve bir çözüm buldum. Şu anda farklı bir rotaya girdiğinizi biliyorum, ancak kendinizi bir daha aynı gemide bulursanız bunu bir deneyin!
actionshrimp

"Şimdi farklı bir rotadan geçtiğini biliyorum" Yedeklemek için hala çok geç değil :-) Bunu deneyip size bildireceğim, teşekkürler.
InteXX

Lanet olsun. Neredeyse, ama tam olarak değil. Evet, odağı son tıklanan düğmeden uzaklaştırır, ancak aynı zamanda HERHANGİ bir düğmenin odak kazanmasını da engeller. Bu, dokunmatik olmayan kullanıcılarımın bir düğmeyi tıklayamayacağı anlamına gelir. Senin için aynısını mı yapıyor?
InteXX

6
Bu ScrollView'da çalışmayacaktır. En iyi görünümünüz ScrollView ise, bunu alt görünümünde kullanın.
Uroš Podkrižnik

81

Eski soru, ama benzer bir sorunla karşılaştığımda karşılaştım ve yaptığım şeyi paylaşacağımı düşündüm.

Odaklanılan görüş her seferinde farklıydı, bu yüzden çok genel olanı kullandım:

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

12
Bunu yapmanın zarif yolu. ClearFocus () 'u çağırmadan önce getCurrentFocus ()' dan bir değerin null olup olmadığını kontrol etmek isteyebilirsiniz
2013 tarihinde

4
+1 Evet, o boş çeki atmanız gerekecek! - Java neden güvenli geçiş operatörü uygulayamıyor? O kadar basit getCurrentFocus()?.clearFocus();, çok hoş ve zarif olurdu : - /
Levite

1
@willlma: Evet, tam olarak kastettiğim buydu.
2014

5
@Levit Çok Swift-like. :-) Ancak Java böyle bir operatörü uygulamış olsa bile, Android'in yetişmesi 4 yılını alacaktır.
Greg Brown

2
@Levit, muhtemelen şimdiye kadar bulmuşsunuzdur, ama Kotlin.
prodaea

9
  1. Kullanabilirsiniz View.clearFocus().

  2. Adlı View.requestFocus()kişiyi kullanın onResume().


@silikonagle: Şimdi bu çok ÇOK garip. (ClearFocus () btw'yi sağlayan işaretçi için teşekkürler - bunun farkında değildim.) İlk düğmeye tıkladığımda, bir seçim yaptığımda ve sonra geri döndüğümde, ilk düğme artık odak alamıyor. Kodumun hiçbir yerinde bu düğme için odaklanabilir ayarlamıyorum. Size kodumu göstermek isterim, ancak bu düzenleme penceresinde yeterince karakter yok ve SO'da yeni olduğum için sadece kod yazabilmek için başka bir cevap girmem gerekip gerekmediğinden emin değilim.
InteXX

@silikonagle: Ne yazık ki, clearFocus () çalışmıyor - düğmeler, alt etkinlik geri döndüğünde odağı koruyor.
InteXX

@silikonagle: Tamam, bu ilk yorumu boşverin. Düğmenin tıklama olayında setFocusable (false) kullanıyordum ve alt etkinlik döndükten sonra tekrar açmayı unutuyordum. clearFocus () hala bir etkiye sahip değil - nedenini merak ediyorum? OnActivityResult () 'dan tüm düğmelerde çağırıyorum, ancak tıklanan düğme hala odağı koruyor. Garip.
InteXX

@silikonagle: @actionshrimp: Odaklanmayla ilgili tüm komutları ve ayarları kaldırmaya karar verdim. Asıl amacım, devre dışı bırakılmış düğmelere odaklanmayı önlemekti, ancak maliyeti buysa buna değmez. RequestFocus (), clearFocus () veya setFocusable () olmadan, alt aktivite döndükten sonra hiçbir düğme odağı korumaz. İki böcekten daha azı - sanırım kullanıcının odağı devre dışı bırakılmış bir düğmeye ayarlayabilmesi ile yaşamak zorunda kalacağım.
InteXX

engelli öğeler odaklanabilir değil AFAIK ... setEnabled (false) kullanın
siliconeagle

9

android:descendantFocusability="beforeDescendants"

Aşağıdaki bazı düzen seçenekleriyle aşağıdaki aktivitede aşağıdakileri kullanmak istendiği gibi işe yaradı.

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

kök görünümde aşağıdaki parametrelerle bağlantılı olarak.

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

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

Teşekkürler: https://forums.xamarin.com/discussion/1856/how-to-disable-auto-focus-on-edit-text

WindowSoftInputMode hakkında

Dikkat edilmesi gereken başka bir çekişme noktası daha var. Varsayılan olarak, Android otomatik olarak ilk odağı Etkinliğinizdeki ilk EditText veya odaklanabilir kontrole atar. Doğal olarak, InputMethod'un (tipik olarak yazılım klavyesi) odak olayına kendini göstererek yanıt vereceği sonucu çıkar. AndroidManifest.xml'deki windowSoftInputMode özniteliği, stateAlwaysHidden olarak ayarlandığında, klavyeye bu otomatik olarak atanan ilk odağı yoksayması talimatını verir.

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

harika referans


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

Profil bilgilerini güncellemeyi bitirdiğimde bunu kullanıyorum ve tüm odağı düzenimdeki EditText'ten kaldırıyorum

====> Güncelle: Üst düzen içeriğinde EditText satırım ekle:

android:focusableInTouchMode="true"


3

Görünüm için odaklanabilirliği devre dışı bırakmaya ve etkinleştirmeye çalıştım ve benim için çalıştı (odak sıfırlandı):

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

2

Her şeyden önce,% 100 çalışacak ........

  1. onResume()Yöntem oluşturun .
  2. Bunun içinde onResume()tekrar tekrar odaklanan manzarayı bulun findViewById().
  3. Bu onResume()setin requestFocus()içinde bu görünüm.
  4. Bu onResume()setin clearFocusiçinde bu görünüm.
  5. Aynı düzende xml'ye gidin ve odaklanmak ve focusabledoğru ve focusableInTuchdoğru olarak ayarlamak istediğiniz üst görünümü bulun .
  6. Bunun içinde onResume()yukarıdaki üstten görünümü bulun.findViewById
  7. Bu onResume()setin içinde requestFocus()en sonunda bu görünüm.
  8. Ve şimdi keyfini çıkarın ......

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

Bunları EditTextView'unuzu içeren ViewGroup'unuza ekleyin. Kısıtlama Düzenime uygun şekilde çalışıyor. Umarım bu yardım eder


1

Ana Aktivitenin durumunu kaydetme yeteneğini kapatmayı deneyebilirsiniz (böylece hangi kontrolün metne sahip olduğunu ve neyin odaklandığını unutmasını sağlar). EditText'inizin neye sahip olduğunu hatırlamanın ve onlarıResume () üzerinde yeniden doldurmanın başka bir yoluna ihtiyacınız olacak. StartActivityForResult () ile alt Aktivitelerinizi başlatın ve ana Aktivitenizde EditText'i doğru şekilde güncelleyecek bir onActivityResult () işleyicisi oluşturun. Bu şekilde, bir myButton.post (new Runnable () {run () {myButton.requestFocus ();}}) kullanarak EditText'leri yeniden doldurduğunuzda, Resume () 'ye odaklanmak istediğiniz uygun düğmeyi ayarlayabilirsiniz;

View.post () yöntemi, başlangıçta odağı ayarlamak için kullanışlıdır, çünkü bu çalıştırılabilir pencere oluşturulduktan ve işler düzeldikten sonra çalıştırılacak ve odak mekanizmasının o zamana kadar düzgün çalışmasına izin verecektir. OnCreate / Start / Resume () sırasında odağı ayarlamaya çalışmanın genellikle sorunları olduğunu buldum.

Lütfen bunun sözde kod olduğunu ve test edilmediğini, ancak deneyebileceğiniz olası bir yön olduğunu unutmayın.


İkinci düşüncede ... Aktivitenin kaydedilmiş durumunu kapatmak yerine önce View.post () maddesini kullanmayı deneyin. Bu sizin için tek başına hile yapabilir.
Amca Kodu Maymun

Ne yazık ki, bunu bizim için test etmenin artık kolay bir yolu yok. O zamandan beri yerel kod modelini terk etmeye ve mobil uygulamalar için HTML5 / CSS3 kullanmaya karar verdim ve bu nedenle sistemimi buna göre yeniden düzenledim. Ancak çok derinlemesine bir cevap gibi görünen şey için teşekkür ederim. Ben oyladım.
InteXX

0

Aşağıdakini deneyin (arayarak 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();
    }

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