programing

안드로이드에서 "가상 키보드 표시/숨기기" 이벤트를 캡처하는 방법은 무엇입니까?

muds 2023. 8. 29. 21:01
반응형

안드로이드에서 "가상 키보드 표시/숨기기" 이벤트를 캡처하는 방법은 무엇입니까?

가상 키보드의 표시 여부에 따라 레이아웃을 변경하고 싶습니다.API와 다양한 블로그를 검색해봤지만, 유용한 것을 찾을 수 없는 것 같습니다.

가능합니까?

감사합니다!

2020년 업데이트

이제 다음과 같은 작업이 가능합니다.

Android 11에서 당신은 할 수 있습니다.

view.setWindowInsetsAnimationCallback(object : WindowInsetsAnimation.Callback {
    override fun onEnd(animation: WindowInsetsAnimation) {
        super.onEnd(animation)
        val showingKeyboard = view.rootWindowInsets.isVisible(WindowInsets.Type.ime())
        // now use the boolean for something
    }
})

또한 키보드 표시/숨기기 애니메이션을 듣고 해당 전환을 수행할 수 있습니다.

Android 11 미리보기와 해당 설명서읽는 것을 추천합니다.

안드로이드 11 이전

그러나 이 작업은 현재까지 사용할 수 없습니다.Compat그래서 당신은 해킹에 의존해야 합니다.

창을 삽입할 수 있으며 아래쪽 삽입이 (실험을 통해) 상당히 양호한 값보다 클 경우 키보드를 표시하는 것으로 간주할 수 있습니다.이것은 훌륭하지 않고 경우에 따라 실패할 수 있지만, 그것에 대한 프레임워크 지원은 없습니다.

이것은 이 정확한 질문인 https://stackoverflow.com/a/36259261/372076 에 대한 좋은 답변입니다.또는 이전 Android 11을 달성하기 위한 몇 가지 다른 접근 방식을 제공하는 페이지가 있습니다.

https://developer.salesforce.com/docs/atlas.en-us.noversion.service_sdk_android.meta/service_sdk_android/android_detecting_keyboard.htm


메모

및 이솔은키보및드소에서 .onConfigurationChanged소프트(가상) 키보드는 호출되지 않습니다.


구성 변경은 직접 처리해야 합니다.

http://developer.android.com/guide/topics/resources/runtime-changes.html#HandlingTheChange

샘플:

// from the link above
@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    
    // Checks whether a hardware keyboard is available
    if (newConfig.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO) {
        Toast.makeText(this, "keyboard visible", Toast.LENGTH_SHORT).show();
    } else if (newConfig.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_YES) {
        Toast.makeText(this, "keyboard hidden", Toast.LENGTH_SHORT).show();
    }
}

그런 다음 일부 보기의 가시성을 변경하고 필드를 업데이트한 다음 레이아웃 파일을 변경합니다.

나는 이런 식으로 했습니다.

더하다OnKeyboardVisibilityListener인터페이스

public interface OnKeyboardVisibilityListener {
    void onVisibilityChanged(boolean visible);
}

HomeActivity.java:

public class HomeActivity extends Activity implements OnKeyboardVisibilityListener {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_sign_up);
    // Other stuff...
    setKeyboardVisibilityListener(this);
}

private void setKeyboardVisibilityListener(final OnKeyboardVisibilityListener onKeyboardVisibilityListener) {
    final View parentView = ((ViewGroup) findViewById(android.R.id.content)).getChildAt(0);
    parentView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {

        private boolean alreadyOpen;
        private final int defaultKeyboardHeightDP = 100;
        private final int EstimatedKeyboardDP = defaultKeyboardHeightDP + (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? 48 : 0);
        private final Rect rect = new Rect();

        @Override
        public void onGlobalLayout() {
            int estimatedKeyboardHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, EstimatedKeyboardDP, parentView.getResources().getDisplayMetrics());
            parentView.getWindowVisibleDisplayFrame(rect);
            int heightDiff = parentView.getRootView().getHeight() - (rect.bottom - rect.top);
            boolean isShown = heightDiff >= estimatedKeyboardHeight;

            if (isShown == alreadyOpen) {
                Log.i("Keyboard state", "Ignoring global layout change...");
                return;
            }
            alreadyOpen = isShown;
            onKeyboardVisibilityListener.onVisibilityChanged(isShown);
        }
    });
}


@Override
public void onVisibilityChanged(boolean visible) {
    Toast.makeText(HomeActivity.this, visible ? "Keyboard is active" : "Keyboard is Inactive", Toast.LENGTH_SHORT).show();
  }
}

이것이 당신에게 도움이 되길 바랍니다.

이것은 가장 효과적인 해결책이 아닐 수도 있습니다.하지만 이것은 매번 나에게 효과가 있었습니다.저는 소프트 키보드를 들어야 할 때마다 이 기능을 호출합니다.

boolean isOpened = false;

public void setListenerToRootView() {
    final View activityRootView = getWindow().getDecorView().findViewById(android.R.id.content);
    activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {

            int heightDiff = activityRootView.getRootView().getHeight() - activityRootView.getHeight();
            if (heightDiff > 100) { // 99% of the time the height diff will be due to a keyboard.
                Toast.makeText(getApplicationContext(), "Gotcha!!! softKeyboardup", 0).show();

                if (isOpened == false) {
                    //Do two things, make the view top visible and the editText smaller
                }
                isOpened = true;
            } else if (isOpened == true) {
                Toast.makeText(getApplicationContext(), "softkeyborad Down!!!", 0).show();
                isOpened = false;
            }
        }
    });
}

참고: 이 방법은 사용자가 부동 키보드를 사용하는 경우 문제가 발생합니다.

활동에서 IMM(가상) 키보드 창 표시/숨기기를 처리하려면 레이아웃을 하위 분류하고 Mesure 메서드에서 재정의해야 합니다(레이아웃의 측정된 너비와 높이를 결정할 수 있음).그런 다음 내용 보기()를 설정하여 하위 분류 레이아웃을 활동의 기본 보기로 설정합니다.이제 IMM 창 표시/숨기기 이벤트를 처리할 수 있습니다.만약 이것이 복잡하게 들린다면, 사실은 그렇지 않습니다.코드는 다음과 같습니다.

main.xml

   <?xml version="1.0" encoding="utf-8"?>
   <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="horizontal" >
        <EditText
             android:id="@+id/SearchText" 
             android:text="" 
             android:inputType="text"
             android:layout_width="fill_parent"
             android:layout_height="34dip"
             android:singleLine="True"
             />
        <Button
             android:id="@+id/Search" 
             android:layout_width="60dip"
             android:layout_height="34dip"
             android:gravity = "center"
             />
    </LinearLayout>

이제 활동 내부에서 레이아웃(main.xml)에 대한 하위 클래스를 선언합니다.

    public class MainSearchLayout extends LinearLayout {

    public MainSearchLayout(Context context, AttributeSet attributeSet) {
        super(context, attributeSet);
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        inflater.inflate(R.layout.main, this);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        Log.d("Search Layout", "Handling Keyboard Window shown");

        final int proposedheight = MeasureSpec.getSize(heightMeasureSpec);
        final int actualHeight = getHeight();

        if (actualHeight > proposedheight){
            // Keyboard is shown

        } else {
            // Keyboard is hidden
        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}

코드를 보면 하위 클래스 생성자의 활동 레이아웃을 부풀린다는 것을 알 수 있습니다.

inflater.inflate(R.layout.main, this);

이제 활동에 대한 하위 분류 레이아웃의 내용 보기를 설정합니다.

public class MainActivity extends Activity {

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        MainSearchLayout searchLayout = new MainSearchLayout(this, null);

        setContentView(searchLayout);
    }

    // rest of the Activity code and subclassed layout...

}

@amalBit의 답변처럼 수신기를 전역 레이아웃에 등록하고 detectorView의 표시 가능한 하단과 제안된 하단의 차이를 계산합니다. 차이가 일부 값(IME의 높이 추정)보다 크면 IME가 작동했다고 생각합니다.

    final EditText edit = (EditText) findViewById(R.id.edittext);
    edit.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            if (keyboardShown(edit.getRootView())) {
                Log.d("keyboard", "keyboard UP");
            } else {
                Log.d("keyboard", "keyboard Down");
            }
        }
    });

private boolean keyboardShown(View rootView) {

    final int softKeyboardHeight = 100;
    Rect r = new Rect();
    rootView.getWindowVisibleDisplayFrame(r);
    DisplayMetrics dm = rootView.getResources().getDisplayMetrics();
    int heightDiff = rootView.getBottom() - r.bottom;
    return heightDiff > softKeyboardHeight * dm.density;
}

높이 임계값 100은 IME의 추정된 최소 높이입니다.

이것은 adjustPan과 adjustResize 모두에서 작동합니다.

Nebojsa Tomcic의 코드를 기반으로 다음과 같은 RelativeLayout-Subclass를 개발했습니다.

import java.util.ArrayList;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.RelativeLayout;

public class KeyboardDetectorRelativeLayout extends RelativeLayout {

    public interface IKeyboardChanged {
        void onKeyboardShown();
        void onKeyboardHidden();
    }

    private ArrayList<IKeyboardChanged> keyboardListener = new ArrayList<IKeyboardChanged>();

    public KeyboardDetectorRelativeLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

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

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

    public void addKeyboardStateChangedListener(IKeyboardChanged listener) {
        keyboardListener.add(listener);
    }

    public void removeKeyboardStateChangedListener(IKeyboardChanged listener) {
        keyboardListener.remove(listener);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        final int proposedheight = MeasureSpec.getSize(heightMeasureSpec);
        final int actualHeight = getHeight();

        if (actualHeight > proposedheight) {
            notifyKeyboardShown();
        } else if (actualHeight < proposedheight) {
            notifyKeyboardHidden();
        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    private void notifyKeyboardHidden() {
        for (IKeyboardChanged listener : keyboardListener) {
            listener.onKeyboardHidden();
        }
    }

    private void notifyKeyboardShown() {
        for (IKeyboardChanged listener : keyboardListener) {
            listener.onKeyboardShown();
        }
    }

}

이건 꽤 잘 작동합니다...활동의 소프트 입력 모드가 "윈도우 관리자"로 설정되어 있을 때만 이 솔루션이 작동함을 표시합니다.레이아웃 매개 변수.소프트_입력_조정_크기 조정"

안드로이드 11 이전 솔루션:

안드로이드 x.core 1.5.0이 출시되면서 안드로이드 11 이전 기기에서 키보드 표시/숨기기 이벤트를 듣기 위해 수행하는 작업입니다.

그라들:

implementation "androidx.core:core-ktx:1.5.0"

조각:

   override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        val view  = activity?.window?.decorView ?: return
        ViewCompat.setOnApplyWindowInsetsListener(view) { v, insets ->
            val showingKeyboard = insets.isVisible(WindowInsetsCompat.Type.ime())
            if(showingKeyboard){
                //do something
            }
            insets
        }
    }

메모리 누수를 방지하기 위해 보기가 파괴될 때 수신기를 제거해야 합니다.이가 소프트웨어 입력 모드일 합니다.adjustResize가 OnApplyWindows로 된 경우 않음InsetsListener가 트리거하지 않는 경우adjustPan그것을 어떻게 작동시킬 것인지에 대한 아이디어가 있는 사람이 있다면.adjustPan나눠주세요.

참고로 문서에 따르면,

* When running on devices with API Level 29 and before, the returned value is an
* approximation based on the information available. This is especially true for the {@link
* Type#ime IME} type, which currently only works when running on devices with SDK level 23
* and above.
*

inset.isVisible(imime)은 SDK 레벨이 23 이상인 장치에서만 작동해야 합니다.

Nebojsa의 해결책은 거의 효과가 있었습니다.여러 줄로 된 텍스트 편집 내부를 클릭했을 때 키보드가 표시되는 것을 알았지만 텍스트 편집 내부에 입력을 시작했을 때 실제높이 및 제안됨높이가 그대로여서 키보드가 아직 표시되어 있는지 몰랐습니다.최대 높이를 저장하기 위해 약간 수정을 했는데 작동이 잘 됩니다.수정된 하위 클래스는 다음과 같습니다.

public class CheckinLayout extends RelativeLayout {

    private int largestHeight;

    public CheckinLayout(Context context, AttributeSet attributeSet) {
        super(context, attributeSet);
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        inflater.inflate(R.layout.checkin, this);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        final int proposedheight = MeasureSpec.getSize(heightMeasureSpec);
        largestHeight = Math.max(largestHeight, getHeight());

        if (largestHeight > proposedheight)
            // Keyboard is shown
        else
            // Keyboard is hidden

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}

사용자 정의 EditText에서 KeyPreIme(int keyCode, KeyEvent 이벤트)를 재정의하여 이 문제를 해결합니다.

@Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
        //keyboard will be hidden
    }
}

누가 이걸 올리는지 모르겠어요.이 솔루션은 사용하기 간편합니다!소프트키보드 클래스는 gist.github.com 에 있습니다.그러나 키보드 팝업/이벤트 콜백 숨기기 동안 UI에서 작업을 제대로 수행하려면 핸들러가 필요합니다.

/*
Somewhere else in your code
*/
RelativeLayout mainLayout = findViewById(R.layout.main_layout); // You must use your root layout
InputMethodManager im = (InputMethodManager) getSystemService(Service.INPUT_METHOD_SERVICE);

/*
Instantiate and pass a callback
*/
SoftKeyboard softKeyboard;
softKeyboard = new SoftKeyboard(mainLayout, im);
softKeyboard.setSoftKeyboardCallback(new SoftKeyboard.SoftKeyboardChanged()
{

    @Override
    public void onSoftKeyboardHide() 
    {
        // Code here
        new Handler(Looper.getMainLooper()).post(new Runnable() {
                @Override
                public void run() {
                    // Code here will run in UI thread
                    ...
                }
            });
    }

    @Override
    public void onSoftKeyboardShow() 
    {
        // Code here
        new Handler(Looper.getMainLooper()).post(new Runnable() {
                @Override
                public void run() {
                    // Code here will run in UI thread
                    ...
                }
            });

    }   
});

저는 이것을 할 수 있는 일종의 해킹을 가지고 있습니다.소프트 키보드가 언제 표시되거나 숨겨졌는지 감지할 수 있는 방법은 없는 것처럼 보이지만 실제로는 다음을 설정하여 표시되거나 숨겨지려고 하는 시점을 감지할 수 있습니다.OnFocusChangeListener에서EditText당신이 듣고 있는 것.

EditText et = (EditText) findViewById(R.id.et);
et.setOnFocusChangeListener(new View.OnFocusChangeListener()
    {
        @Override
        public void onFocusChange(View view, boolean hasFocus)
        {
            //hasFocus tells us whether soft keyboard is about to show
        }
    });

참고: 이 해킹으로 한 가지 주의할 점은 이 콜백이 다음과 같은 경우 즉시 실행된다는 것입니다.EditText집중력을 얻거나 잃습니다.이는 실제로 소프트 키보드가 표시되거나 숨기기 직전에 실행됩니다.키보드를 표시하거나 숨긴 후에 작업을 수행하는 가장 좋은 방법은Handler다음과 같이 ~400ms의 지연 시간을 갖습니다.

EditText et = (EditText) findViewById(R.id.et);
et.setOnFocusChangeListener(new View.OnFocusChangeListener()
    {
        @Override
        public void onFocusChange(View view, boolean hasFocus)
        {
            new Handler().postDelayed(new Runnable()
                {
                    @Override
                    public void run()
                    {
                        //do work here
                    }
                }, 400);
        }
    });

샌더, 당신은 소프트 키보드로 차단된 뷰를 보여주려고 하는 것 같습니다.이 http://android-developers.blogspot.com/2009/04/updating-applications-for-on-screen.html 을 사용해 보십시오.

이 페이지에서 가장 많이 업데이트된 솔루션이 언급하고 있음에도 불구하고, Android 21까지 작동하는 setWindowInsets Animation Callback의 ViewComp 버전이 있습니다.

이제, 이 솔루션의 접근 방식은 21년 전으로 거슬러 올라갑니다.

출처: https://developer.android.com/reference/androidx/core/view/ViewCompat#setWindowInsetsAnimationCallback(android.view.View,androidx.core.view.WindowInsetsAnimationCompat.Callback)

저는 한 줄 텍스트 뷰 백 코딩 문제를 해결했습니다.

package com.helpingdoc;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;

public class MainSearchLayout extends LinearLayout {
    int hieght = 0;
    public MainSearchLayout(Context context, AttributeSet attributeSet) {

        super(context, attributeSet);
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        inflater.inflate(R.layout.main, this);


    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        Log.d("Search Layout", "Handling Keyboard Window shown");
       if(getHeight()>hieght){
           hieght = getHeight();
       }
        final int proposedheight = MeasureSpec.getSize(heightMeasureSpec);
        final int actualHeight = getHeight();
        System.out.println("....hieght = "+ hieght);
        System.out.println("....actualhieght = "+ actualHeight);
        System.out.println("....proposedheight = "+ proposedheight);
        if (actualHeight > proposedheight){
            // Keyboard is shown


        } else if(actualHeight<proposedheight){
            // Keyboard is hidden

        }

        if(proposedheight == hieght){
             // Keyboard is hidden
        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}

또한 첫 번째 DecorView의 하위 하단 패딩을 확인할 수 있습니다.키보드가 표시되면 0이 아닌 값으로 설정됩니다.

@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    View view = getRootView();
    if (view != null && (view = ((ViewGroup) view).getChildAt(0)) != null) {
        setKeyboardVisible(view.getPaddingBottom() > 0);
    }
    super.onLayout(changed, left, top, right, bottom);
}

@Filipkowicz의 위 답변은 Android API < 30에서 잘 작동합니다.Android API 30 이후로 우리는 사용해야 합니다.setWindowInsetsAnimationCallback그래서 아래 답변은 API 21 - 30을 작동하기 위해 두 가지 방법을 결합한 것입니다.

private fun isKeyboardVisible(insets: WindowInsets): Boolean {
    val insetsCompat = WindowInsetsCompat.toWindowInsetsCompat(insets)
    val systemWindow = insetsCompat.systemWindowInsets
    val rootStable = insetsCompat.stableInsets
    if (systemWindow.bottom > rootStable.bottom) {
        // This handles the adjustResize case on < API 30, since
        // systemWindow.bottom is probably going to be the IME
        return true
    }
    return false
}

@JvmStatic
@BindingAdapter("goneWhenKeyboardVisible")
fun View.goneWhenKeyboardVisible() {
    if (isRPlus()) {
        setWindowInsetsAnimationCallback(object :
            WindowInsetsAnimation.Callback(DISPATCH_MODE_STOP) {
            override fun onProgress(
                insets: WindowInsets,
                runningAnimations: MutableList<WindowInsetsAnimation>
            ): WindowInsets {
                return insets
            }

            override fun onStart(
                animation: WindowInsetsAnimation,
                bounds: WindowInsetsAnimation.Bounds
            ): WindowInsetsAnimation.Bounds {
                if (isVisible)
                    isVisible = !rootWindowInsets.isVisible(WindowInsets.Type.ime())
                return super.onStart(animation, bounds)
            }

            override fun onEnd(animation: WindowInsetsAnimation) {
                super.onEnd(animation)
                if (!isVisible)
                    isVisible = !rootWindowInsets.isVisible(WindowInsets.Type.ime())
            }
        })
    } else {
        setOnApplyWindowInsetsListener { _, insets ->
            isVisible = !isKeyboardVisible(insets)
            insets
        }
    }
}

숨기기 |키보드 이벤트 표시는 OnGlobalLayoutListener의 간단한 해킹을 통해 들을 수 있습니다.

 final View activityRootView = findViewById(R.id.top_root);
        activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
            public void onGlobalLayout() {
                int heightDiff = activityRootView.getRootView().getHeight() - activityRootView.getHeight();

                if (heightDiff > 100) {
                    // keyboard is up
                } else {
                    // keyboard is down
                }
            }
        });

여기 activityRootView는 활동의 루트 보기입니다.

보기 사용키보드 이벤트를 쉽게 가져올 수 있는 TreeObserver입니다.

layout_parent.viewTreeObserver.addOnGlobalLayoutListener {
            val r = Rect()
            layout_parent.getWindowVisibleDisplayFrame(r)
            if (layout_parent.rootView.height - (r.bottom - r.top) > 100) { // if more than 100 pixels, its probably a keyboard...
                Log.e("TAG:", "keyboard open")
            } else {
                Log.e("TAG:", "keyboard close")
            }
        }

layout_parent는 다음과 같은 보기입니다.edit_text.parent

키보드가 보일 때 보기를 숨기기 위해 간단한 바인딩을 만들었습니다.솔루션은 다음을 위한 현재 AndroidX 구현을 기반으로 합니다.WindowInsetsCompat아직 베타(208x 코어 1.5)에 있음 - 출처

private fun isKeyboardVisible(insets: WindowInsets): Boolean {
    val insetsCompat = WindowInsetsCompat.toWindowInsetsCompat(insets)
    val systemWindow = insetsCompat.systemWindowInsets
    val rootStable = insetsCompat.stableInsets
    if (systemWindow.bottom > rootStable.bottom) {
        // This handles the adjustResize case on < API 30, since
        // systemWindow.bottom is probably going to be the IME
        return true
    }
    return false
}

@BindingAdapter("goneWhenKeyboardVisible")
fun View.goneWhenKeyboardVisible(enabled: Boolean) {
    if (enabled) {
        setOnApplyWindowInsetsListener { view, insets ->
            visibility = if (isKeyboardVisible(insets)) GONE else VISIBLE
            insets
        }
    } else {
        setOnApplyWindowInsetsListener(null)
        visibility = VISIBLE
    }
}

용도:

<FrameLayout
                android:id="@+id/bottom_toolbar"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                app:goneWhenKeyboardVisible="@{true}"
                />

Kotlin 사용자의 경우, 이것은 댓글에 있는 다음 답변에서 영감을 받아 확장을 만들 수 있습니다.

import android.graphics.Rect
import android.view.View
import android.widget.TextView

const val SOFT_KEYBOARD_HEIGHT = 100

fun TextView.addOnKeyboardVisibilityListener(
    onKeyboardShown: () -> Unit,
    onKeyboardHidden: () -> Unit,
) {
    viewTreeObserver.addOnGlobalLayoutListener {
        if(rootView.isKeyboardShown()) {
            onKeyboardShown()
        } else {
            onKeyboardHidden()
        }
    }
}

fun View.isKeyboardShown(): Boolean =
    Rect().let { rect ->
        rootView.getWindowVisibleDisplayFrame(rect)
        rect
    }.let {
        rootView.bottom - it.bottom
    }.let { heightDiff ->
        heightDiff > SOFT_KEYBOARD_HEIGHT * rootView.resources.displayMetrics.density
    }

다음과 같이 사용할 수 있습니다.

editText.addOnKeyboardVisibilityListener(
    onKeyboardShown = {
        // TODO
    },
    onKeyboardHidden = {
        // TODO
    }
)

Nebojsa Tomcic의 대답은 나에게 도움이 되지 않았습니다.있습니다RelativeLayout와 함께TextView그리고.AutoCompleteTextView 합 니 다 야 해 스 롤 ▁the 합 다 ▁inside 니 ▁i ▁to ▁scroll ▁need 안 그스 크TextView키보드가 표시될 때와 숨길 때 아래쪽으로 이동합니다.이를 위해 오버로드했습니다.onLayout방법과 그것은 나에게 잘 작동합니다.

public class ExtendedLayout extends RelativeLayout
{
    public ExtendedLayout(Context context, AttributeSet attributeSet)
    {
        super(context, attributeSet);
        LayoutInflater inflater = (LayoutInflater)
                context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        inflater.inflate(R.layout.main, this);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b)
    {
        super.onLayout(changed, l, t, r, b);

        if (changed)
        {
            int scrollEnd = (textView.getLineCount() - textView.getHeight() /
                textView.getLineHeight()) * textView.getLineHeight();
            textView.scrollTo(0, scrollEnd);
        }
    }
}

언급URL : https://stackoverflow.com/questions/4312319/how-to-capture-the-virtual-keyboard-show-hide-event-in-android

반응형