Android Ekran klavyesi görünür olduğunda Tam Ekran Modunda düzen nasıl ayarlanır


178

Yazılım klavyesi etkinken düzeni ayarlamak için çok araştırma yaptım ve başarıyla uyguladım, ancak android:theme="@android:style/Theme.NoTitleBar.Fullscreen"bildirim dosyasında etkinlik etiketimde bunu kullandığımda sorun geliyor .

Bunun için android:windowSoftInputMode="adjustPan|adjustResize|stateHidden"farklı seçeneklerle kullandım ama şansım yok.

Bundan sonra FullScreenprogramlı olarak uyguladım ve çalışmak için çeşitli düzenler denedim FullScreenama hepsi boşuna.

Bu bağlantıları referans aldım ve bu konuyla ilgili birçok gönderiye baktım:

http://android-developers.blogspot.com/2009/04/updating-applications-for-on-screen.html

http://davidwparker.com/2011/08/30/android-how-to-float-a-row-above-keyboard/

İşte xml kodu:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout android:id="@+id/masterContainerView"
    android:layout_width="fill_parent" android:layout_height="fill_parent"
    android:orientation="vertical" xmlns:android="http://schemas.android.com/apk/res/android"
    android:background="#ffffff">

    <ScrollView android:id="@+id/parentScrollView"
        android:layout_width="fill_parent" android:layout_height="wrap_content">

        <LinearLayout android:layout_width="fill_parent"
            android:layout_height="fill_parent" android:orientation="vertical">

            <TextView android:id="@+id/setup_txt" android:layout_width="wrap_content"
                android:layout_height="wrap_content" android:text="Setup - Step 1 of 3"
                android:textColor="@color/top_header_txt_color" android:textSize="20dp"
                android:padding="8dp" android:gravity="center_horizontal" />

            <TextView android:id="@+id/txt_header" android:layout_width="fill_parent"
                android:layout_height="40dp" android:text="AutoReply:"
                android:textColor="@color/top_header_txt_color" android:textSize="14dp"
                android:textStyle="bold" android:padding="10dp"
                android:layout_below="@+id/setup_txt" />

            <EditText android:id="@+id/edit_message"
                android:layout_width="fill_parent" android:layout_height="wrap_content"
                android:text="Some text here." android:textSize="16dp"
                android:textColor="@color/setting_editmsg_color" android:padding="10dp"
                android:minLines="5" android:maxLines="6" android:layout_below="@+id/txt_header"
                android:gravity="top" android:scrollbars="vertical"
                android:maxLength="132" />

            <ImageView android:id="@+id/image_bottom"
                android:layout_width="fill_parent" android:layout_height="wrap_content"
                android:layout_below="@+id/edit_message" />

        </LinearLayout>
    </ScrollView>

    <RelativeLayout android:id="@+id/scoringContainerView"
        android:layout_width="fill_parent" android:layout_height="50px"
        android:orientation="vertical" android:layout_alignParentBottom="true"
        android:background="#535254">

        <Button android:id="@+id/btn_save" android:layout_width="wrap_content"
            android:layout_height="wrap_content" android:layout_alignParentRight="true"
            android:layout_marginTop="7dp" android:layout_marginRight="15dp"
            android:layout_below="@+id/edit_message"
            android:text = "Save" />

        <Button android:id="@+id/btn_cancel" android:layout_width="wrap_content"
            android:layout_height="wrap_content" android:layout_marginTop="7dp"
            android:layout_marginRight="10dp" android:layout_below="@+id/edit_message"
            android:layout_toLeftOf="@+id/btn_save" android:text = "Cancel" />

    </RelativeLayout>
</RelativeLayout>

resim açıklamasını buraya girin

Yazılım klavyesi resme geldiğinde alttaki 2 düğmenin yukarı çıkmasını istiyorum.

resim açıklamasını buraya girin


1
ScrollView içinde ve EditText altında Düğmeler eklemeniz gerektiğini düşünüyorum.
Balaji Khadake

Zaten işe yaramayan birçok seçenek denedim ...
Vineet Shukla

1
ur düğmelerini bir framelayout'a koyun ve framelayout'un ağırlığını 1 olarak ayarlayın ve nihayet android:windowSoftInputMode="adjustPan"bana sadece bu çalışmayı söyleyin .. ..
Sherif elKhatib

@VineetShukla tam ekran ile herhangi bir çalışma buldunuz mu ??
Muhammed Babar

2
Kullanmamanız gerektiğine adjustResizeve adjustPanaynı zamanda android.view.WindowManager.LayoutParams#SOFT_INPUT_ADJUST_RESIZEjavadoc'dan dikkat edin: "Bu, {@link SOFT_INPUT_ADJUST_PAN} ile birleştirilemez"
Denis Kniazhev 19:14

Yanıtlar:


257

Yghm'ın geçici çözümüne dayanarak, sorunu tek satırlı olarak çözmemi sağlayan bir kolaylık sınıfı kodladım (elbette yeni sınıfı kaynak koduma ekledikten sonra). Tek astar:

     AndroidBug5497Workaround.assistActivity(this);

Ve uygulama sınıfı:


public class AndroidBug5497Workaround {

    // For more information, see https://issuetracker.google.com/issues/36911528
    // To use this class, simply invoke assistActivity() on an Activity that already has its content view set.

    public static void assistActivity (Activity activity) {
        new AndroidBug5497Workaround(activity);
    }

    private View mChildOfContent;
    private int usableHeightPrevious;
    private FrameLayout.LayoutParams frameLayoutParams;

    private AndroidBug5497Workaround(Activity activity) {
        FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content);
        mChildOfContent = content.getChildAt(0);
        mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            public void onGlobalLayout() {
                possiblyResizeChildOfContent();
            }
        });
        frameLayoutParams = (FrameLayout.LayoutParams) mChildOfContent.getLayoutParams();
    }

    private void possiblyResizeChildOfContent() {
        int usableHeightNow = computeUsableHeight();
        if (usableHeightNow != usableHeightPrevious) {
            int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight();
            int heightDifference = usableHeightSansKeyboard - usableHeightNow;
            if (heightDifference > (usableHeightSansKeyboard/4)) {
                // keyboard probably just became visible
                frameLayoutParams.height = usableHeightSansKeyboard - heightDifference;
            } else {
                // keyboard probably just became hidden
                frameLayoutParams.height = usableHeightSansKeyboard;
            }
            mChildOfContent.requestLayout();
            usableHeightPrevious = usableHeightNow;
        }
    }

    private int computeUsableHeight() {
        Rect r = new Rect();
        mChildOfContent.getWindowVisibleDisplayFrame(r);
        return (r.bottom - r.top);
    }
}

Umarım bu birine yardımcı olur.


8
Teşekkürler! Hiçbir fikrim neden yok, ama yerine zorunda return (r.bottom - r.top); olan return r.bottom, aksi takdirde etkinlik görünümü durum çubuğunun boyutuna göre çok yüksek itilmiş olur, benim HTC One Mini'de işe alır. Yine de başka bir cihazda test etmedim. Umarım yardımcı olabilir.
Joan

4
Merhaba Joseph Johnson, kodunuzu kullandım ve mükemmel çalıştı. Ancak günümüzde bazı küçük cihazlarda klavye ve düzen arasındaki boşluğu (boş ekran) gösterdiği bir sorunla karşı karşıyayız. Bu konuda herhangi bir fikriniz var mı? Ayrıca dönüş r.bottom denedim.
Pankaj

2
Joseph Johnson: Metodunuzu uyguladım, üstteki düzenleme metnine tıkladığımızda iyi çalışıyor, ancak altta düzenleme metnine tıkladığımızda tüm tasarım yükseliyor
ranjith

3
Ne yazık ki Nexus 7 (2013) üzerinde çalışmıyor. AdjustNothing set ile bile hala tavalar.
Le-roy Staines

4
Müthiş cevap, çok teşekkür ederim. Bir Nexus 6 üzerinde çalışıyor ama kullanmak yerine frameLayoutParams.height = usableHeightSansKeyboard;kullanmak frameLayoutParams.height = usableHeightNow; zorunda değilim Bunu yapmazsam bazı öğeler ekranın dışına düşer.
RobertoAllende

37

Cevap çoktan seçildiğinden ve hata olduğu bilinen bir sorun olduğundan, "Olası Etrafta Çalışma" ekleyeceğimi düşündüm.

Yazılım klavyesi gösterildiğinde fullScreen moduna geçebilirsiniz. Bu, "adjustPan" öğesinin düzgün çalışmasını sağlar.

Başka bir deyişle, yine de uygulama temasının bir parçası olarak @android: style / Theme.Black.NoTitleBar.Fullscreen kullanıyorum ve etkinlik penceresi yumuşak giriş modunun bir parçası olarak stateVisible | adjustResize ama birlikte çalışabilmeleri için tam ekran moduna geçmeliyim klavye çıkmadan önce.

Aşağıdaki Kodu kullanın:

Tam ekran modunu kapat

getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);

Tam ekran modunu aç

getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);

Not - ilham kaynağı: Tam Ekran modunda Başlık Gizleme


1
Soruna zaman ayırdığınızı takdir ediyorum, bunun için +1. Bu yaklaşımı kesinlikle test edeceğim ve yakında benim için işe yarayıp yaramadığını size bildireceğim, teşekkürler.
Vineet Shukla

1
Şüpheli gibi çalışıyor! Gerçekten iyi bir çözüm! Yanımda +1.
Mike


1
klavye kapanıyor, klavye arka planı siyah oluyor.
Yapışma

vay teşekkürler ... AndroidBug5497Workaround tarafından belirtilen Geçici Çözüm'ü birleştirerek benim için gerçekten iyi çalışıyor ... Kombine kaynağı GitHub'a yükledim
CrandellWS

23

Bu çözümü Joseph Johnson'dan denedim , ama diğerleri gibi içerik ve klavye arasındaki boşlukla karşılaştım. Sorun, tam ekran modunu kullanırken yumuşak giriş modunun her zaman yatay kaydırılması nedeniyle oluşur . Bu kaydırma, yumuşak girdi tarafından gizlenecek bir girdi alanını etkinleştirdiğinizde Joseph'in çözümüne müdahale eder.

Yumuşak girdi göründüğünde, içerik önce orijinal yüksekliğine göre kaydırılır ve ardından Joseph'in çözümü tarafından istenen düzenle yeniden boyutlandırılır. Yeniden boyutlandırma ve sonraki düzen kaydırma işlemini geri almaz, bu da boşluğa neden olur. Etkinliklerin tam sırası:

  1. Global düzen dinleyici
  2. Yatay kaydırma
  3. İçerik düzeni (= içeriğin gerçek boyutlandırılması)

Yatay kaydırmayı devre dışı bırakmak mümkün değildir, ancak içeriğin yüksekliğini değiştirerek yatay kaydırma ofsetini 0 olmaya zorlamak mümkündür. Bu, dinleyicide yapılabilir, çünkü kaydırma gerçekleşmeden önce çalıştırılır. İçerik yüksekliğini kullanılabilir yüksekliğe ayarlamak, sorunsuz bir kullanıcı deneyimi sağlar, yani titremez.

Ben de bu değişiklikleri yaptım. Bunlardan herhangi biri sorun çıkarsa, bana bildirin:

  • Kullanılacak mevcut yüksekliğin anahtarlamalı belirlenmesi getWindowVisibleDisplayFrame. RectGereksiz çöp biraz önlemek için önbelleğe alınır.
  • Dinleyicinin de kaldırılmasına izin verin. Farklı tam ekran gereksinimlerine sahip farklı parçalar için bir etkinliği yeniden kullandığınızda faydalıdır.
  • Gösterilen veya gizlenen klavye arasında ayrım yapmayın, ancak içerik yüksekliğini her zaman görünür ekran çerçevesi yüksekliğine ayarlayın.

Bir Nexus 5 üzerinde test edilmiştir ve ekran boyutları küçükten büyüğe değişen 16-24 API seviyelerini çalıştıran emülatörler.

Kod Kotlin'e taşındı, ancak değişikliklerimi Java'ya geri taşımak basit. Yardıma ihtiyacınız olursa bana bildirin:

class AndroidBug5497Workaround constructor(activity: Activity) {
    private val contentContainer = activity.findViewById(android.R.id.content) as ViewGroup
    private val rootView = contentContainer.getChildAt(0)
    private val rootViewLayout = rootView.layoutParams as FrameLayout.LayoutParams
    private val viewTreeObserver = rootView.viewTreeObserver
    private val listener = ViewTreeObserver.OnGlobalLayoutListener { possiblyResizeChildOfContent() }

    private val contentAreaOfWindowBounds = Rect()
    private var usableHeightPrevious = 0

    // I call this in "onResume()" of my fragment
    fun addListener() {
        viewTreeObserver.addOnGlobalLayoutListener(listener)
    }

    // I call this in "onPause()" of my fragment
    fun removeListener() {
        viewTreeObserver.removeOnGlobalLayoutListener(listener)
    }

    private fun possiblyResizeChildOfContent() {
        contentContainer.getWindowVisibleDisplayFrame(contentAreaOfWindowBounds)
        val usableHeightNow = contentAreaOfWindowBounds.height()
        if (usableHeightNow != usableHeightPrevious) {
            rootViewLayout.height = usableHeightNow
            // Change the bounds of the root view to prevent gap between keyboard and content, and top of content positioned above top screen edge.
            rootView.layout(contentAreaOfWindowBounds.left, contentAreaOfWindowBounds.top, contentAreaOfWindowBounds.right, contentAreaOfWindowBounds.bottom)
            rootView.requestLayout()

            usableHeightPrevious = usableHeightNow
        }
    }
}

9
Bu en iyi cevap gibi görünüyor. Burada java taşıdık gist.github.com/grennis/2e3cd5f7a9238c59861015ce0a7c5584 . Not: Gözlemcinin hayatta olmadığı ve bunu da kontrol etmesi gerektiğine dair istisnalar alıyordum.
Greg Ennis

Aman Tanrım! o hayalet alanı arayan tüm sistem görünümleri hiyerarşisini geçiyordu. Bir yemek kamyonu için hendek bilgisayarlarına yakındım ama son dakikada cevabınızı gördüm. İşe yarıyor :)
16:18

1
@Greg Ennis Java bağlantı noktası için teşekkürler. Çok çaba ve zaman kazandırdı.
Ikun

@GregEnnis, teşekkürler, çözümünüz onResume (), onPause (), onDestroy () ile çalışır (GitHub kodundaki yorumlara bakın).
CoolMind

RemoveListener çağrısı çalışmıyor gibi görünüyor, ancak bu benim için çalışıyor. Hem possiblyResizeChildOfContentaramanın hem de aramanın içine kesme noktaları koydum removeListenerve removeListenerkesme noktasına çarptıktan sonra bile possiblyResizeChildOfContenthala çağrılıyor. Bu sorunu yaşayan başka var mı?
Quinn

14

Sistem kullanıcı arayüzü yaklaşımını ( https://developer.android.com/training/system-ui/immersive.html ) kullanıyorsanız basit ve güvenilir bir çözüm buldum .

Kullandığınız durumda View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN, örneğin kullanıyorsanız , çalışır CoordinatorLayout.

WindowManager.LayoutParams.FLAG_FULLSCREEN(Tema ile de ayarlayabileceğiniz) için işe yaramaz android:windowFullscreen, ancak SYSTEM_UI_FLAG_LAYOUT_STABLE( docs'a göre "aynı görsel etkiye sahiptir") ile benzer bir etki elde edebilirsiniz ve bu çözüm tekrar çalışmalıdır.

getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION /* If you want to hide navigation */
                    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE)

Marshmallow'u çalıştıran cihazımda test ettim.

Anahtar, yumuşak klavyelerin aynı zamanda sistem pencerelerinden (durum çubuğu ve gezinme çubuğu gibi) olmasıdır, bu nedenle WindowInsetssistem tarafından gönderilen doğru ve güvenilir bilgiler içerir.

DrawerLayoutDurum çubuğunun arkasına çizmeye çalıştığımız gibi kullanım durumunda , yalnızca üst iç metni yok sayan ve yazılım klavyesini oluşturan alt iç metni uygulayan bir düzen oluşturabiliriz.

İşte benim özel FrameLayout:

/**
 * Implements an effect similar to {@code android:fitsSystemWindows="true"} on Lollipop or higher,
 * except ignoring the top system window inset. {@code android:fitsSystemWindows="true"} does not
 * and should not be set on this layout.
 */
public class FitsSystemWindowsExceptTopFrameLayout extends FrameLayout {

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

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

    public FitsSystemWindowsExceptTopFrameLayout(Context context, AttributeSet attrs,
                                                 int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
    public FitsSystemWindowsExceptTopFrameLayout(Context context, AttributeSet attrs,
                                                 int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    @Override
    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            setPadding(insets.getSystemWindowInsetLeft(), 0, insets.getSystemWindowInsetRight(),
                    insets.getSystemWindowInsetBottom());
            return insets.replaceSystemWindowInsets(0, insets.getSystemWindowInsetTop(), 0, 0);
        } else {
            return super.onApplyWindowInsets(insets);
        }
    }
}

Ve kullanmak için:

<com.example.yourapplication.FitsSystemWindowsExceptTopFrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- Your original layout here -->
</com.example.yourapplication.FitsSystemWindowsExceptTopFrameLayout>

Bu, teorik olarak deli modifikasyonu olmayan herhangi bir cihaz için, rastgele 1/3veya 1/4ekran boyutunu referans olarak almaya çalışan herhangi bir saldırıdan çok daha iyi çalışmalıdır .

(API 16+ gerektirir, ancak durum çubuğunun arkasında çizim yapmak için yalnızca Lollipop + 'da tam ekran kullanıyorum, bu nedenle bu durumda en iyi çözüm.)


@Dilip Yukarıda belirtilen koşulların karşılanması koşuluyla API 16+ üzerinde çalışır.
Hai Zhang

10

Lütfen bir etkinlik için ayarlandığında android:windowSoftInputMode="adjustResize"çalışmaz WindowManager.LayoutParams.FLAG_FULLSCREEN. İki seçeneğiniz var.

  1. Etkinliğiniz için tam ekran modunu devre dışı bırakın. Etkinlik tam ekran modunda yeniden boyutlandırılmaz. Bunu xml'de (etkinliğin temasını değiştirerek) veya Java kodunda yapabilirsiniz. OnCreate () yönteminize aşağıdaki satırları ekleyin.

    getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);   
    getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);`

VEYA

  1. Tam ekran moduna geçmek için alternatif bir yol kullanın. Aşağıdaki kodu onCreate () yönteminize ekleyin.

    getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
    getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
    getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
    View decorView = getWindow().getDecorView();
    // Hide the status bar.
    int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN;
    decorView.setSystemUiVisibility(uiOptions);`

Yöntem 2'nin yalnızca Android 4.1 ve sonraki sürümlerinde çalıştığını lütfen unutmayın.


@AnshulTyagi yöntemi-2 yalnızca Android 4.1 ve sonraki sürümlerinde çalışır.
Abhinav Chauhan

4
Sırasıyla 5.0 ve 4.4.2, Nexus 9 ve Samsung s4 üzerinde test edildi, 2. yöntem çalışmıyor.
RobVoisey

1
2. yöntem sadece işe yaramaz ve üzerinde çok zaman harcadım.
Greg Ennis

Teşekkürler, günümü kurtar.
Deni Rohimat

9

Bu sorunla da yüzleşmek zorunda kaldım ve HTC One, galaxy s1, s2, s3, not ve HTC hissi üzerinde kontrol ettiğim bir işim vardı.

mizanpajınızın kök görünümüne global bir düzen dinleyicisi yerleştirme

mRootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener(){
            public void onGlobalLayout() {
                checkHeightDifference();
            }
    });

ve orada yükseklik farkını kontrol ettim ve ekranın yükseklik farkı ekran yüksekliğinin üçte birinden büyükse, klavyenin açık olduğunu varsayabiliriz. bu cevaptan aldı .

private void checkHeightDifference(){
    // get screen frame rectangle 
    Rect r = new Rect();
    mRootView.getWindowVisibleDisplayFrame(r);
    // get screen height
    int screenHeight = mRootView.getRootView().getHeight();
    // calculate the height difference
    int heightDifference = screenHeight - (r.bottom - r.top);

    // if height difference is different then the last height difference and
    // is bigger then a third of the screen we can assume the keyboard is open
    if (heightDifference > screenHeight/3 && heightDifference != mLastHeightDifferece) {
        // keyboard visiblevisible
        // get root view layout params
        FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mRootView.getLayoutParams();
        // set the root view height to screen height minus the height difference
        lp.height = screenHeight - heightDifference;
        // call request layout so the changes will take affect
        .requestLayout();
        // save the height difference so we will run this code only when a change occurs.
        mLastHeightDifferece = heightDifference;
    } else if (heightDifference != mLastHeightDifferece) {
        // keyboard hidden
        PFLog.d("[ChatroomActivity] checkHeightDifference keyboard hidden");
        // get root view layout params and reset all the changes we have made when the keyboard opened.
        FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mRootView.getLayoutParams();
        lp.height = screenHeight;
        // call request layout so the changes will take affect
        mRootView.requestLayout();
        // save the height difference so we will run this code only when a change occurs.
        mLastHeightDifferece = heightDifference;
    }
}

bu muhtemelen kurşun geçirmez değildir ve belki bazı cihazlarda çalışmaz, ancak benim için çalıştı ve umarım size de yardımcı olacaktır.


1
Bazı ayarlamalar gerekiyordu, ama işe yaradı. Nexus 7 2013'te klavye yüksekliğini (screenHeight / 3) bazı piksellerle azaltmak zorunda kaldım. Güzel fikir, teşekkürler!
Joao Sousa

7

Joseph Johnson çözümünü uyguladım ve iyi çalıştı, bu çözümü kullandıktan sonra bazen uygulamanın çekmecesinin düzgün kapanmayacağını fark ettim. Kullanıcı edittexts bulunan parçayı kapattığında dinleyici removeOnGlobalLayoutListener kaldırmak için bir işlevsellik ekledim.

    //when the application uses full screen theme and the keyboard is shown the content not scrollable! 
//with this util it will be scrollable once again
//http://stackoverflow.com/questions/7417123/android-how-to-adjust-layout-in-full-screen-mode-when-softkeyboard-is-visible
public class AndroidBug5497Workaround {


    private static AndroidBug5497Workaround mInstance = null;
    private View mChildOfContent;
    private int usableHeightPrevious;
    private FrameLayout.LayoutParams frameLayoutParams;
    private ViewTreeObserver.OnGlobalLayoutListener _globalListener;

    // For more information, see https://code.google.com/p/android/issues/detail?id=5497
    // To use this class, simply invoke assistActivity() on an Activity that already has its content view set.

    public static AndroidBug5497Workaround getInstance (Activity activity) {
        if(mInstance==null)
        {
            synchronized (AndroidBug5497Workaround.class)
            {
                mInstance = new AndroidBug5497Workaround(activity);
            }
        }
        return mInstance;
    }

    private AndroidBug5497Workaround(Activity activity) {
        FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content);
        mChildOfContent = content.getChildAt(0);
        frameLayoutParams = (FrameLayout.LayoutParams) mChildOfContent.getLayoutParams();

        _globalListener = new ViewTreeObserver.OnGlobalLayoutListener()
        {

            @Override
            public void onGlobalLayout()
            {
                 possiblyResizeChildOfContent();
            }
        };
    }

    public void setListener()
    {
         mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(_globalListener);
    }

    public void removeListener()
    {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            mChildOfContent.getViewTreeObserver().removeOnGlobalLayoutListener(_globalListener);
        } else {
            mChildOfContent.getViewTreeObserver().removeGlobalOnLayoutListener(_globalListener);
        }
    }

    private void possiblyResizeChildOfContent() {
        int usableHeightNow = computeUsableHeight();
        if (usableHeightNow != usableHeightPrevious) {
            int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight();
            int heightDifference = usableHeightSansKeyboard - usableHeightNow;
            if (heightDifference > (usableHeightSansKeyboard/4)) {
                // keyboard probably just became visible
                frameLayoutParams.height = usableHeightSansKeyboard - heightDifference;
            } else {
                // keyboard probably just became hidden
                frameLayoutParams.height = usableHeightSansKeyboard;
            }
            mChildOfContent.requestLayout();
            usableHeightPrevious = usableHeightNow;
        }
    }

    private int computeUsableHeight() {
        Rect r = new Rect();
        mChildOfContent.getWindowVisibleDisplayFrame(r);
        return (r.bottom - r.top);
    } 
}

benim edittexts'imin bulunduğu sınıfı kullanıyor

@Override
public void onStart()
{
    super.onStart();
    AndroidBug5497Workaround.getInstance(getActivity()).setListener();
}

@Override
public void onStop()
{
    super.onStop();
    AndroidBug5497Workaround.getInstance(getActivity()).removeListener();
}

7

Düzene ekleyin android:fitsSystemWindows="true", bu düzen yeniden boyutlandırılacaktır.


Bunu benim için çözen şey buydu. Buna ek olarak, doğru görünüme ayarladığınızdan emin olun. Durum çubuğunun altına gitmesi gereken bir arka planınız varsa, onu orada değil, içindeki bir düzende ayarlayın. Muhtemelen EditText görünümleri vb içindeki ikinci düzen içinde olmalıdır. Ayrıca bu konuşmayı da izleyin, çünkü işleri daha net hale getirir: youtube.com/watch?v=_mGDMVRO3iE
Stan

Benim için de çalıştı. @Stan yorum sayesinde, aynı zamanda aktivite / parça düzeni yerine ViewPager üzerine yerleştirerek FULLSCREEN tema ile çalışmasını başardı.
marcouberti

5

FullScreen ile çalışmasını sağlamak için:

İyonik klavye eklentisini kullanın. Bu, klavye göründüğünde ve kaybolduğunda dinlemenizi sağlar.

OnDeviceReady bu olay dinleyicilerini ekleyin:

// Allow Screen to Move Up when Keyboard is Present
window.addEventListener('native.keyboardshow', onKeyboardShow);
// Reset Screen after Keyboard hides
window.addEventListener('native.keyboardhide', onKeyboardHide);

Mantık:

function onKeyboardShow(e) {
    // Get Focused Element
    var thisElement = $(':focus');
    // Get input size
    var i = thisElement.height();
    // Get Window Height
    var h = $(window).height()
    // Get Keyboard Height
    var kH = e.keyboardHeight
    // Get Focused Element Top Offset
    var eH = thisElement.offset().top;
    // Top of Input should still be visible (30 = Fixed Header)
    var vS = h - kH;
    i = i > vS ? (vS - 30) : i;
    // Get Difference
    var diff = (vS - eH - i);
    if (diff < 0) {
        var parent = $('.myOuter-xs.myOuter-md');
        // Add Padding
        var marginTop = parseInt(parent.css('marginTop')) + diff - 25;
        parent.css('marginTop', marginTop + 'px');
    }
}

function onKeyboardHide(e) {
  // Remove All Style Attributes from Parent Div
  $('.myOuter-xs.myOuter-md').removeAttr('style');
}

Temel olarak fark eksi ise, bu, klavyenin girişinizi kapsadığı piksel miktarıdır. Yani ana div'inizi buna göre ayarlarsanız buna karşı koymalısınız.

Mantığa zaman aşımı eklenmesi, 300 ms'nin de performansı optimize etmesi gerektiğini söylüyor (çünkü bu, klavye süresinin görünmesine izin verecektir.


3

Joseph Johnson'ın sınıfını denedim ve işe yaradı, ama ihtiyaçlarımı tam olarak karşılamadı. Android taklit etmek yerine: windowSoftInputMode = "adjustResize", android taklit etmek gerekiyordu: windowSoftInputMode = "adjustPan".

Bunu tam ekran bir web görünümü için kullanıyorum. İçerik görünümünü doğru konuma kaydırmak için, odaklanılan ve böylece klavye girişini alan sayfa öğesinin konumu hakkında ayrıntılar sağlayan bir javascript arayüzü kullanmam gerekiyor. Bu ayrıntıları atladım, ancak Joseph Johnson'ın sınıfını yeniden yazdım. Yeniden boyutlandırmaya karşı özel bir tava uygulamanız için çok sağlam bir temel sağlayacaktır.

package some.package.name;

import some.package.name.JavaScriptObject;

import android.app.Activity;
import android.graphics.Rect;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.FrameLayout;

//-------------------------------------------------------
// ActivityPanner Class
//
// Convenience class to handle Activity attributes bug.
// Use this class instead of windowSoftInputMode="adjustPan".
//
// To implement, call enable() and pass a reference
// to an Activity which already has its content view set.
// Example:
//      setContentView( R.layout.someview );
//      ActivityPanner.enable( this );
//-------------------------------------------------------
//
// Notes:
//
// The standard method for handling screen panning
// when the virtual keyboard appears is to set an activity
// attribute in the manifest.
// Example:
// <activity
//      ...
//      android:windowSoftInputMode="adjustPan"
//      ... >
// Unfortunately, this is ignored when using the fullscreen attribute:
//      android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
//
//-------------------------------------------------------
public class ActivityPanner {

    private View contentView_;
    private int priorVisibleHeight_;

    public static void enable( Activity activity ) {
        new ActivityPanner( activity );
    }

    private ActivityPanner( Activity activity ) {
        FrameLayout content = (FrameLayout)
            activity.findViewById( android.R.id.content );
        contentView_ = content.getChildAt( 0 );
        contentView_.getViewTreeObserver().addOnGlobalLayoutListener(
            new ViewTreeObserver.OnGlobalLayoutListener() {
                public void onGlobalLayout() { panAsNeeded(); }
        });
    }

    private void panAsNeeded() {

        // Get current visible height
        int currentVisibleHeight = visibleHeight();

        // Determine if visible height changed
        if( currentVisibleHeight != priorVisibleHeight_ ) {

            // Determine if keyboard visiblity changed
            int screenHeight =
                contentView_.getRootView().getHeight();
            int coveredHeight =
                screenHeight - currentVisibleHeight;
            if( coveredHeight > (screenHeight/4) ) {
                // Keyboard probably just became visible

                // Get the current focus elements top & bottom
                // using a ratio to convert the values
                // to the native scale.
                float ratio = (float) screenHeight / viewPortHeight();
                int elTop = focusElementTop( ratio );
                int elBottom = focusElementBottom( ratio );

                // Determine the amount of the focus element covered
                // by the keyboard
                int elPixelsCovered = elBottom - currentVisibleHeight;

                // If any amount is covered
                if( elPixelsCovered > 0 ) {

                    // Pan by the amount of coverage
                    int panUpPixels = elPixelsCovered;

                    // Prevent panning so much the top of the element
                    // becomes hidden
                    panUpPixels = ( panUpPixels > elTop ?
                                    elTop : panUpPixels );

                    // Prevent panning more than the keyboard height
                    // (which produces an empty gap in the screen)
                    panUpPixels = ( panUpPixels > coveredHeight ?
                                    coveredHeight : panUpPixels );

                    // Pan up
                    contentView_.setY( -panUpPixels );
                }
            }
            else {
                // Keyboard probably just became hidden

                // Reset pan
                contentView_.setY( 0 );
            }

            // Save usabale height for the next comparison
            priorVisibleHeight_ = currentVisibleHeight;
        }
    }

    private int visibleHeight() {
        Rect r = new Rect();
        contentView_.getWindowVisibleDisplayFrame( r );
        return r.bottom - r.top;
    }

    // Customize this as needed...
    private int viewPortHeight() { return JavaScriptObject.viewPortHeight(); }
    private int focusElementTop( final float ratio ) {
        return (int) (ratio * JavaScriptObject.focusElementTop());
    }
    private int focusElementBottom( final float ratio ) {
        return (int) (ratio * JavaScriptObject.focusElementBottom());
    }

}

İhtiyacım olan şey gibi görünüyor, lütfen tam bir örnek ekleyebilir misiniz? işin için teşekkürler!
vilicvane

Bütün bir projeyi yayınlamak istemiyordum. Sağladığım, mükemmel çalışan bir çözüme doğru size çok uzun bir yol getirecek. Kendinizi tanımlamanız gerekenler: Bir "JavaScriptObject" sınıfı oluşturun ve bunu js arayüzü olarak web görünümünüze enjekte edin (Bunun için web görünümü belgelerine bakın). Kapsamlı bir şekilde bir web görünümü kullanan bir şey yazıyorsanız bunu zaten yapmış olmanız iyi bir olasılıktır. Odak olaylarını dinlemek ve odak öğesi konumlandırması hakkında JavaScriptObject sınıfınıza veri beslemek için web görünümüne JavaScript ekleyin.
BuvinJ

2

Aslında, yumuşak klavye görünümü , modda Activityne seçersem seçerim, hiçbir şekilde etkilenmez .windowSoftInputModeFullScreen

Bu özellik hakkında çok fazla belge bulamadım, ancak FullScreenmodun yumuşak klavyenin fazla kullanılmasını gerektirmeyen oyun uygulaması için tasarlandığını düşünüyorum . Sizinki, yumuşak klavye aracılığıyla kullanıcı etkileşimi gerektiren bir Etkinlikse, lütfen FullScreen olmayan bir tema kullanmayı tekrar düşünün. Bir NoTitleBartema kullanarak TitleBar'ı kapatabilirsiniz . Neden bildirim çubuğunu gizlemek istersiniz?


2

Sadece tut android:windowSoftInputMode="adjustResize". Bunun sadece bir out tutmak için verilmiş olduğundan "adjustResize"ve "adjustPan"(pencere ayar modu ya adjustResize veya adjustPan ile belirtilir. Oldukça her zaman bir ya da diğer belirtmeniz önerilir). Burada bulabilirsiniz: http://developer.android.com/resources/articles/on-screen-inputs.html

Benim için mükemmel çalışıyor.


Herhangi bir sorunla karşılaşmıyorum ... XML'inizi de denedim. Bu da çalışır ... Os sürüm 2.2 kullanarak
Balaji Khadake

Ben sadece tam ekran modu ile denedim ... m Nexus One ve Nexus S üzerinde test .... Çalışır.
Balaji Khadake

1
Galaxy S, HTC wildfire, HTC Hero, Motorola Deify ve Sony XPeria ile denedim. Tek bir cihazda çalışmıyor.
Vineet Shukla


2

Şu anda bu yaklaşımı kullanıyorum ve bir cazibe gibi çalışıyor. İşin püf noktası, klavye yüksekliğini yukarıda ve aşağıda 21 farklı yöntemlerden alıyor ve ardından etkinliğimizde kök görünümümüzün alt dolgusu olarak kullanıyoruz. Düzeninizin üst dolguya ihtiyaç duymadığını varsaydım (durum çubuğunun altına gider), ancak bunu yaparsanız cevabımı güncellemek için beni bilgilendirin.

MainActivity.java

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        RelativeLayout mainLayout = findViewById(R.id.main_layout);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            ViewCompat.setOnApplyWindowInsetsListener(mainLayout , new OnApplyWindowInsetsListener() {
                @Override
                public WindowInsetsCompat onApplyWindowInsets(View v, WindowInsetsCompat insets) {
                    v.setPadding(0, 0, 0, insets.getSystemWindowInsetBottom());
                    return insets;
                }
            });
        } else {
            View decorView = getWindow().getDecorView();
            final View contentView = mainLayout;
            decorView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                @Override
                public void onGlobalLayout() {
                    Rect r = new Rect();
                    //r will be populated with the coordinates of your view that area still visible.
                    decorView.getWindowVisibleDisplayFrame(r);

                    //get screen height and calculate the difference with the useable area from the r
                    int height = decorView.getContext().getResources().getDisplayMetrics().heightPixels;
                    int diff = height - r.bottom;

                    //if it could be a keyboard add the padding to the view
                    if (diff != 0) {
                        // if the use-able screen height differs from the total screen height we assume that it shows a keyboard now
                        //check if the padding is 0 (if yes set the padding for the keyboard)
                        if (contentView.getPaddingBottom() != diff) {
                            //set the padding of the contentView for the keyboard
                            contentView.setPadding(0, 0, 0, diff);
                        }
                    } else {
                        //check if the padding is != 0 (if yes reset the padding)
                        if (contentView.getPaddingBottom() != 0) {
                            //reset the padding of the contentView
                            contentView.setPadding(0, 0, 0, 0);
                        }
                    }
                }
            });
        }
    }
...
}

Kök görünümünüzü bir kimlikle ele almayı unutmayın:

activity_main.xml

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/main_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

Umarım birine yardımcı olur.


1
Bu cevabın neden hala üstte olmadığını anlayamıyorum. Diğerleri aksaklık, flaş, ama bu özellikle 5+ api'niz varsa parlak.
Anton Shkurenko

1

Yalnızca android:windowSoftInputMode="adjustResize|stateHiddenAdjustPan'ı kullandığınızda kullanın , ardından resizing özelliğini devre dışı bırakın


Ben de kullandım .... Lütfen tam ekran modunda yaptığınızdan ve hangi cihazda test yaptığınızdan emin olun.
Vineet Shukla

HTC NEXUS one, ok i hvnt tam ekran ekle
Mohammed Azharuddin Shaikh

getWindow () kullanın. requestFeature (Window.FEATURE_NO_TITLE); tema yerine onCreate ()?
Muhammed Azharuddin Shaikh

10
Yukarıdaki kod tam ekran olmadan iyi çalışıyor ancak xml veya koddan tam ekran ekliyor ... Çalışmıyor ... Lütfen soruyu dikkatlice okuyun.
Vineet Shukla

1

Joseph Johnson'ı AndroidBug5497Workaround sınıfını oluşturdum, ancak ekran klavyesi ve görünüm arasında siyah alan elde ettim. Bu bağlantıya Greg Ennis'den bahsettim . Yukarıda bazı değişiklikler yaptıktan sonra bu benim son çalışma kodu.

 public class SignUpActivity extends Activity {

 private RelativeLayout rlRootView; // this is my root layout
 private View rootView;
 private ViewGroup contentContainer;
 private ViewTreeObserver viewTreeObserver;
 private ViewTreeObserver.OnGlobalLayoutListener listener;
 private Rect contentAreaOfWindowBounds = new Rect();
 private FrameLayout.LayoutParams rootViewLayout;
 private int usableHeightPrevious = 0;

 private View mDecorView;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_sign_up);
  mDecorView = getWindow().getDecorView();
  contentContainer =
   (ViewGroup) this.findViewById(android.R.id.content);

  listener = new OnGlobalLayoutListener() {
   @Override
   public void onGlobalLayout() {
    possiblyResizeChildOfContent();
   }
  };

  rootView = contentContainer.getChildAt(0);
  rootViewLayout = (FrameLayout.LayoutParams)
  rootView.getLayoutParams();

  rlRootView = (RelativeLayout) findViewById(R.id.rlRootView);


  rlRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
   @Override
   public void onGlobalLayout() {
    int heightDiff = rlRootView.getRootView().getHeight() - rlRootView.getHeight();
    if (heightDiff > Util.dpToPx(SignUpActivity.this, 200)) {
     // if more than 200 dp, it's probably a keyboard...
     //  Logger.info("Soft Key Board ", "Key board is open");

    } else {
     Logger.info("Soft Key Board ", "Key board is CLOSED");

     hideSystemUI();
    }
   }
  });
 }

 // This snippet hides the system bars.
 protected void hideSystemUI() {
  // Set the IMMERSIVE flag.
  // Set the content to appear under the system bars so that the 
  content
  // doesn't resize when the system bars hide and show.
  mDecorView.setSystemUiVisibility(
   View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
 }
 @Override
 protected void onPause() {
  super.onPause();
  if (viewTreeObserver.isAlive()) {
   viewTreeObserver.removeOnGlobalLayoutListener(listener);
  }
 }

 @Override
 protected void onResume() {
  super.onResume();
  if (viewTreeObserver == null || !viewTreeObserver.isAlive()) {
   viewTreeObserver = rootView.getViewTreeObserver();
  }
  viewTreeObserver.addOnGlobalLayoutListener(listener);
 }

 @Override
 protected void onDestroy() {
  super.onDestroy();
  rootView = null;
  contentContainer = null;
  viewTreeObserver = null;
 }
 private void possiblyResizeChildOfContent() {
  contentContainer.getWindowVisibleDisplayFrame(contentAreaOfWindowBounds);

  int usableHeightNow = contentAreaOfWindowBounds.height();

  if (usableHeightNow != usableHeightPrevious) {
   rootViewLayout.height = usableHeightNow;
   rootView.layout(contentAreaOfWindowBounds.left,
    contentAreaOfWindowBounds.top, contentAreaOfWindowBounds.right, contentAreaOfWindowBounds.bottom);
   rootView.requestLayout();

   usableHeightPrevious = usableHeightNow;
  } else {

   this.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
  }
 }
}

1

https://stackoverflow.com/a/19494006/1815624 ve bunu gerçekleştirme arzusuna dayanarak ...

güncellenmiş fikir


cevapları birleştirmek

İlgili kod:

        if (heightDifference > (usableHeightSansKeyboard / 4)) {

            // keyboard probably just became visible
            frameLayoutParams.height = usableHeightSansKeyboard - heightDifference;
            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
            activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
        } else {

            // keyboard probably just became hidden
            if(usableHeightPrevious != 0) {
                frameLayoutParams.height = usableHeightSansKeyboard;
                activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
                activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);

            }

Https://github.com/CrandellWS/AndroidBug5497Workaround/blob/master/AndroidBug5497Workaround.java adresinde Tam Kaynak

eski fikir

Klavyeyi açmadan önce kap yüksekliğinin statik değerini oluşturma usableHeightSansKeyboard - heightDifferenceKlavyenin açıldığı zamana göre kap yüksekliğini ayarlayın ve kapandığında kaydedilen değere ayarlayın

if (heightDifference > (usableHeightSansKeyboard / 4)) {
                // keyboard probably just became visible
                frameLayoutParams.height = usableHeightSansKeyboard - heightDifference;
                int mStatusHeight = getStatusBarHeight();
                frameLayoutParams.topMargin = mStatusHeight;
                ((MainActivity)activity).setMyMainHeight(usableHeightSansKeyboard - heightDifference);

                if(BuildConfig.DEBUG){
                    Log.v("aBug5497", "keyboard probably just became visible");
                }
            } else {
                // keyboard probably just became hidden
                if(usableHeightPrevious != 0) {
                    frameLayoutParams.height = usableHeightSansKeyboard;
                    ((MainActivity)activity).setMyMainHeight();    
                }
                frameLayoutParams.topMargin = 0;

                if(BuildConfig.DEBUG){
                    Log.v("aBug5497", "keyboard probably just became hidden");
                }
            }

MainActivity'de Yöntemler

public void setMyMainHeight(final int myMainHeight) {

    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            ConstraintLayout.LayoutParams rLparams =  (ConstraintLayout.LayoutParams) myContainer.getLayoutParams();
            rLparams.height = myMainHeight;

            myContainer.setLayoutParams(rLparams);
        }

    });

}

int mainHeight = 0;
public void setMyMainHeight() {

    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            ConstraintLayout.LayoutParams rLparams =  (ConstraintLayout.LayoutParams) myContainer.getLayoutParams();
            rLparams.height = mainHeight;

            myContainer.setLayoutParams(rLparams);
        }

    });

}

Kapsayıcı XML Örneği

<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
        <android.support.constraint.ConstraintLayout
            android:id="@+id/my_container"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            app:layout_constraintHeight_percent=".8">

gerekiyorsa benzer şekilde marjlar eklenebilir ...

Başka bir husus, kullanım yastığının bir örneğidir:

https://github.com/mikepenz/MaterialDrawer/issues/95#issuecomment-80519589


1

1) KeyboardHeightHelper oluşturun:

public class KeyboardHeightHelper {

    private final View decorView;
    private int lastKeyboardHeight = -1;

    public KeyboardHeightHelper(Activity activity, View activityRootView, OnKeyboardHeightChangeListener listener) {
        this.decorView = activity.getWindow().getDecorView();
        activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(() -> {
            int keyboardHeight = getKeyboardHeight();
            if (lastKeyboardHeight != keyboardHeight) {
                lastKeyboardHeight = keyboardHeight;
                listener.onKeyboardHeightChange(keyboardHeight);
            }
        });
    }

    private int getKeyboardHeight() {
        Rect rect = new Rect();
        decorView.getWindowVisibleDisplayFrame(rect);
        return decorView.getHeight() - rect.bottom;
    }

    public interface OnKeyboardHeightChangeListener {
        void onKeyboardHeightChange(int keyboardHeight);
    }
}

2) Etkinliğiniz tam ekran olsun:

activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);

3) Klavye yüksekliği değişikliklerini dinleyin ve görünümünüz için alt dolgu ekleyin:

View rootView = activity.findViewById(R.id.root); // your root view or any other you want to resize
KeyboardHeightHelper effectiveHeightHelper = new KeyboardHeightHelper(
        activity, 
        rootView,
        keyboardHeight -> rootView.setPadding(0, 0, 0, keyboardHeight));

Böylece , ekranda her klavye belirdiğinde, görünümünüz için alt dolgu değişecek ve içerik yeniden düzenlenecektir.


0

Alt çubuğun görünümün altına yapışmasını istiyorsunuz, ancak klavye görüntülendiğinde, klavyenin üzerine yerleştirilmek üzere yukarı hareket etmelidirler, değil mi?

Bu kod snippet'ini deneyebilirsiniz:

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    ...>

    <RelativeLayout
        android:id="@+id/RelativeLayoutTopBar"
    ...>
    </RelativeLayout>

    <LinearLayout
        android:id="@+id/LinearLayoutBottomBar"
        android:layout_alignParentBottom = true
        ...>
    </LinearLayout>

    <LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="390dp"
    android:orientation="vertical" 
    android:layout_above="@+id/LinearLayoutBottomBar"
    android:layout_below="@+id/RelativeLayoutTopBar"> 

    <ScrollView 
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:layout_marginBottom="10dp"
        android:id="@+id/ScrollViewBackground">

            ...

        </ScrollView>
     </LinearLayout>
  </RelativeLayout>

BottomBar görünümün alt kısmına yapışacak ve ScrollView içeren LinearLayout üst / alt çubuk ve klavye görüntülendikten sonra görünümden geriye kalanları alacaktır. Sizin için de işe yarayıp yaramadığını bana bildirin.


1
Uygulamalarımda birkaç kez çalıştığı için çok garip. Bu arada, RelativeLayout öğesinin yönü yoktur, böylece kodunuzdaki bu nitelikleri silebilirsiniz. Kod snippet'ini satıra kesebileceğimi fark ettim: android: layout_below = "@ + id / scoringContainerView", ScrollView'a eklemek zorundasınız
banzai86

Tam ekran? Üstte bir düzen olmadan mı demek istiyorsun?
banzai86

hayır ..... Pil ömrünü, cihazın bağlantısını vb. gösteren hiçbir durum çubuğu yok ....
Vineet Shukla

hayır, durum çubuğu uygulamamda görünür. mizanpajlarınızın sırasını değiştirmeyi deneyebilir, yani mizanpajınızın kodunu diğer kodun üzerindeki düğmelerle yerleştirip tekrar deneyebilirsiniz? belki layout_below'u kullanmak için önce bunları tanımlamanız gerekir
banzai86

1
lütfen soruyu dikkatlice okuyun ...... FullScreen modu ile sorun yaşadığımdan bahsetmiştim ......
Vineet Shukla

0

Cevabınız için teşekkürler Joseph. Ancak, muhtemelenResizeChildOfContent () yönteminde, bölüm

else {
            // keyboard probably just became hidden
            frameLayoutParams.height = usableHeightSansKeyboard;
        }

görüşün alt kısmı gizlendiğinden benim için çalışmıyor. Bu yüzden global bir değişken restore etmeliydim restoreHeight ve yapıcıya son satırı ekledim

restoreHeight = frameLayoutParams.height;

ve daha sonra bahsedilen kısmı değiştirdim

else {
            // keyboard probably just became hidden
            frameLayoutParams.height = restoreHeight;
        }

Ancak kodunuzun neden işe yaramadığı hakkında hiçbir fikrim yok. Birisi buna ışık tutabilirse çok yardımcı olur.


0

Durum çubuğunu gizlemek için yalnızca tam ekran modunu kullanıyordum. Ancak, klavye gösterildiğinde uygulamanın yeniden boyutlandırılmasını istiyorum. Diğer tüm çözümler (muhtemelen yazı yaşı nedeniyle) karmaşıktı veya kullanımım için mümkün değildi (PhoneGap Build çuvalı için Java kodunu değiştirmek istemiyorum).

Tam ekran kullanmak yerine, yapılandırmamı Android için tam ekran olmayacak şekilde değiştirdim:

            <preference name="fullscreen" value="false" />

Ve cordova-plugin-statusbarkomut satırı ile:

cordova plugin add cordova-plugin-statusbar

Uygulama yüklendiğinde, basit, kendini gizlemek için eklenti üzerinde bir yöntem çağırır, örneğin:

    if (window.cordova && window.cordova.platformId == 'android' && window.StatusBar)
        window.StatusBar.hide();

Bu bir cazibe gibi çalışır. Sadece gerçek dezavantajı, uygulama yüklendiğinde durum çubuğunun breifly görünür olmasıdır. Benim ihtiyaçlarım için bu bir sorun değildi.


0

StackOverflow gelen tüm olası cevapları denedim, nihayet bir hafta sonra çözüldü Uzun arama. Koordinat düzenini kullandım ve bu linearLayout ile değiştirdim ve sorunum düzeltildi. Muhtemelen koordinat düzeninde hatalar var ya da hatam var.


0

Joseph Johnson ve Johan Stuyts'ın birçok çözümünü denedim. Ancak sonuç olarak, bazı durumlarda (Lenovo s820 gibi) içerik ve klavye arasında beyaz bir boşluk var. Bu yüzden kodlarında bazı değişiklikler yaptım ve sonunda çalışma çözümüm var.

Fikrim, klavye gösterilirken içeriğin üstüne kenar boşluğu eklemeye dayanıyor.

contentContainer.getWindowVisibleDisplayFrame(contentAreaOfWindowBounds);
    int usableHeightNow = contentAreaOfWindowBounds.height();

    if (usableHeightNow != usableHeightPrevious) {

        int difference = usableHeightNow - usableHeightPrevious;

        if (difference < 0 && difference < -150) {
            keyboardShowed = true;
            rootViewLayout.topMargin -= difference + 30;
            rootViewLayout.bottomMargin += 30;
        }
        else if (difference < 0 && difference > -150){
            rootViewLayout.topMargin -= difference + 30;
        }
        else if (difference > 0 && difference > 150) {
            keyboardShowed = false;
            rootViewLayout.topMargin = 0;
            rootViewLayout.bottomMargin = 0;
        }

        rootView.requestLayout();

        Log.e("Bug Workaround", "Difference: " + difference);

        usableHeightPrevious = usableHeightNow;
}

Gördüğünüz gibi, farkın üstüne 30 piksel ekliyorum çünkü ekranın üst kısmı ile kenar boşluklu içerik bölgesi arasında küçük bir beyaz boşluk var. Ve nerede göründüğünü bilmiyorum, bu yüzden sadece marjları küçültmeye karar verdim ve şimdi tam olarak ihtiyacım olan şekilde çalışıyor.


0

Bugün tam ekran sorunu ayarlamak adjustResize çalışmıyor android sdk için gerçek.

Bulduğum cevaplardan:
çözüm - ama çözüm bu resim sorunu üzerinde gösteriyor:

Daha sonra çözümü buldum ve gereksiz bir eylemi kaldırın:

this.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);

Yani, Kotlin'deki sabit çözüm koduma bakın:

class AndroidBug5497Workaround constructor(val activity: Activity) {

    private val content = activity.findViewById<View>(android.R.id.content) as FrameLayout

    private val mChildOfContent = content.getChildAt(0)
    private var usableHeightPrevious: Int = 0
    private val contentContainer = activity.findViewById(android.R.id.content) as ViewGroup
    private val rootView = contentContainer.getChildAt(0)
    private val rootViewLayout = rootView.layoutParams as FrameLayout.LayoutParams

    private val listener = {
        possiblyResizeChildOfContent()
    }

    fun addListener() {
        mChildOfContent.apply {
            viewTreeObserver.addOnGlobalLayoutListener(listener)

        }
    }

    fun removeListener() {
        mChildOfContent.apply {
            viewTreeObserver.removeOnGlobalLayoutListener(listener)
        }
    }

    private fun possiblyResizeChildOfContent() {
        val contentAreaOfWindowBounds = Rect()
        mChildOfContent.getWindowVisibleDisplayFrame(contentAreaOfWindowBounds)
        val usableHeightNow = contentAreaOfWindowBounds.height()

        if (usableHeightNow != usableHeightPrevious) {
            rootViewLayout.height = usableHeightNow
            rootView.layout(contentAreaOfWindowBounds.left,
                    contentAreaOfWindowBounds.top, contentAreaOfWindowBounds.right, contentAreaOfWindowBounds.bottom);
            mChildOfContent.requestLayout()
            usableHeightPrevious = usableHeightNow
        }
    }
}

Hata düzeltme uygulama kodu:

 class LeaveDetailActivity : BaseActivity(){

    private val keyBoardBugWorkaround by lazy {
        AndroidBug5497Workaround(this)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

    }

    override fun onResume() {
        keyBoardBugWorkaround.addListener()
        super.onResume()
    }

    override fun onPause() {
        keyBoardBugWorkaround.removeListener()
        super.onPause()
    }
}

0

Kullanmayın:

getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);

çünkü kötü çalışıyor. Bunun yerine şunları kullanın:

fun setFullScreen(fullScreen: Boolean) {
        val decorView = getWindow().getDecorView()
        val uiOptions : Int
        if(fullScreen){
            uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN // this hide statusBar
            toolbar.visibility = View.GONE // if you use toolbar
            tabs.visibility = View.GONE // if you use tabLayout
        } else {
            uiOptions = View.SYSTEM_UI_FLAG_VISIBLE // this show statusBar
            toolbar.visibility = View.VISIBLE
            tabs.visibility = View.VISIBLE
        }
        decorView.setSystemUiVisibility(uiOptions)
    }

-1

Benim durumumda, Cordova uygulamama Crosswalk eklediğimde bu sorun oluşmaya başladı. Uygulamam tam ekran ve android'de kullanılmıyor: windowSoftInputMode = "adjustPan".

Uygulamada zaten iyonik klavye eklentisi vardı, bu yüzden klavyenin yukarı veya aşağı olup olmadığını tespit etmek sayesinde kolaydı:

// Listen for events to when the keyboard is opened and closed
window.addEventListener("native.keyboardshow", keyboardUp, false);
window.addEventListener('native.keyboardhide', keyboardDown, false);

function keyboardUp()
{
    $('html').addClass('keyboardUp');
}

function keyboardDown()
{
    $('html').removeClass('keyboardUp');
}

Yukarıdaki tüm düzeltmeleri denedim ama benim için bunu bitirdi basit çizgi css bu bit oldu:

&.keyboardUp {
        overflow-y: scroll;
}

Umarım bu, harcadığım birkaç günü kurtarır. :)


Ben android ile cordova ile yaya geçidi kullanıyorum: windowSoftInputMode = "adjustPan". Ancak, çalışmıyor. Sınıfın html öğesine eklendiğini görüyorum, ancak css'in ekranda bir etkisi yok. Ekranın hareket etmesine izin veren başka ayarlarınız var mı?
darewreck

Eklemek dönüşümü ayarlamalıyım: translateY (0px) çalışması için. Ancak, kaydırma hiç çalışmıyor. Herhangi bir fikir?
darewreck
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.