it-swarm.dev

Yumuşak klavye göründüğünde, EditText alanımın odağını kaybetmesine neden oluyor

ListView'de birkaç EditText alanı var. EditText alanlarından birine dokunduğumda, klavye görünüşte kayar (olması gerektiği gibi), ancak dokunduğum EditText alanı odağı kaybediyor. Klavyeyi görünümde başlatmak için (sorunu gerçekten çözmek yerine sorunu çözmek için) çeşitli InputMethodManager yöntemlerini kullanmayı denedim, ancak bu işe yaramadı - klavye, Etkinlik göründüğünde görünmüyordu.

EditText'in türü number'dır ve klavye içeri girdiğinde, bir sayı klavyesidir, ancak kaydırmayı bitirdiğinde ve EditText odağını kaybettiğinde, alfabetik klavyeye dönüşür (bu, EditText'in artık odağı olmadığı fikrini pekiştirir) .

Sorum şu:

1) EditText alanımın seçimini ve ardından yazılım klavyesinde notu sonrasında kaydırmayı nasıl yapabilirim, EditText'imin odağını kaybetmesine neden olabilirim?

... başarısızlık ... 

2) Klavyeyi görünüşte nasıl başlatmasını sağlayabilirim ki asla içeri girmemesi gerekir (bu yüzden sakıncalı bulduğum davranışlardan kaçınır)?

Bildirimim Android:windowSoftInputMode="stateAlwaysVisible" içeriyor, ancak bir EditText öğesine dokunana kadar klavye görünmüyor. 'StateAlwaysVisible' özniteliğinin bu yoksayılması yalnızca emülatörde gerçekleşiyor gibi görünüyor - sağlanan aygıtımda onurlandırılıyor, bu nedenle yukarıdaki 2 numaralı soru aygıtta çalışıyor ... emülatörde çalışmıyor. 

Sağlayabileceğiniz her türlü yardım için teşekkürler!

50
Kyle Humfeld

İşte nasıl yaptım. İçine metin yazmak için EditText öğesine dokunduğunuzda onFocusChangeListener() birkaç kez çağrılır. Sıra:

  1. Odak farklı bir görünümdeydi, o zaman odağı kaybeder.
  2. Hedef odak kazanıyor
  3. Yumuşak klavye açılır.
  4. Bu hedefin odak kaybetmesine neden olur
  5. Kod bu durumu tespit eder ve target.requestFocus () öğesini çağırır.
  6. En soldaki, en üstteki görüntü Android saçmalığından dolayı odaklanıyor
  7. En soldaki görünüm, requestFocus'un çağrılmasından dolayı odağını kaybediyor
  8. Hedef sonunda odaklanmaya başladı

    //////////////////////////////////////////////////////////////////
    private final int minDelta = 300;           // threshold in ms
    private long focusTime = 0;                 // time of last touch
    private View focusTarget = null;
    
    View.OnFocusChangeListener onFocusChangeListener = new View.OnFocusChangeListener() {
        @Override
        public void onFocusChange(View view, boolean hasFocus) {
            long t = System.currentTimeMillis();
            long delta = t - focusTime;
            if (hasFocus) {     // gained focus
                if (delta > minDelta) {
                    focusTime = t;
                    focusTarget = view;
                }
            }
            else {              // lost focus
                if (delta <= minDelta  &&  view == focusTarget) {
                    focusTarget.post(new Runnable() {   // reset focus to target
                        public void run() {
                            focusTarget.requestFocus();
                        }
                    });
                }
            }
        }
    };
    

Yukarıdaki kod, klavye açılır pencereleri için iyi çalışır. Ancak, konuşma metni metne açılır penceresini algılamaz. 

13
SoloPilot

AndroidManifest.xml'nizde değişiklik yapmanız gerekiyor

Android ekleyin: windowSoftInputMode = "adjustPan" listview.

    <activity Android:name=".MyEditTextInListView"
              Android:label="@string/app_name"
              Android:windowSoftInputMode="adjustPan">

Saygılarımızla

118
Frank

Benim durumumda bu oluyor çünkü ListView yeniden boyutlandırıldığında tüm liste öğelerini yeniden yaratıyor (yani, her görünen liste öğesi için tekrar getView () çağırıyor).

EditText, getView () uygulamasından döndürdüğüm düzende olduğundan, bu daha önce odağı olandan farklı bir EditText örneği olduğu anlamına gelir. İkinci bir sonuç, yazılım klavyesi göründüğünde veya kaybolduğunda EditText'in içeriğini kaybettiğimi buldum.

Görüşümün tamamen erişilebilir kalmasını istediğimden (yani, klavye penceresinin arkasına gizlenmek yerine, bazı kısımlar erişilebilir değil) yeniden boyutlandırılmasını istiyorum, aksi takdirde en iyi yaklaşım gibi görünen Frank'in cevabını kullanamadım.

Bunu, odağın kaybolduğu zaman damgasını kaydetmek için EditText üzerinde bir OnFocusChangeListener kullanarak ve sonra liste öğesinin yeniden yaratılması sırasında, mevcut zaman odağın kaybolduğu andan itibaren bir eşik değerindeyse, requestFocus öğesini çağırın. ) söz konusu EditText’e geri vermek için.

Metni, aynı zamanda EditText'in önceki örneğinden alabilir ve yeni örneğe aktarabilirsiniz.

private class MyAdapter<Type> extends ArrayAdapter<String>
    implements OnFocusChangeListener
{
    private EditText mText;
    private long mTextLostFocusTimestamp;
    private LayoutInflater mLayoutInflater;

    public MyAdapter(Context context, int resource, int textResourceId, ArrayList<String> data, LayoutInflater li) {
        super(context, resource, textResourceId, data);
        mLayoutInflater = li;
        mTextLostFocusTimestamp = -1;
    }

    private void reclaimFocus(View v, long timestamp) {
        if (timestamp == -1)
            return;
        if ((System.currentTimeMillis() - timestamp) < 250)
            v.requestFocus();
    }

    @Override public View getView (int position, View convertView, ViewGroup parent)
    {
        View v = mLayoutInflater.inflate(R.layout.mylayout, parent, false);

        EditText newText = (EditText) v.findViewById(R.id.email);
        if (mText != null)
            newText.setText(mText.getText());
        mText = newText;
        mText.setOnFocusChangeListener(this);
        reclaimFocus(mText, mTextLostFocusTimestamp);

        return v;
    }

    @Override public void onFocusChange(View v, boolean hasFocus) {
        if ((v == mText) && !hasFocus)
            mTextLostFocusTimestamp = System.currentTimeMillis();
    }
}
9
sheltond

ListView içindeki editText ise, View özelliğini getView yöntemiyle bu şekilde şişirdiğinizden emin olun.


        if (convertView == null)
        convertView = LayoutInflater.from(context).inflate(R.layout.yourItemListLayout,
                parent, false);   

Düzenleme: Bu bazı cep telefonları için ben yukarıda Mr.Frank cevabını kullandığım tüm değil.

1
Samer Kador

AndroidManifest.xml dosyasında, görünümleri içeren aktivitedeki adjustNothing özelliğini kullanın

<activity
            Android:name=".ActivityName"
            Android:windowSoftInputMode="adjustNothing">
1

Bu kodu, her zaman görülebilir donanım klavyesi olan bir cihazda test etmelisiniz. Davranış burada da olabilir.

Bundan kaçınmak için klavyeyi her zaman görülebilir hale getirebilirsiniz .. ancak bu konuya göre görebileceğiniz kadar kolay değildir:

https://groups.google.com/forum/#!topic/Android-developers/FyENeEdmYC0

Teorik olarak burada açıklandığı şekilde kendi Android klavyenizi (stok Android klavyesini temel olarak kullanmanıza rağmen) oluşturmanız gerekebilir: Android: Tuş takımını her zaman görünür hale getirmek için nasıl?

1
neteinstein

Buraya Xamarin veya Xamarin ile gelenler için:

Ben de aynı sorunu yaşadım ama yalnızca Android 5.x ile - 8.1 dahil tüm yeni Sürümler iyi çalıştı.

Açıkçası sheltond şunu söyleyerek haklıydı:

Benim durumumda bu oluyor çünkü ListView yeniden boyutlandırıldığında tüm liste öğelerini yeniden yaratıyor (yani, her görünen liste öğesi için tekrar getView () çağırıyor).

Benim listview de yeniden boyutlandırıyordu ve hayır, Frank s windowSoftInputMode="adjustPan" ayarlamak için benim için bir seçenek değildi çünkü bu klavyenin listeyi kısmen ekrandan çıkardığı anlamına geliyor.

Saatlerce odak-hata ayıklama sonrasında tek yapmam gereken, Xamarin Forms ListView'ün hücre önbellekleme stratejisini ayarlamaktı:

Itibaren

CachingStrategy="RecycleElement"

Için

CachingStrategy="RetainElement"

Bu, hücrelerin yeniden oluşturulmasını durduracaktır. Ancak, bu büyük listeler için düşük performans ve yüksek bellek tüketimi ile sonuçlanabilir. Farkında olmak.

0
Waescher

Android ekle: windowSoftInputMode = "viewlist" veya "EditText" i tutan etkinlikte "adjustResize". Bu sorununu çözecektir.

<activity Android:name=".MainActivity"
        Android:windowSoftInputMode="adjustResize">
</activity>
0
Jibin Anto

Bu adam aynı problem ve dahası vardı. ListView yerine bir ScrollView ve LinearLayout kullanarak çözdü. 

0
Martin Stone

Benim durumumda, Klavye göründüğünde kök ScrollView'ümde root_scrollview.fullScroll(View.FOCUS_DOWN) ismini aradım. İle değiştirdim

login_scrollview.post(new Runnable() { 
    @Override
    public void run() {
        root_scrollview.scrollTo(0,root_container.bottom)
    }
});

root_container root_scrollview öğesinin hemen alt öğesidir. Bu benim için sorunu çözdü.

Not: Doğrudan arama root_scrollview.scrollTo(0,root_container.bottom) çalışmıyordu.

0
Ismail Shaikh