Android วิธีปรับเลย์เอาต์ในโหมดเต็มหน้าจอเมื่อมองเห็นซอฟต์คีย์บอร์ด


178

ฉันค้นคว้ามากเพื่อปรับเลย์เอาต์เมื่อมีการใช้งานซอฟต์คีย์บอร์ดและฉันใช้งานได้สำเร็จ แต่ปัญหาเกิดขึ้นเมื่อฉันใช้android:theme="@android:style/Theme.NoTitleBar.Fullscreen"สิ่งนี้ในแท็กกิจกรรมของฉันในไฟล์รายการ

สำหรับเรื่องนี้ฉันได้ใช้android:windowSoftInputMode="adjustPan|adjustResize|stateHidden"กับตัวเลือกที่แตกต่างกัน แต่ไม่มีโชค

หลังจากนั้นฉันดำเนินการFullScreenโปรแกรมและพยายามที่รูปแบบต่าง ๆ เพื่อให้การทำงานมีFullScreenแต่ทั้งหมดในไร้สาระ

ฉันอ้างลิงค์เหล่านี้และดูโพสต์มากมายที่เกี่ยวข้องกับปัญหานี้:

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/

นี่คือรหัส xml:

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

ป้อนคำอธิบายรูปภาพที่นี่

ฉันต้องการปุ่ม 2 ปุ่มด้านล่างควรขึ้นไปด้านบนเมื่อ softkeyboard ปรากฏในรูปภาพ

ป้อนคำอธิบายรูปภาพที่นี่


1
ฉันคิดว่าคุณต้องเพิ่มปุ่มใน ScrollView และด้านล่าง EditText
Balaji Khadake

ฉันได้ลองใช้ตัวเลือกมากมายที่ไม่สามารถใช้งานได้ ...
Vineet Shukla

1
ใส่ปุ่ม ur ใน framelayout และตั้งค่าน้ำหนักของ framelayout เป็น 1 และในที่สุดใช้เพียงandroid:windowSoftInputMode="adjustPan"บอกฉันว่างานนี้ ..
Sherif elKhatib

@VineetShukla คุณพบผลงานเต็มหน้าจอหรือไม่?
มูฮัมหมัดบาบา

2
โปรดสังเกตว่าคุณไม่ควรใช้adjustResizeและadjustPanในเวลาเดียวกันจาก javadoc ของandroid.view.WindowManager.LayoutParams#SOFT_INPUT_ADJUST_RESIZE: "สิ่งนี้ไม่สามารถใช้ร่วมกับ {@link SOFT_INPUT_ADJUST_PAN}"
Denis Kniazhev

คำตอบ:


257

ขึ้นอยู่กับการแก้ปัญหาของ yghm ฉันได้เขียนคลาสความสะดวกสบายที่ช่วยให้ฉันสามารถแก้ปัญหาด้วยสายการบินเดียว (หลังจากเพิ่มคลาสใหม่ลงในซอร์สโค้ดของหลักสูตร) หนึ่งซับคือ:

     AndroidBug5497Workaround.assistActivity(this);

และคลาสการใช้งานคือ:


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

หวังว่านี่จะช่วยใครซักคน


8
ขอบคุณ! ฉันไม่รู้ว่าทำไม แต่ฉันต้องแทนที่return (r.bottom - r.top); ด้วยreturn r.bottomเพื่อให้ทำงานกับ HTC One Mini ของฉันไม่เช่นนั้นมุมมองกิจกรรมจะถูกผลักให้สูงเกินไปด้วยขนาดของแถบสถานะ ฉันยังไม่ได้ทดสอบกับอุปกรณ์อื่น หวังว่าจะช่วยได้
Joan

4
สวัสดีโจเซฟจอห์นสันฉันใช้รหัสของคุณและมันทำงานได้อย่างสมบูรณ์ แต่วันนี้ประสบปัญหาในอุปกรณ์ขนาดเล็กบางอย่างที่จะแสดงช่องว่าง (หน้าจอว่าง) ระหว่างแป้นพิมพ์และเค้าโครง คุณมีความคิดเกี่ยวกับปัญหานี้หรือไม่? ฉันลอง r.bottom ด้วย
Pankaj

2
โจเซฟจอห์นสัน: ฉันได้ใช้วิธีการของคุณมันทำงานได้ดีเมื่อเราคลิกที่ข้อความแก้ไขด้านบน แต่เมื่อเราคลิกที่ edittext ด้านล่างการออกแบบทั้งหมดขึ้น
ranjith

3
น่าเสียดายที่มันใช้ไม่ได้กับ Nexus 7 (2013) มันยังคงกระทะแม้จะมีการปรับชุดไม่มี
Le-roy Staines

4
คำตอบที่ยอดเยี่ยมขอบคุณมาก มันใช้งานได้กับ Nexus 6 แต่แทนที่จะใช้frameLayoutParams.height = usableHeightSansKeyboard;ฉันต้องใช้frameLayoutParams.height = usableHeightNow; ถ้าฉันไม่ได้องค์ประกอบบางอย่างอยู่นอกจอ
RobertoAllende

37

เนื่องจากคำตอบได้ถูกเลือกแล้วและเป็นปัญหาที่รู้กันว่าเป็นข้อผิดพลาดฉันคิดว่าฉันจะเพิ่ม "Possible Work Around"

คุณสามารถสลับโหมดเต็มหน้าจอเมื่อแสดงคีย์บอร์ดนุ่ม สิ่งนี้ทำให้ "adjustPan" ทำงานอย่างถูกต้อง

ในคำอื่น ๆ ฉันยังคงใช้@android: style / Theme.Black.NoTitleBar.Fullscreenเป็นส่วนหนึ่งของชุดรูปแบบของแอปพลิเคชันและstateVisible | adjustResizeเป็นส่วนหนึ่งของหน้าต่างกิจกรรมป้อนข้อมูลแบบอ่อน แต่เพื่อให้พวกเขาทำงานร่วมกันฉันต้องสลับโหมดเต็มหน้าจอ ก่อนที่คีย์บอร์ดจะมา

ใช้รหัสต่อไปนี้:

ปิดโหมดเต็มหน้าจอ

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

เปิดโหมดเต็มหน้าจอ

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

หมายเหตุ - แรงบันดาลใจมาจาก: ซ่อนชื่อในโหมดเต็มหน้าจอ


1
ฉันขอขอบคุณที่คุณให้เวลากับปัญหา +1 สำหรับสิ่งนั้น ฉันจะทดสอบวิธีการนี้อย่างแน่นอนและแจ้งให้คุณทราบในไม่ช้าถ้ามันใช้งานได้สำหรับฉันขอบคุณ
Vineet Shukla

1
ทำงานเป็นที่น่าสงสัย! ทางออกที่ดีจริงๆ! +1 จากด้านข้างของฉัน
Mike


1
คีย์บอร์ดล็อคทำให้พื้นหลังแป้นพิมพ์เป็นสีดำ เอฟเฟ็กต์การถ่ายภาพดูไม่ดี :(
nibz

ว้าวขอบคุณ ... มันใช้งานได้ดีสำหรับฉันจริงๆด้วยการรวมวิธีแก้ปัญหาที่กล่าวถึงโดย AndroidBug5497Workaround ... ฉันอัปโหลดแหล่งรวมไปยัง GitHub ... github.com/CrandellWS/AndroidBug5497Workaround/blob/master/…
CrandellWS

23

ฉันลองวิธีแก้ปัญหาจากโจเซฟจอห์นสันแต่เหมือนคนอื่น ๆ ที่ฉันพบปัญหาช่องว่างระหว่างเนื้อหาและคีย์บอร์ด ปัญหาเกิดขึ้นเนื่องจากโหมดป้อนข้อมูลแบบซอฟต์จะถูกเลื่อนเมื่อใช้โหมดเต็มหน้าจอเสมอ การแพนกล้องนี้รบกวนการแก้ปัญหาของโจเซฟเมื่อคุณเปิดใช้งานฟิลด์อินพุตที่จะถูกซ่อนไว้โดยอินพุตนุ่ม

เมื่ออินพุตซอฟต์ปรากฏขึ้นเนื้อหาจะถูกแพนก่อนตามความสูงเดิมจากนั้นปรับขนาดตามเลย์เอาต์ที่ร้องขอโดยโซลูชันของโจเซฟ การปรับขนาดและเค้าโครงที่ตามมาไม่ได้ยกเลิกการแพนซึ่งส่งผลให้เกิดช่องว่าง ลำดับเต็มของเหตุการณ์คือ:

  1. ฟังเค้าโครงทั่วโลก
  2. ปรากฎว่า
  3. เค้าโครงของเนื้อหา (= การปรับขนาดเนื้อหาจริง)

ไม่สามารถปิดการแพนกล้องได้ แต่เป็นไปได้ที่จะบังคับให้แพนออฟเซตเป็น 0 โดยการเปลี่ยนความสูงของเนื้อหา สิ่งนี้สามารถทำได้ในฟังเพราะมันจะทำงานก่อนที่จะปรากฎ การตั้งค่าความสูงของเนื้อหาเป็นความสูงที่มีอยู่จะส่งผลให้ผู้ใช้ได้รับประสบการณ์ที่ราบรื่นเช่นไม่มีการกะพริบ

ฉันยังทำการเปลี่ยนแปลงเหล่านี้ หากปัญหาข้อใดข้อหนึ่งเหล่านี้แจ้งให้เราทราบ:

  • getWindowVisibleDisplayFrameเปลี่ยนการกำหนดความสูงพร้อมที่จะใช้งาน The Rectถูกแคชเพื่อป้องกันขยะที่ไม่จำเป็น
  • อนุญาตให้ผู้ฟังถูกลบเช่นกัน สิ่งนี้มีประโยชน์เมื่อคุณนำกิจกรรมมาใช้ใหม่สำหรับชิ้นส่วนต่าง ๆ ที่มีข้อกำหนดแบบเต็มหน้าจอแตกต่างกัน
  • อย่าแยกแยะระหว่างคีย์บอร์ดที่แสดงหรือซ่อนอยู่ แต่ตั้งค่าความสูงของเนื้อหาให้เป็นความสูงของกรอบการแสดงผลที่มองเห็นได้เสมอ

มันได้รับการทดสอบบน Nexus 5 และอีมูเลเตอร์ที่ใช้ระดับ API 16-24 พร้อมขนาดหน้าจอตั้งแต่ขนาดเล็กไปจนถึงขนาดใหญ่

รหัสได้รับการพอร์ตไปยัง Kotlin แต่การย้ายการเปลี่ยนแปลงของฉันกลับไปที่ Java นั้นง่ายมาก แจ้งให้เราทราบหากคุณต้องการความช่วยเหลือ:

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
นี่น่าจะเป็นคำตอบที่ดีที่สุด ฉันรังเพลิงจาวานี่gist.github.com/grennis/2e3cd5f7a9238c59861015ce0a7c5584 หมายเหตุฉันได้รับการยกเว้นว่าผู้สังเกตการณ์ไม่มีชีวิตและต้องตรวจสอบสิ่งนั้นด้วย
เกร็กเอนนิส

โอ้พระเจ้า! สำรวจลำดับชั้นการดูระบบทั้งหมดเพื่อค้นหาพื้นที่ Ghost นั้น ฉันอยู่ใกล้กับคอมพิวเตอร์ที่ติดคลองสำหรับรถบรรทุกอาหาร แต่เห็นคำตอบของคุณในนาทีสุดท้าย มันได้ผล :)
rupps

1
@Greg Ennis ขอบคุณสำหรับพอร์ต Java บันทึกความพยายามและเวลามากมาย
Ikun

@GregEnnis ขอบคุณโซลูชันของคุณใช้งานได้กับ onResume (), onPause (), onDestroy () (ดูความคิดเห็นในรหัส GitHub)
CoolMind

สิ่งนี้ใช้ได้สำหรับฉันยกเว้นว่าการเรียก RemoveListener ดูเหมือนจะไม่ทำงาน ฉันวางจุดพักทั้งในการpossiblyResizeChildOfContentโทรและการremoveListenerโทรและแม้หลังจากที่ฉันกดremoveListenerจุดหยุดpossiblyResizeChildOfContentก็ยังคงถูกเรียก ใครที่มีปัญหานี้
Quinn

14

ฉันเพิ่งพบโซลูชันที่ง่ายและน่าเชื่อถือหากคุณใช้วิธี UI ของระบบ ( https://developer.android.com/training/system-ui/immersive.html )

มันทำงานได้ในกรณีที่เมื่อคุณกำลังใช้เช่นถ้าคุณกำลังใช้View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREENCoordinatorLayout

มันจะไม่ทำงานสำหรับWindowManager.LayoutParams.FLAG_FULLSCREEN(สิ่งที่คุณสามารถตั้งค่าในชุดรูปแบบด้วยandroid:windowFullscreen) แต่คุณสามารถบรรลุผลที่คล้ายกันด้วยSYSTEM_UI_FLAG_LAYOUT_STABLE(ซึ่ง "มีผลภาพเหมือนกัน" ตามเอกสาร ) และวิธีนี้จะทำงานอีกครั้ง

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 แล้ว

กุญแจสำคัญคือคีย์บอร์ดนุ่มนวลก็เป็นหนึ่งในหน้าต่างระบบ (เช่นแถบสถานะและแถบนำทาง) ดังนั้นการWindowInsetsจัดส่งโดยระบบจะมีข้อมูลที่ถูกต้องและเชื่อถือได้เกี่ยวกับมัน

สำหรับกรณีการใช้งานเช่นในDrawerLayoutที่ที่เราพยายามวาดด้านหลังแถบสถานะเราสามารถสร้างเลย์เอาต์ที่ไม่สนใจเฉพาะส่วนบนสุดและใช้ส่วนเสริมด้านล่างซึ่งเป็นคีย์บอร์ดนุ่ม

นี่คือประเพณีของฉัน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);
        }
    }
}

และใช้มัน:

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

ในทางทฤษฎีสิ่งนี้ควรใช้งานได้กับอุปกรณ์ใด ๆ โดยไม่ต้องดัดแปลงอย่างบ้าคลั่งดีกว่าแฮ็คใด ๆ ที่พยายามใช้การสุ่ม1/3หรือ1/4ขนาดหน้าจอเป็นข้อมูลอ้างอิง

(มันต้องใช้ API 16+ แต่ฉันใช้เต็มหน้าจอเฉพาะบน Lollipop + เพื่อวาดด้านหลังแถบสถานะดังนั้นจึงเป็นทางออกที่ดีที่สุดในกรณีนี้)


@Dilip ใช้งานได้กับ API 16+ โดยมีเงื่อนไขว่าเป็นไปตามเงื่อนไขที่กล่าวมา
Hai Zhang

10

โปรดทราบว่าandroid:windowSoftInputMode="adjustResize"จะไม่ทำงานเมื่อWindowManager.LayoutParams.FLAG_FULLSCREENมีการตั้งค่าสำหรับกิจกรรม คุณมีสองตัวเลือก

  1. ปิดใช้งานโหมดเต็มหน้าจอสำหรับกิจกรรมของคุณ กิจกรรมไม่ได้ถูกปรับขนาดในโหมดเต็มหน้าจอ คุณสามารถทำได้ทั้งใน xml (โดยการเปลี่ยนธีมของกิจกรรม) หรือในรหัส Java เพิ่มบรรทัดต่อไปนี้ในเมธอด onCreate () ของคุณ

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

หรือ

  1. ใช้วิธีทางเลือกเพื่อให้ได้โหมดเต็มหน้าจอ เพิ่มรหัสต่อไปนี้ในวิธี onCreate () ของคุณ

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

โปรดทราบว่าวิธีที่ 2 ใช้ได้กับ Android 4.1 ขึ้นไปเท่านั้น


@AnshulTyagi method-2 ใช้ได้กับ Android 4.1 ขึ้นไปเท่านั้น
Abhinav Chauhan

4
ทดสอบกับ 5.0 และ 4.4.2, Nexus 9 และ Samsung s4 ตามลำดับวิธีที่ 2 ไม่ทำงาน
RobVoisey

1
วิธีที่ 2 ใช้งานไม่ได้และฉันเสียเวลาไปกับมันมาก
เกร็กเอนนิส

ขอบคุณบันทึกวันของฉัน
Deni Rohimat

9

ฉันต้องเผชิญกับปัญหานี้ด้วยและมีการแก้ไขที่ฉันตรวจสอบบน HTC one, galaxy s1, s2, s3, note และความรู้สึกของ HTC

วาง listener แบบโกลบอลลงในมุมมองรูทของเลย์เอาต์ของคุณ

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

และในนั้นฉันได้ตรวจสอบความแตกต่างของความสูงและถ้าความแตกต่างของความสูงของหน้าจอใหญ่กว่าหนึ่งในสามของความสูงของหน้าจอนั้นเราสามารถสันนิษฐานได้ว่าแป้นพิมพ์เปิดอยู่ เอามาจากคำตอบนี้

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

นี่อาจไม่ได้เป็น bullet bullet และอาจใช้กับอุปกรณ์บางอย่าง แต่มันใช้งานได้สำหรับฉันและหวังว่ามันจะช่วยคุณได้เช่นกัน


1
จำเป็นต้องมีการปรับแต่ง แต่ใช้งานได้ ใน Nexus 7 2013 ฉันต้องลดความสูงของคีย์บอร์ด (screenHeight / 3) ด้วยบางพิกเซล เป็นความคิดที่ดีขอบคุณ!
Joao Sousa

7

ฉันใช้งานโซลูชันของโจเซฟจอห์นสันและมันใช้งานได้ดีฉันสังเกตเห็นหลังจากใช้โซลูชันนี้บางครั้งลิ้นชักในแอปพลิเคชันจะปิดไม่สนิท ฉันเพิ่มฟังก์ชันการทำงานเพื่อลบ listener removeOnGlobalLayoutListener เมื่อผู้ใช้ปิดแฟรกเมนต์ที่มี edittexts อยู่

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

ใช้คลาสที่มี edittexts ของฉันตั้งอยู่

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

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

7

เพิ่มandroid:fitsSystemWindows="true"ในเค้าโครงและเค้าโครงนี้จะปรับขนาด


นั่นคือสิ่งที่แก้ไขได้สำหรับฉัน นอกจากนี้ให้แน่ใจว่าคุณตั้งค่าไว้ในมุมมองที่ถูกต้อง หากคุณมีพื้นหลังที่ควรอยู่ด้านล่างแถบสถานะอย่าตั้งค่าไว้ที่นั่น แต่อยู่ที่เค้าโครงด้านใน อาจเป็นไปได้ว่ามุมมอง EditText ฯลฯ ควรอยู่ในเลย์เอาต์ที่สองภายใน ดูการสนทนานี้ด้วยเพราะทำให้สิ่งต่าง ๆ ชัดเจนขึ้น: youtube.com/watch?v=_mGDMVRO3iE
Stan

ทำงานให้ฉันเช่นกัน ขอบคุณที่ @Stan คอมเม้นท์ฉันยังสามารถใช้งานได้กับธีม FULLSCREEN ที่วางแอททริบิวนั้นไว้ใน ViewPager แทนโครงร่างของกิจกรรม / แฟรกเมนต์
marcouberti

5

หากต้องการให้มันทำงานกับเต็มหน้าจอ:

ใช้ปลั๊กอินคีย์บอร์ดไอออนิก สิ่งนี้ช่วยให้คุณฟังเมื่อแป้นพิมพ์ปรากฏขึ้นและหายไป

OnDeviceReady เพิ่มผู้ฟังเหตุการณ์เหล่านี้:

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

ตรรกะ:

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

โดยทั่วไปหากความแตกต่างคือลบแล้วนั่นคือจำนวนพิกเซลที่แป้นพิมพ์ครอบคลุมการป้อนข้อมูลของคุณ ดังนั้นหากคุณปรับ div ผู้ปกครองของคุณด้วยสิ่งนี้ควรตอบโต้มัน

การเพิ่มการหมดเวลาลงในตรรกะบอกว่า 300ms ควรเพิ่มประสิทธิภาพด้วยเช่นกัน (ซึ่งจะทำให้เวลาของแป้นพิมพ์ปรากฏขึ้น


3

ฉันลองชั้นเรียนของโจเซฟจอห์นสันและมันใช้งานได้ แต่ไม่ค่อยตรงกับความต้องการของฉัน แทนที่จะเลียนแบบ android: windowSoftInputMode = "adjustResize" ฉันต้องจำลอง android: windowSoftInputMode = "adjustPan"

ฉันกำลังใช้สิ่งนี้เป็น webview แบบเต็มหน้าจอ ในการเลื่อนมุมมองเนื้อหาไปยังตำแหน่งที่ถูกต้องฉันต้องใช้ส่วนต่อประสาน javascript ซึ่งให้รายละเอียดเกี่ยวกับตำแหน่งขององค์ประกอบของหน้าซึ่งมีโฟกัสและทำให้ได้รับการป้อนข้อมูลด้วยแป้นพิมพ์ ฉันละทิ้งรายละเอียดเหล่านั้น แต่ให้เขียนใหม่ในชั้นเรียนของโจเซฟจอห์นสัน มันจะให้ฐานที่แข็งแกร่งมากสำหรับคุณในการปรับใช้แพนที่กำหนดเองกับการปรับขนาดของเขา

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

}

ดูเหมือนว่าจะเป็นสิ่งที่ฉันต้องการคุณช่วยเพิ่มตัวอย่างทั้งหมดได้ไหม? ขอบคุณสำหรับการทำงานของคุณ!
vilicvane

ฉันไม่ได้ต้องการโพสต์โครงการทั้งหมด สิ่งที่ฉันให้มาจะทำให้คุณรู้สึกถึงวิธีการทำงานที่สมบูรณ์แบบ สิ่งที่คุณต้องกำหนดด้วยตัวคุณเอง: สร้างคลาส "JavaScriptObject" และแทรกลงใน webview ของคุณเป็นอินเทอร์เฟซ js (ตรวจสอบเอกสารประกอบของ webview เพื่อดูว่า) มีโอกาสที่ดีที่คุณได้ทำไปแล้วว่าถ้าเขียนสิ่งที่ใช้เว็บวิวในลักษณะที่ครอบคลุม เพิ่ม JavaScript ใน webview เพื่อฟังเหตุการณ์โฟกัสและป้อนข้อมูลในคลาส JavaScriptObject ของคุณเกี่ยวกับการจัดตำแหน่งองค์ประกอบโฟกัส
BuvinJ

2

อันที่จริงลักษณะแป้นพิมพ์ที่อ่อนนุ่มนั้นดูเหมือนจะไม่ส่งผลกระทบActivityใด ๆ ต่อสิ่งที่windowSoftInputModeฉันเลือกFullScreenโหมดใด

แม้ว่าฉันจะไม่พบเอกสารจำนวนมากเกี่ยวกับคุณสมบัตินี้ แต่ฉันคิดว่าFullScreenโหมดนี้ออกแบบมาสำหรับแอพพลิเคชั่นเกมที่ไม่ต้องใช้คีย์บอร์ดนุ่ม หากคุณเป็นกิจกรรมที่ต้องมีการโต้ตอบกับผู้ใช้ผ่านแป้นพิมพ์อ่อนโปรดพิจารณาอีกครั้งโดยใช้ชุดรูปแบบที่ไม่ใช่แบบเต็มหน้าจอ คุณสามารถปิด TitleBar โดยใช้NoTitleBarชุดรูปแบบ ทำไมคุณต้องการซ่อนแถบการแจ้งเตือน


2

android:windowSoftInputMode="adjustResize"เพียงแค่ให้เป็น เนื่องจากได้รับการกำหนดให้คงอยู่เพียงหนึ่งครั้ง"adjustResize"และ"adjustPan"(โหมดการปรับหน้าต่างถูกระบุด้วย adjustResize หรือ adjustPan ขอแนะนำอย่างยิ่งให้คุณระบุหนึ่งหรืออื่น ๆ เสมอ) คุณสามารถค้นหาได้ที่นี่: http://developer.android.com/resources/articles/on-screen-inputs.html

มันทำงานได้อย่างสมบูรณ์แบบสำหรับฉัน


ฉันไม่ได้รับปัญหาใด ๆ ... ฉันลองใช้ XML ของคุณแล้ว อันนี้ยังใช้งานได้.. ฉันใช้ระบบปฏิบัติการเวอร์ชั่น 2.2
Balaji Khadake

ฉันได้ลองกับโหมดเต็มหน้าจอเท่านั้น ... กำลังทดสอบบน Nexus One และ Nexus S ของฉัน .... มันใช้งานได้
Balaji Khadake

1
ฉันได้ลองกับ Galaxy S, HTC wildfire, HTC Hero, Motorola Deify และ Sony XPeria ไม่ทำงานบนอุปกรณ์เดียว
Vineet Shukla


2

ขณะนี้ฉันใช้วิธีนี้และใช้งานได้เหมือนมีเสน่ห์ เคล็ดลับคือเราได้ความสูงของแป้นพิมพ์จากวิธีการที่แตกต่างกันในวันที่ 21 ด้านบนและด้านล่างจากนั้นใช้เป็นส่วนเสริมด้านล่างของมุมมองรูตของเราในกิจกรรมของเรา ฉันคิดว่าเลย์เอาต์ของคุณไม่จำเป็นต้องมีช่องว่างด้านบน (ไปด้านล่างแถบสถานะ) แต่ในกรณีที่คุณทำแจ้งให้ฉันทราบเพื่ออัปเดตคำตอบของฉัน

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

อย่าลืมระบุมุมมองรูทของคุณด้วยรหัส:

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

หวังว่าจะช่วยใครซักคน


1
ไม่เข้าใจว่าทำไมคำตอบนี้จึงยังไม่ถึงด้านบน คนอื่นนั้นผิดปกติแฟลช แต่อันนี้ยอดเยี่ยมโดยเฉพาะถ้าคุณมี 5+ API
Anton Shkurenko

1

ใช้android:windowSoftInputMode="adjustResize|stateHiddenเมื่อคุณใช้ AdjustPan เท่านั้นจากนั้นจะปิดใช้งานคุณสมบัติการปรับขนาด


ฉันเคยใช้ด้วย .... โปรดให้คุณทำในโหมดเต็มหน้าจอและคุณกำลังทดสอบอุปกรณ์ใดอยู่
Vineet Shukla

หนึ่ง HTC NEXUS โอเคฉัน hvnt เพิ่มแบบเต็มหน้าจอ
Mohammed Azharuddin Shaikh

คุณสามารถใช้ getWindow (). requestFeature (Window.FEATURE_NO_TITLE); onCreate () แทนที่จะใช้ธีมหรือไม่
Mohammed Azharuddin Shaikh

10
รหัสข้างต้นใช้งานได้ดีโดยไม่มีแบบเต็มหน้าจอ แต่เพิ่มแบบเต็มหน้าจออย่างใดอย่างหนึ่งจาก xml หรือจากรหัส ... มันไม่ทำงาน ... โปรดอ่านคำถามอย่างละเอียด
Vineet Shukla

1

ฉันใช้ Joseph Johnson สร้างคลาส AndroidBug5497 Workaround แต่ได้รับพื้นที่สีดำระหว่าง softkeyboard และมุมมอง ผมเรียกว่าการเชื่อมโยงนี้เกร็กเอนนิส หลังจากทำการเปลี่ยนแปลงบางอย่างกับข้างต้นนี่คือรหัสการทำงานสุดท้ายของฉัน

 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และปรารถนาที่จะทำให้มันเกิดขึ้น ...

แนวคิดที่อัปเดต


รวมคำตอบจาก

รหัสที่เกี่ยวข้อง:

        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

ความคิดเก่า ๆ

สร้างค่าคงที่ของความสูงของภาชนะบรรจุก่อนเปิดแป้นพิมพ์ตั้งค่าความสูงของภาชนะตามusableHeightSansKeyboard - heightDifferenceเมื่อแป้นพิมพ์เปิดขึ้นและตั้งค่ากลับเป็นค่าที่บันทึกเมื่อปิด

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

วิธีการในกิจกรรมหลัก

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

    });

}

ตัวอย่างคอนเทนเนอร์ XML

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

สามารถเพิ่มระยะขอบในทำนองเดียวกันหากจำเป็น ...

ข้อควรพิจารณาอีกประการคือใช้การขยายตัวอย่างของสิ่งนี้สามารถดูได้ที่:

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


1

1) สร้าง KeyboardHeightHelper:

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) ให้กิจกรรมของคุณเต็มหน้าจอ:

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

3) ฟังการเปลี่ยนแปลงความสูงของแป้นพิมพ์และเพิ่มช่องว่างด้านล่างสำหรับมุมมองของคุณ:

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

ดังนั้นแต่ละครั้งที่แป้นพิมพ์จะปรากฏบนหน้าจอ - ช่องว่างด้านล่างสำหรับมุมมองของคุณจะเปลี่ยนไปและเนื้อหาจะได้รับการจัดเรียงใหม่


0

คุณต้องการให้แถบด้านล่างติดกับด้านล่างของมุมมอง แต่เมื่อมีการแสดงแป้นพิมพ์พวกเขาควรเลื่อนขึ้นเพื่อวางเหนือแป้นพิมพ์ใช่ไหม

คุณสามารถลองใช้ตัวอย่างรหัสนี้:

<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 จะติดกับด้านล่างของมุมมองและ LinearLayout ที่มี ScrollView จะใช้สิ่งที่เหลืออยู่ของมุมมองหลังจากแถบด้านบน / ล่างและแป้นพิมพ์จะปรากฏขึ้น แจ้งให้เราทราบหากมันเหมาะกับคุณเช่นกัน


1
แปลกมากที่ทำงานในแอพของฉันหลายครั้ง โดยวิธีการ RelativeLayout ไม่มีการวางแนวเพื่อให้คุณสามารถลบคุณลักษณะเหล่านี้ในรหัสของคุณ ฉันเพิ่งรู้ว่าฉันสามารถลดข้อมูลโค้ดลงในบรรทัด: android: layout_below = "@ + id / scoreContainerView" ซึ่งคุณต้องเพิ่ม ScrollView ของคุณ
banzai86

เต็มจอ? คุณหมายถึงไม่มีเลย์เอาต์ที่ด้านบนหรือไม่?
banzai86

ไม่มี ..... ผมหมายถึงไม่มีแถบสถานะซึ่งแสดงแบตเตอรี่, การเชื่อมต่อสำหรับอุปกรณ์ ฯลฯ ....
Vineet ศูกละ

ไม่แถบสถานะปรากฏในแอปของฉัน คุณลองเปลี่ยนลำดับของเลย์เอาต์ซึ่งหมายความว่าคุณใส่รหัสสำหรับเลย์เอาต์ของคุณด้วยปุ่มด้านบนของรหัสอื่นแล้วลองอีกครั้งได้ไหม บางทีคุณต้องกำหนดมันก่อนเพื่อที่จะใช้ layout_below
banzai86

1
โปรดอ่านคำถามอย่างระมัดระวัง ...... ฉันได้กล่าวว่าฉันมีปัญหากับโหมดเต็มหน้าจอ ......
Vineet Shukla

0

ขอบคุณโจเซฟสำหรับคำตอบของคุณ อย่างไรก็ตามในวิธีการอาจResizeChildOfContent () ส่วนที่

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

ไม่ได้ผลสำหรับฉันเนื่องจากมุมมองส่วนล่างซ่อนอยู่ ดังนั้นฉันต้องใช้การเรียกคืนตัวแปรระดับโลกความสูงและในตัวสร้างฉันใส่บรรทัดสุดท้าย

restoreHeight = frameLayoutParams.height;

แล้วฉันก็แทนที่ส่วนที่กล่าวถึงเดิมด้วย

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

แต่ฉันไม่รู้ว่าทำไมรหัสของคุณใช้งานไม่ได้สำหรับฉัน มันจะเป็นความช่วยเหลือที่ดีมากถ้ามีคนสามารถทำให้กระจ่างในเรื่องนี้


0

ฉันใช้โหมดเต็มหน้าจอเพื่อซ่อนแถบสถานะเท่านั้น อย่างไรก็ตามฉันต้องการให้แอพปรับขนาดเมื่อแสดงแป้นพิมพ์ โซลูชันอื่น ๆ ทั้งหมด (น่าจะเกิดจากอายุโพสต์) มีความซับซ้อนหรือเป็นไปไม่ได้สำหรับการใช้งานของฉัน (ต้องการหลีกเลี่ยงการเปลี่ยนรหัส Java สำหรับกระสอบ PhoneGap Build)

แทนที่จะใช้เต็มหน้าจอฉันปรับเปลี่ยนการกำหนดค่าของฉันสำหรับ Android ให้เป็นแบบไม่เต็มหน้าจอ:

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

และเพิ่มcordova-plugin-statusbar, ผ่านทางบรรทัดคำสั่ง:

cordova plugin add cordova-plugin-statusbar

เมื่อโหลดแอพฉันเรียกวิธีการอย่างง่ายบนปลั๊กอินเพื่อซ่อนตัวเองเช่น:

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

งานนี้มีเสน่ห์เหมือนกัน ข้อเสียจริงเท่านั้นคือแถบสถานะจะมองเห็นได้อย่างชัดเจนในขณะที่โหลดแอป สำหรับความต้องการของฉันนั่นไม่ใช่ปัญหา


0

ฉันได้ลองคำตอบทั้งหมดที่เป็นไปได้จาก stackOverflow ในที่สุดฉันก็แก้ไขหลังจากการค้นหา Long สัปดาห์ ฉันใช้เลย์เอาต์ประสานงานและฉันเปลี่ยนสิ่งนี้ด้วย linearLayout และปัญหาของฉันได้รับการแก้ไข ฉันไม่รู้ว่ารูปแบบการประสานงานอาจมีข้อบกพร่องหรืออะไรผิดพลาดของฉัน


0

ฉันลองวิธีแก้ปัญหาหลายอย่างรวมถึง Joseph Johnson's และ Johan Stuyts แต่เป็นผลให้ฉันมีช่องว่างระหว่างเนื้อหาและแป้นพิมพ์ในอุปกรณ์บางอย่าง (เช่น Lenovo s820) ในทุกกรณี ดังนั้นฉันจึงทำการเปลี่ยนแปลงรหัสของพวกเขาและในที่สุดก็มีวิธีแก้ไขปัญหา

ความคิดของฉันขึ้นอยู่กับการเพิ่มมาร์จิ้นไปด้านบนของเนื้อหาเมื่อคีย์บอร์ดแสดง

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

อย่างที่คุณเห็นฉันเพิ่มความแตกต่าง 30 px เนื่องจากมีพื้นที่สีขาวเล็ก ๆ ระหว่างส่วนบนของหน้าจอและเขตเนื้อหาที่มีระยะขอบ และฉันไม่รู้ว่ามันจะปรากฏที่ใดดังนั้นฉันตัดสินใจเพียงแค่ทำให้ส่วนต่างเล็กลงและตอนนี้มันก็ทำงานได้อย่างที่ฉันต้องการ


0

วันนี้ใช้งานไม่ได้ปรับขนาดในปัญหาเต็มหน้าจอเป็นจริงสำหรับ Android sdk

จากคำตอบที่ฉันพบ:
วิธีแก้ปัญหา - แต่วิธีแก้ไขมีสิ่งนี้แสดงในภาพ:

กว่าที่ฉันพบวิธีแก้ปัญหาและลบสิ่งที่ไม่จำเป็นออก:

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

ดังนั้นดูรหัสโซลูชันคงที่ของฉันบน Kotlin:

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

การแก้ไขข้อผิดพลาดของฉันใช้รหัส:

 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

อย่าใช้:

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

เพราะทำงานได้ไม่ดี แทนที่จะใช้:

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

ในกรณีของฉันปัญหานี้เริ่มเกิดขึ้นเมื่อฉันเพิ่ม Crosswalk ไปยังแอปพลิเคชัน Cordova ของฉัน แอพของฉันไม่ได้ใช้งานแบบเต็มหน้าจอและ Android: windowSoftInputMode = "adjustPan"

ฉันมีปลั๊กอินแป้นพิมพ์ไอออนิกในแอปพลิเคชั่นดังนั้นการตรวจสอบว่าแป้นพิมพ์ขึ้นหรือลงเป็นเรื่องง่ายต้องขอบคุณ:

// 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');
}

ฉันพยายามแก้ไขทั้งหมดข้างต้น แต่บรรทัดง่าย ๆ ที่ทำให้ฉันเป็นบิตของ css นี้:

&.keyboardUp {
        overflow-y: scroll;
}

หวังว่านี่จะช่วยให้คุณประหยัดได้ไม่กี่วันที่ฉันใช้ไปกับสิ่งนี้ :)


ฉันใช้ทางม้าลายกับคอร์โดวาและ Android: windowSoftInputMode = "adjustPan" อย่างไรก็ตามมันไม่ทำงาน ฉันเห็นว่าชั้นจะได้รับการเพิ่มองค์ประกอบ HTML แต่ CSS ไม่มีผลบนหน้าจอ มีการตั้งค่าอื่น ๆ ที่คุณอนุญาตให้หน้าจอเคลื่อนที่ได้หรือไม่?
darewreck

ฉันต้องตั้งค่าการแปลงเพิ่ม: translateY (0px) เพื่อให้มันใช้งานได้ อย่างไรก็ตามการเลื่อนไม่ทำงานเลย ความคิดใด ๆ
darewreck
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.