programing

Android 소프트키보드가 보일 때 전체 화면 모드에서 레이아웃을 조정하는 방법

muds 2023. 9. 18. 22:44
반응형

Android 소프트키보드가 보일 때 전체 화면 모드에서 레이아웃을 조정하는 방법

때 를 했고 는 Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ,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>

enter image description here

사진에 소프트키보드가 뜨면 하단 2개의 버튼이 위쪽으로 올라가길 원합니다.

enter image description here

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

이미 정답이 정해졌고 버그로 알려진 문제이기 때문에 'Possible Work Around'를 추가하려고 생각했습니다.

소프트 키보드가 표시되면 전체 화면 모드로 전환할 수 있습니다.그러면 "AdjustPan"이 올바르게 작동할 수 있습니다.

즉, @android:style/Theme.Black.NoTitleBar.전체 화면을 응용 프로그램 테마의 일부로 사용하고 상태Visible|활동 창 소프트 입력 모드의 일부로 크기 조정을 수행하지만 키보드가 뜨기 전에 전체 화면 모드를 전환해야 합니다.

다음 코드를 사용합니다.

전체 화면 모드 끄기

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

참고 - 영감은 다음에서 왔습니다.전체 화면 모드에서 제목 숨기기

는 Joseph Johnson의 해결책을 시도했지만, 다른 사람들과 마찬가지로 콘텐츠와 키보드 사이의 문제에 부딪혔습니다.전체 화면 모드를 사용할 때 소프트 입력 모드는 항상 팬 상태이기 때문에 문제가 발생합니다.이 패닝은 소프트 입력에 의해 가려질 입력 필드를 활성화할 때 조셉의 솔루션을 방해합니다.

소프트 입력이 나타나면 내용은 처음에 원래 높이를 기준으로 패닝된 다음 조셉 솔루션에서 요청한 레이아웃에 따라 크기가 조정됩니다.크기 조정 및 후속 레이아웃은 패닝을 실행 취소하지 않으므로 간격이 발생합니다.전체 이벤트 순서는 다음과 같습니다.

  1. 글로벌 레이아웃 리스너
  2. 패닝
  3. 컨텐츠 레이아웃 (= 컨텐츠의 실제 크기 조정)

패닝을 비활성화할 수는 없지만 콘텐츠의 높이를 변경하여 팬 오프셋을 0으로 강제 설정할 수도 있습니다.이것은 청취자가 패닝을 하기 전에 실행되기 때문에 수행할 수 있습니다.콘텐츠 높이를 사용 가능한 높이로 설정하면 사용자 환경이 원활해집니다. 즉, 깜박임이 발생하지 않습니다.

저도 이런 변경을 했습니다.다음과 같은 문제가 발생할 경우 알려주십시오.

  • Δ Δ Δ Δ Δ Δ Δ Δ ΔΔ Δ Δ Δ Δ Δ Δ Δ Δ Δ,getWindowVisibleDisplayFrame.Rect불필요한 쓰레기를 조금이라도 방지하기 위해 캐시됩니다.
  • 리스너도 제거할 수 있도록 허용합니다.이 기능은 다른 전체 화면 요구 사항을 가진 다른 조각에 대해 작업을 재사용할 때 유용합니다.
  • 표시된 키보드와 숨겨진 키보드를 구별하지 말고 항상 표시 프레임 높이로 컨텐츠 높이를 설정합니다.

넥서스 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
        }
    }
}

시스템 UI 접근법(https://developer.android.com/training/system-ui/immersive.html) 을 사용하는 경우 간단하고 신뢰할 수 있는 솔루션을 찾았습니다.

사용할 때는 효과가 있습니다.View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 를 : CoordinatorLayout.

에게는 통하지 않을 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)

마시멜로를 실행하는 내 장치에서 테스트해 봤습니다.

창 중 , 모음 등)이므로 은 도 이므로 이므로 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+가 필요한데, 상태 표시줄 뒤에 그림을 그리는 데는 롤리팝+에서만 풀스크린을 사용하고 있어 이 경우 가장 좋은 솔루션입니다.)

를 해 주시기 .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);`
    

method-2는 Android 4.1 이상에서만 작동합니다.

저도 이 문제에 직면해야 했고 HTC 원, 갤럭시 s1, s2, s3, 노트, HTC 센세이션을 확인하는 작업을 했습니다.

레이아웃의 루트 보기에 전역 레이아웃 리스너 배치

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

그리고 거기서 나는 높이 차이를 확인했고 만약 화면의 높이 차이가 화면 높이의 3분의 1보다 크다면 키보드가 열려 있다고 가정할 수 있습니다. 이 답변에서 따왔습니다.

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

이것은 아마도 총알에 대한 증거가 아닐 것이고 아마도 몇몇 장치에서는 작동하지 않을 것입니다. 그러나 그것은 저에게 효과가 있었고 당신에게도 도움이 되기를 바랍니다.

더하다android:fitsSystemWindows="true"레이아웃으로 이동하면 이 레이아웃의 크기가 조정됩니다.

Joseph Johnson 솔루션을 구현했는데 잘 작동했습니다. 이 솔루션을 사용한 후 애플리케이션의 드로어가 제대로 닫히지 않을 때가 있다는 것을 알게 되었습니다.사용자가 편집 텍스트가 있는 프래그먼트를 닫을 때 리스너 removeOnGlobalLayoutListener를 제거하는 기능을 추가했습니다.

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

내 편집 텍스트가 위치한 클래스를 사용합니다.

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

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

저는 현재 이 방법을 사용하고 있는데 매력적으로 작용합니다.비결은 키보드 높이를 위 아래 21개의 다양한 방법으로 얻은 다음 활동에서 루트 뷰의 하단 패딩으로 사용한다는 것입니다.저는 당신의 레이아웃에 상단 패딩(상태 표시줄 아래로 이동)이 필요 없다고 생각했지만, 필요하다면 제 답변을 업데이트하도록 알려주세요.

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

루트 뷰에 ID 주소를 지정하는 것을 잊지 마십시오.

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

누군가에게 도움이 되길 바랍니다.

FullScreen(전체 화면)으로 작동하려면:

이온 키보드 플러그인을 사용합니다.이를 통해 키보드가 나타나고 사라질 때까지 들을 수 있습니다.

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

기본적으로 차이가 마이너스라면 키보드가 입력한 픽셀의 양입니다.그래서 만약 당신이 이것으로 당신의 부모 디브를 조정한다면 그것은 그것에 대항할 것입니다.

논리에 시간 제한을 추가하면 300ms도 성능을 최적화해야 합니다(이렇게 하면 키보드 시간이 나타날 수 있기 때문입니다.

저는 조셉 존슨의 수업을 시도해 보았는데 효과는 있었지만, 제 요구를 충족시키지는 못했습니다.안드로이드:windowSoftInputMode="adjustResize"를 에뮬레이트하는 것보다 안드로이드:windowSoftInputMode="adjustPan"을 에뮬레이트할 필요가 있었습니다.

저는 이것을 전체 화면 웹뷰에 사용하고 있습니다.컨텐츠 뷰를 정확한 위치로 이동하기 위해서는 포커스가 있는 페이지 요소의 위치에 대한 상세 정보를 제공하는 자바스크립트 인터페이스를 사용해야 합니다.자세한 내용은 생략했지만, 조셉 존슨의 수업을 다시 쓴 것을 제공했습니다.사용자 정의 팬과 크기를 비교하여 구현할 수 있는 매우 견고한 기반을 제공할 것입니다.

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

}

1) 키보드 만들기높이 도우미:

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

따라서 키보드가 화면에 나타날 때마다 보기의 하단 패딩이 변경되고 내용이 재정렬됩니다.

실제로 부드러운 키보드 모양은 영향을 미치지 않는 것 같습니다.Activity windowSoftInputMode에서 합니다.FullScreen

이 부동산에 대한 문서를 많이 찾을 수는 없었지만, 제 생각에는FullScreen모드는 소프트 키보드를 많이 사용할 필요가 없는 게임 어플리케이션을 위해 고안되었습니다.소프트 키보드를 통한 사용자 상호 작용이 필요한 활동일 경우 전체 화면이 아닌 테마를 사용하는 것을 다시 고려하십시오.여을끌수다a수을une을 사용하여 제목 을 끌 수 있습니다.NoTitleBar테마. 왜 알림바를 숨기려고 합니까?

그대로 두십시오.android:windowSoftInputMode="adjustResize". 왜냐하면 그것은 단지 하나만 밖에 나가지 못하게 하기 위해 주어지기 때문입니다."adjustResize"그리고."adjustPan"(창 조정 모드는 resize(크기 조정) 또는 adjustPan(판 조정)으로 지정됩니다.항상 하나 또는 다른 하나를 지정하는 것이 좋습니다.여기에서 확인하실 수 있습니다: http://developer.android.com/resources/articles/on-screen-inputs.html

저한테 딱 들어맞습니다.

android:windowSoftInputMode="adjustResize|stateHidden AdjustPan을 합니다.

Joseph Johnson을 사용하여 AndroidBug5497Work Around 클래스를 만들었지만 소프트키보드와 뷰 사이에 검은 공간이 생겼습니다.링크 그렉 에니스를 참조했습니다.위의 내용을 수정한 후 이것이 저의 최종 작업 코드입니다.

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

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

private void resizeWindowOnKeyboardVisible() {
            RelativeLayout rootLayout;
            rootLayout = findViewById(R.id.rootLayout);
            this.getWindow().getDecorView().getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    
                ViewGroup.LayoutParams layoutParams = rootLayout.getLayoutParams();
                int height ;
    
                @Override
                public void onGlobalLayout() {
                    Rect r = new Rect();
                    getWindow().getDecorView().getWindowVisibleDisplayFrame(r);
                    int screenHeight = rootLayout.getContext().getResources().getDisplayMetrics().heightPixels;
                    int heightDiff = screenHeight - r.bottom;
    
                    if (heightDiff > screenHeight*0.15)
                    {
                        height = screenHeight - heightDiff;
                        layoutParams.height=height;
                        rootLayout.setLayoutParams(layoutParams);
                    }else{
                        height=ViewGroup.LayoutParams.MATCH_PARENT;
                        if( height!=layoutParams.height) {
                            layoutParams.height = height;
                            rootLayout.setLayoutParams(layoutParams);
                        }
                    }
                }
            });
        }

Android:windowSoftInputMode="adjustResize|stateHidden을 사용하면 모든 경우에 작동하지 않을 수 있으며 Android:fitSystemWindows="true는 SYSTEM_UI_FLAG_FULLSCREEN 태그를 사용할 때 도움이 되지 않습니다.키보드가 보일 때 보기/창/웹 보기를 조정할 수 있도록 하려면 다음 작업을 수행합니다.

  • 상대 레이아웃을 루트 레이아웃으로 사용합니다.
  • 위 메서드 크기 조정 선언WindowOnKeyboardVisible() 활동에서 Create() 메서드에서 내용 보기()를 설정한 후 호출합니다.

안드로이드 11(API 30)에서도 작동합니다.

@ 더 사용되지 @Sdghasemi 을 으로 가 되지 의 되지 insets.getSystemWindowInsetBottom() 키보드 부드럽게 . 그리고 키보드 열림을 부드럽게 하기 위해 패딩 애니메이션을 넣었습니다.

val rootLayout = findViewById<RelativeLayout>(R.id.your_root_layout)      
ViewCompat.setOnApplyWindowInsetsListener(rootLayout) { v, insets ->
    val animator = ValueAnimator.ofInt(0, insets.getInsets(WindowInsetsCompat.Type.ime()).bottom))
    animator.addUpdateListener { 
        valueAnimator -> v.setPadding(0, 0, 0, valueAnimator.animatedValue as? Int ?: 0) 
    }
    animator.duration = 200
    animator.start()
    insets
}

전화해 보세요.onCreate()의의 Activity에는 이 보다 더 잘합니다. 은 보다 합니다 합니다 보다 android:windowSoftInputMode="adjustPan"AndroidManifest.xml

아래쪽 막대가 보기 아래쪽으로 붙기를 원하지만 키보드가 표시되면 위쪽으로 이동하여 키보드 위에 놓여야 합니다.

다음 코드 조각을 시도해 볼 수 있습니다.

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

아래쪽 막대는 보기 아래쪽으로 고정되고 위쪽/아래쪽 막대와 키보드가 표시된 후에는 스크롤 보기가 포함된 선형 레이아웃이 보기 왼쪽으로 이동합니다.당신에게도 도움이 되는지 알려주세요.

조셉씨의 답변에 감사드립니다.그러나 ResizeChildOfContent() 메서드에서 부분

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

시야가 가려지는 바람에 제게 도움이 되지 않았습니다그래서 전 세계적인 변수 복원을 해야 했습니다.높이, 그리고 시공자 안에 마지막 줄을 집어넣었습니다.

restoreHeight = frameLayoutParams.height;

그리고 전에 언급했던 부분을 다른 부분으로 대체했습니다.

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

하지만 왜 당신의 코드가 나에게 안들어갔는지 모르겠어요.누군가 이것을 밝혀줄 수 있다면 큰 도움이 될 것입니다.

저는 상태 표시줄을 숨기기 위해 전체 화면 모드만 사용하고 있었습니다.하지만 키보드가 표시되면 앱 크기를 조정했으면 합니다.다른 솔루션들은 모두 제가 사용하기에는 복잡하거나 불가능했습니다(PhoneGap Build의 sack을 위해 Java 코드를 변경하는 것을 피하고자 함).

전체 화면을 사용하는 대신 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();

이게 매력적으로 느껴지네요.유일한 단점은 앱이 로드되는 동안 상태 표시줄이 잠깐 보인다는 것입니다.제가 필요로 하는 것은 문제가 되지 않았습니다.

stackOverflow에서 가능한 모든 답변을 시도해보았고, 마침내 일주일간의 긴 검색 끝에 해결했습니다. 좌표 레이아웃을 사용했고 선형 레이아웃으로 변경했고 문제는 해결되었습니다.좌표 레이아웃에 버그나 제 실수가 있을지 모르겠습니다.

저는 조셉 존슨과 요한 스튜이츠를 포함한 많은 해결책을 시도했습니다.하지만 그 결과 모든 경우에 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;
}

보시다시피 화면 상단과 여백이 있는 컨텐츠 존 사이에 작은 흰색 공간이 있기 때문에 30px를 추가합니다.그리고 그것이 어디에 나타나는지 모르기 때문에 마진을 줄이기로 결정했고 지금은 정확히 내가 필요로 하는 대로 작동합니다.

오늘 작동하지 않음 조정전체 화면 문제에 대해 크기 조정은 안드로이드 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()
    }
}

화면의 높이를 계산하는 도우미 클래스나 함수를 직접 만들지 않고도 다른 방법이 있습니다.용을 합니다.ViewCompat.setOnApplyWindowInsetsListener높이에 할 수 . 청취자와 함께 키보드가 열려 있는지 확인하고 키보드 높이에 따라 하단 패딩을 설정할 수 있습니다.

// the root view of your webview, e.g FrameLayout or LinearLayout
    rootView = view.findViewById(R.id.whatever);
    
    ViewCompat.setOnApplyWindowInsetsListener(rootView, (webView, insets) -> {
        
        // checks if keyboard is visible, the Type.ime() stands for Input Method
        boolean isKeyboardVisible = insets.isVisible(WindowInsetsCompat.Type.ime());
        
        // get the keyboard height and use the height as bottom padding for your view
        int bottomKeyboardPadding = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom;

        
        if (isKeyboardVisible) { webView.setPadding(0, 0, 0, bottomKeyboardPadding); }
        else { webView.setPadding(0, 0, 0, 0); }

        return insets;
    });

소프트 입력으로 전체 화면을 지원하려면:

private fun View.setStatusBarTransparent() {
    this@MainActivity.apply {
        window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
        window.statusBarColor = ContextCompat.getColor(this, R.color.transparent)
        this@setStatusBarTransparent.fitsSystemWindows = true
        WindowCompat.setDecorFitsSystemWindows(window, false)
        ViewCompat.setOnApplyWindowInsetsListener(this@setStatusBarTransparent) { root, windowInset ->
            val inset = windowInset.getInsets(WindowInsetsCompat.Type.systemBars())
            val inset2 = windowInset.getInsets(WindowInsetsCompat.Type.ime())
            root.updateLayoutParams<ViewGroup.MarginLayoutParams> {
                leftMargin = inset.left
                bottomMargin = maxOf(inset.bottom, inset2.bottom)
                rightMargin = inset.right
            }
            WindowInsetsCompat.CONSUMED
        }
    }
}

사용 안 함:

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

저의 경우, 이 문제는 제가 Cordova 애플리케이션에 횡단보도를 추가하면서 발생하기 시작했습니다.내 앱은 전체 화면과 안드로이드에서 사용되지 않습니다. 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;
}

이것이 제가 이 일에 소비했던 며칠간의 시간을 아끼길 바랍니다.:)

언급URL : https://stackoverflow.com/questions/7417123/android-how-to-adjust-layout-in-full-screen-mode-when-softkeyboard-is-visible

반응형