แป้นพิมพ์อ่อนเปิดและปิดผู้ฟังในกิจกรรมใน Android


141

ฉันมีActivityที่ที่มี 5 EditTextวินาที เมื่อผู้ใช้คลิกที่ปุ่มแรกEditTextแป้นพิมพ์แบบอ่อนจะเปิดขึ้นเพื่อป้อนค่าบางอย่างในนั้น ฉันต้องการตั้งค่าViewการมองเห็นของผู้อื่นเป็นGoneเมื่อแป้นพิมพ์อ่อนเปิดขึ้นและเมื่อผู้ใช้คลิกที่EditTextแป้นแรกและเมื่อแป้นพิมพ์อ่อนปิดลงจากเดิมEditTextเมื่อกดปุ่มย้อนกลับ จากนั้นฉันต้องการตั้งค่าViewการเปิดเผยของคนอื่นให้มองเห็นได้

มีผู้ฟังหรือโทรกลับหรือแฮ็คเมื่อคีย์บอร์ดนุ่มเปิดขึ้นจากการคลิกครั้งแรกEditTextใน Android หรือไม่?


1
ไม่ไม่มีผู้ฟังดังกล่าว มีเป็นแฮ็กเพื่อให้บรรลุสิ่งที่คุณกำลังพยายามที่จะ นี่คือวิธีการที่เป็นไปได้: วิธีการส่งออกเหตุการณ์ชี้ใน Android
Vikram

@Vikram ฉันไม่ได้มองหาtrying to detect the virtual keyboard height in Android.
N Sharma

ฉันรู้ว่า. หากคุณอ่านรหัสคุณจะเห็นว่ามีการกำหนดความสูงอย่างไร กำลังส่งเหตุการณ์ตัวชี้ -> สองกรณี => 1 หากแป้นพิมพ์เปิด => & ถ้าตัวชี้XและYตำแหน่งอยู่บน / เหนือแป้นพิมพ์ => SecurityException=> ลดลงYและลองอีกครั้ง => จนกว่าจะไม่มีข้อยกเว้น => Yค่าปัจจุบันคือความสูงของแป้นพิมพ์ 2. ถ้าแป้นพิมพ์ไม่ได้เปิด => SecurityExceptionไม่มี
Vikram

นำไปใช้กับสถานการณ์ของคุณอย่างไร? ส่งเหตุการณ์ตัวชี้ที่สมมติว่า 2/3 ของความสูงของหน้าจอ หากSecurityExceptionแป้นพิมพ์ถูกโยน => เปิดอยู่ มิฉะนั้นแป้นพิมพ์จะปิด
Vikram

@Vikram ฉันเพียงอยากให้เรื่องนี้เป็นครั้งแรกไม่ได้อื่น ๆEditText EditTextฉันจะแยกแยะสิ่งนี้ได้อย่างไร?
N Sharma

คำตอบ:


90

จะใช้ได้เฉพาะเมื่อandroid:windowSoftInputModeกิจกรรมของคุณถูกตั้งค่าเป็นadjustResizeในไฟล์ Manifest คุณสามารถใช้ตัวฟังเค้าโครงเพื่อดูว่าแป้นพิมพ์ปรับขนาดโครงร่างรูทของกิจกรรมของคุณหรือไม่

ฉันใช้คลาสพื้นฐานต่อไปนี้สำหรับกิจกรรมของฉัน:

public class BaseActivity extends Activity {
    private ViewTreeObserver.OnGlobalLayoutListener keyboardLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            int heightDiff = rootLayout.getRootView().getHeight() - rootLayout.getHeight();
            int contentViewTop = getWindow().findViewById(Window.ID_ANDROID_CONTENT).getTop();

            LocalBroadcastManager broadcastManager = LocalBroadcastManager.getInstance(BaseActivity.this);

            if(heightDiff <= contentViewTop){
                onHideKeyboard();

                Intent intent = new Intent("KeyboardWillHide");
                broadcastManager.sendBroadcast(intent);
            } else {
                int keyboardHeight = heightDiff - contentViewTop;
                onShowKeyboard(keyboardHeight);

                Intent intent = new Intent("KeyboardWillShow");
                intent.putExtra("KeyboardHeight", keyboardHeight);
                broadcastManager.sendBroadcast(intent);
            }
        }
    };

    private boolean keyboardListenersAttached = false;
    private ViewGroup rootLayout;

    protected void onShowKeyboard(int keyboardHeight) {}
    protected void onHideKeyboard() {}

    protected void attachKeyboardListeners() {
        if (keyboardListenersAttached) {
            return;
        }

        rootLayout = (ViewGroup) findViewById(R.id.rootLayout);
        rootLayout.getViewTreeObserver().addOnGlobalLayoutListener(keyboardLayoutListener);

        keyboardListenersAttached = true;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        if (keyboardListenersAttached) {
            rootLayout.getViewTreeObserver().removeGlobalOnLayoutListener(keyboardLayoutListener);
        }
    }
}

กิจกรรมตัวอย่างต่อไปนี้ใช้สิ่งนี้เพื่อซ่อนมุมมองเมื่อแป้นพิมพ์ปรากฏขึ้นและแสดงอีกครั้งเมื่อแป้นพิมพ์ถูกซ่อน

เค้าโครง xml:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:id="@+id/rootLayout"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical">              

    <ScrollView
        android:id="@+id/scrollView"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        >

        <!-- omitted for brevity -->

    </ScrollView>

    <LinearLayout android:id="@+id/bottomContainer"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        >

        <!-- omitted for brevity -->

    </LinearLayout>

</LinearLayout>

และกิจกรรม:

public class TestActivity extends BaseActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.test_activity);

        attachKeyboardListeners();
    }

    @Override
    protected void onShowKeyboard(int keyboardHeight) {
        // do things when keyboard is shown
        bottomContainer.setVisibility(View.GONE);
    }

    @Override
    protected void onHideKeyboard() {
        // do things when keyboard is hidden
        bottomContainer.setVisibility(View.VISIBLE);
    }        
}

4
+1 ใช่นี่คือทางออกที่สมบูรณ์แบบสำหรับปัญหาของฉัน
N Sharma

20
สวัสดีคุณใช้ getTop () บน Window.ID_ANDROID_CONTENT Get top ไม่ได้ผลสำหรับฉัน มันจะเป็น 0 เสมอมันทำงานเหมือนที่ควรจะใช้ getHeight () แทน
Daniele Segato

1
คุณได้รับrootLayout = (ViewGroup) findViewById(R.id.rootLayout);จากที่ไหน?
CommonSenseCode

1
ไม่ทำงานสำหรับฉันด้วยเหตุผลบางอย่างมันมักจะเรียก onShowKeyboard ไม่ว่าฉันจะเปิดหรือปิดก็ตาม ฉันใช้ findViewById (android.R.id.content) นั่นอาจเป็นปัญหา?
McSullivan D'And

3
@tsig โซลูชัน +100 ของคุณขึ้นอยู่กับหน้าจอเฉพาะ ล้มเหลวบนแท็บเล็ตและโทรศัพท์ hdpi ฉันใช้การแก้ไขเป็นสิบเปอร์เซ็นต์ของความสูงของอุปกรณ์ นั่นหมายความว่าหากความสูงของมุมมองต่ำกว่า screenHeight - 10% แป้นพิมพ์เปิดอยู่ แป้นพิมพ์อื่นปิดอยู่ นี่คือ contentViewTop ของฉันใน onGlobalLayout: contentViewTop = (getWindow (). getDecorView (). getBottom () / 10)
ilker

100

เค้กที่มี ไลบรารี KeyboardVisibilityEvent ที่ยอดเยี่ยม

KeyboardVisibilityEvent.setEventListener(
    getActivity(),
    new KeyboardVisibilityEventListener() {
        @Override
        public void onVisibilityChanged(boolean isOpen) {
            // write your code
        }
    });

เครดิตสำหรับ Yasuhiro SHIMIZU


1
วิธีนี้ใช้ไม่ได้เนื่องจากแป้นพิมพ์ไม่มีความสูงคงที่และความสูงในไลบรารีนี้ตั้งไว้ที่ 100dp
milosmns

12
มันยังยากรหัส หลายหน้าต่าง? ซัมซุงแยกมุมมอง? ภาพในโหมดภาพ? นอกจากนี้ยังมีคีย์บอร์ดแบบแถวเดียวที่น้อยที่สุดที่จะร้อง 100dp ที่นี่ไม่มีกระสุนเงิน ...
milosmns

1
เนื่องจากไม่มีปัญหาทั้งหมดสำหรับปัญหานี้ดูเหมือนว่าจะเป็นวิธีที่ง่ายที่สุดในการนำไปใช้และกลับไปที่รหัสที่คุณต้องการใช้งานจริง :)
Machine Tribe

1
นี่เป็นคำตอบที่ดีที่สุดเชื่อถือได้โดยสิ้นเชิงกับทุกอุปกรณ์
Pelanes

1
@TimCastelijns จากประสบการณ์ของฉันฉันได้ลองใช้รูปแบบต่างๆและนี่คือรูปแบบที่ทำงานได้ดีขึ้นในอุปกรณ์ส่วนใหญ่ อาจจะไม่สมบูรณ์แบบ แต่ฉันมีปัญหามากมายกับฟีเจอร์นี้ใน Nexus 5X และอุปกรณ์ Nexus อื่น ๆ และมันก็ทำงานได้อย่างสมบูรณ์แบบ
Pelanes

70

ดังที่ Vikram ชี้ให้เห็นในความคิดเห็นการตรวจจับว่าซอฟต์คีย์แสดงหรือหายไปนั้นเป็นไปได้เฉพาะกับแฮ็กที่น่าเกลียดเท่านั้น

อาจจะเพียงพอที่จะตั้งผู้ฟังโฟกัสในข้อความแก้ไข :

yourEditText.setOnFocusChangeListener(new OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
        if (hasFocus) {
            //got focus
        } else {
            //lost focus
        }
   }
});

32
สมมติว่าฉันคลิกที่ข้อความแก้ไขแล้วมันsetOnFocusChangeListenerจะถูกเรียกว่าฟังจากนั้นฉันกดย้อนกลับไปแล้วมันจะปิดแป้นพิมพ์และ แต่ไม่ได้คลิกที่มุมมองอื่นตอนนี้ฉันคลิกที่ข้อความแก้ไขเดียวกันอีกครั้งซึ่งได้โฟกัสแล้วจะเกิดอะไรขึ้น?
N Sharma

3
@ วิลเลียมส์ฉันไม่แน่ใจทั้งหมด แต่ฉันสงสัยว่าonFocusChange()จะไม่ถูกเรียก
Manuel Allenspach

1
นี่ไม่ใช่คำถามของฉัน โปรดอ่านคำถามของฉันอีกครั้ง - ฉันมีกิจกรรมที่มี 5 EditText เมื่อผู้ใช้คลิกที่ EditText แรกจากนั้นคีย์บอร์ดนุ่มเปิดขึ้นเพื่อป้อนค่าบางอย่างในนั้น ฉันต้องการตั้งค่าการมองเห็นมุมมองอื่น ๆ เป็น Gone เมื่อซอฟต์คีย์บอร์ดเปิดขึ้นเมื่อผู้ใช้คลิกที่ EditText แรกและเมื่อคีย์บอร์ดนุ่มปิดจาก EditText เดียวกันเมื่อกดย้อนกลับฉันต้องการตั้งค่าการมองเห็นอื่น ๆ ให้มองเห็นได้ มีผู้ฟังหรือโทรกลับหรือแฮ็คเมื่อซอฟต์คีย์บอร์ดเปิดขึ้นเมื่อคลิกที่ EditText แรกใน Android หรือไม่?
N Sharma

4
ผู้ชายไม่มองคำตอบนี้เพราะเขากำลังบอกสิ่งที่แตกต่างออกไปแม้ว่าฉันจะไม่เข้าใจก็ตาม
N Sharma

2
อย่างไรก็ตามมันไม่ได้ผลสำหรับฉัน ... เมื่อซ่อนแป้นพิมพ์แบบนุ่มไม่มีการเปลี่ยนแปลงโฟกัสใด ๆ เกิดขึ้นใน EditText ... ดังนั้นฉันจึงไม่ได้รับการแจ้งเตือนจาก Listener นี้
Licat Julius

52

สำหรับกิจกรรม:

    final View activityRootView = findViewById(R.id.activityRoot);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                Rect r = new Rect();

                activityRootView.getWindowVisibleDisplayFrame(r);

                int heightDiff = view.getRootView().getHeight() - (r.bottom - r.top);
                if (heightDiff > 100) { 
                 //enter your code here
                }else{
                 //enter code for hid
                }
            }
        });

สำหรับ Fragment:

    view = inflater.inflate(R.layout.live_chat_fragment, null);
view.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.
                view.getWindowVisibleDisplayFrame(r);

                int heightDiff = view.getRootView().getHeight() - (r.bottom - r.top);
                if (heightDiff > 500) { // if more than 100 pixels, its probably a keyboard...

                }
            }
        });

3
ใช้สำหรับกิจกรรม แต่แทนที่จะเปรียบเทียบกับมุมมองฉันเทียบกับขนาดหน้าจอ ใช้งานได้ดี
Roee

จะเป็นการดีกว่าที่จะเปรียบเทียบ heightDiff กับความสูงเป็น dp แทนที่จะเป็นพิกเซล อาจแตกต่างกันอย่างมีนัยสำคัญ
Leo Droidcoder

สิ่งนี้ต้องการandroid:windowSoftInputMode="adjustResize"ในรายการหรือไม่?
LiuWenbin_NO

android: windowSoftInputMode = "adjustmentResize" android: configChanges = "orientation | keyboard | keyboardHidden"
M Singh Karnawat

มันได้ผลสำหรับฉันฉันยังคงมีคำถาม มีค่าใช้จ่ายจำนวนมากหรือไม่?
Licat Julius

34

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

ชอบมาก:

    private ViewTreeObserver.OnGlobalLayoutListener keyboardLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        // navigation bar height
        int navigationBarHeight = 0;
        int resourceId = getResources().getIdentifier("navigation_bar_height", "dimen", "android");
        if (resourceId > 0) {
            navigationBarHeight = getResources().getDimensionPixelSize(resourceId);
        }

        // status bar height
        int statusBarHeight = 0;
        resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            statusBarHeight = getResources().getDimensionPixelSize(resourceId);
        }

        // display window size for the app layout
        Rect rect = new Rect();
        getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);

        // screen height - (user app height + status + nav) ..... if non-zero, then there is a soft keyboard
        int keyboardHeight = rootLayout.getRootView().getHeight() - (statusBarHeight + navigationBarHeight + rect.height());

        if (keyboardHeight <= 0) {
            onHideKeyboard();
        } else {
            onShowKeyboard(keyboardHeight);
        }
    }
};

ดูเหมือนว่าจะทำงานได้ดีโดยมีข้อยกเว้นอย่างหนึ่งคือแบ่งในโหมดแบ่งหน้าจอ ไม่งั้นก็เยี่ยม
MCLLC

17

คุณสามารถลอง:

private void initKeyBoardListener() {
    // Минимальное значение клавиатуры. 
    // Threshold for minimal keyboard height.
    final int MIN_KEYBOARD_HEIGHT_PX = 150;
    // Окно верхнего уровня view. 
    // Top-level window decor view.
    final View decorView = getWindow().getDecorView();
    // Регистрируем глобальный слушатель. Register global layout listener.
    decorView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        // Видимый прямоугольник внутри окна. 
        // Retrieve visible rectangle inside window.
        private final Rect windowVisibleDisplayFrame = new Rect();
        private int lastVisibleDecorViewHeight;

        @Override
        public void onGlobalLayout() {
            decorView.getWindowVisibleDisplayFrame(windowVisibleDisplayFrame);
            final int visibleDecorViewHeight = windowVisibleDisplayFrame.height();

            if (lastVisibleDecorViewHeight != 0) {
                if (lastVisibleDecorViewHeight > visibleDecorViewHeight + MIN_KEYBOARD_HEIGHT_PX) {
                    Log.d("Pasha", "SHOW");
                } else if (lastVisibleDecorViewHeight + MIN_KEYBOARD_HEIGHT_PX < visibleDecorViewHeight) {
                    Log.d("Pasha", "HIDE");
                }
            }
            // Сохраняем текущую высоту view до следующего вызова.
            // Save current decor view height for the next call.
            lastVisibleDecorViewHeight = visibleDecorViewHeight;
        }
    });
}

1
Spasibo, Dolbik! :)
AlexS

5

รหัสด้านล่างใช้งานได้สำหรับฉัน

mainLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            if (mainLayout != null) {
                int heightDiff = mainLayout.getRootView().getHeight() - mainLayout.getHeight();
                if (heightDiff > dpToPx(getActivity(), 200)) { 
                   //keyboard is open
                } else {
                   //keyboard is hide
                }
            }
        }
    });

mainLayout คืออะไร? และ heightDiff เป็น 0 เสมอเมื่อข้อความยื่นด้านบนของมุมมอง
Md Imran Choudhury

4

คุณสามารถใช้ฟังก์ชันส่วนขยาย Rx ของฉัน (Kotlin)

/**
 * @return [Observable] to subscribe of keyboard visibility changes.
 */
fun AppCompatActivity.keyboardVisibilityChanges(): Observable<Boolean> {

    // flag indicates whether keyboard is open
    var isKeyboardOpen = false

    val notifier: BehaviorSubject<Boolean> = BehaviorSubject.create()

    // approximate keyboard height
    val approximateKeyboardHeight = dip(100)

    // device screen height
    val screenHeight: Int = getScreenHeight()

    val visibleDisplayFrame = Rect()

    val viewTreeObserver = window.decorView.viewTreeObserver

    val onDrawListener = ViewTreeObserver.OnDrawListener {

        window.decorView.getWindowVisibleDisplayFrame(visibleDisplayFrame)

        val keyboardHeight = screenHeight - (visibleDisplayFrame.bottom - visibleDisplayFrame.top)

        val keyboardOpen = keyboardHeight >= approximateKeyboardHeight

        val hasChanged = isKeyboardOpen xor keyboardOpen

        if (hasChanged) {
            isKeyboardOpen = keyboardOpen
            notifier.onNext(keyboardOpen)
        }
    }

    val lifeCycleObserver = object : GenericLifecycleObserver {
        override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event?) {
            if (source.lifecycle.currentState == Lifecycle.State.DESTROYED) {
                viewTreeObserver.removeOnDrawListener(onDrawListener)
                source.lifecycle.removeObserver(this)
                notifier.onComplete()
            }
        }
    }

    viewTreeObserver.addOnDrawListener(onDrawListener)
    lifecycle.addObserver(lifeCycleObserver)

    return notifier
            .doOnDispose {
                viewTreeObserver.removeOnDrawListener(onDrawListener)
                lifecycle.removeObserver(lifeCycleObserver)
            }
            .onTerminateDetach()
            .hide()
}

ตัวอย่าง:

(context as AppCompatActivity)
                    .keyboardVisibilityChanges()
                    .subscribeBy { isKeyboardOpen ->
                        // your logic
                    }

ไม่ได้ผลสำหรับฉัน ไม่พบวิธีการdip()และgetScreenHeight()
Marcin Kunert

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

GenericLifecycleObserver เลิกใช้แล้ว? วิธีแก้ปัญหาใด ๆ
Zainal Fahrudin

2

หากทำได้ให้ลองขยาย EditText และแทนที่เมธอด 'onKeyPreIme'

@Override
public void setOnEditorActionListener(final OnEditorActionListener listener) {
    mEditorListener = listener; //keep it for later usage
    super.setOnEditorActionListener(listener);
}

@Override
public boolean onKeyPreIme(final int keyCode, final KeyEvent event) {
    if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
        if (mEditorListener != null) {
            //you can define and use custom listener,
            //OR define custom R.id.<imeId>
            //OR check event.keyCode in listener impl
            //* I used editor action because of ButterKnife @
            mEditorListener.onEditorAction(this, android.R.id.closeButton, event);
        }
    }
    return super.onKeyPreIme(keyCode, event);
}

คุณจะขยายได้อย่างไร:

  1. ใช้งาน onFocus ฟังและประกาศ 'onKeyboardShown'
  2. ประกาศ 'onKeyboardHidden'

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


2

วิธีนี้จะได้ผลโดยไม่จำเป็นต้องเปลี่ยนกิจกรรมของคุณ android:windowSoftInputMode

ขั้นตอนที่ 1: ขยายคลาส EditText และแทนที่สองสิ่งนี้:

@Override
public void setOnEditorActionListener(final OnEditorActionListener listener) {
    mEditorListener = listener;
    super.setOnEditorActionListener(listener);
}

@Override
public boolean onKeyPreIme(final int keyCode, final KeyEvent event) {
    if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
        if (mEditorListener != null) {
            mEditorListener.onEditorAction(this, android.R.id.closeButton, event);
        }
    }
    return super.onKeyPreIme(keyCode, event);
}

ขั้นตอนที่ 2: สร้างสองสิ่งนี้ในกิจกรรมของคุณ:

private void initKeyboard() {
    final AppEditText editText = findViewById(R.id.some_id);
    editText.setOnFocusChangeListener(new OnFocusChangeListener() {
        @Override
        public void onFocusChange(View v, boolean hasFocus) {
            setKeyboard(hasFocus);
        }
    });
    editText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
        @Override
        public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
            if (event == null || event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
                editText.clearFocus();
            }
            return false;
        }
    });
}

public void setKeyboard(boolean isShowing) {
    // do something
}

*** จำไว้ว่าในการclearFocusทำงานคุณต้องกำหนดให้พาเรนต์หรือลูกคนแรกในลำดับชั้นพาเรนต์โฟกัสได้

    setFocusableInTouchMode(true);
    setFocusable(true);

ทำให้ editText แบบกำหนดเองเป็นทางออกที่ง่ายที่สุด!
Kebab Krabby

1
public class MainActivity extends BaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.mainactivity);
    attachKeyboardListeners();
    ....
    yourEditText1.setOnFocusChangeListener(new OnFocusChangeListener() {
    @Override
    public void onFocusChange(View v, boolean hasFocus) {
            if (hasFocus) {
                yourEditText2.setVisibility(View.GONE);
                yourEditText3.setVisibility(View.GONE);
                yourEditText4.setVisibility(View.GONE);
                yourEditText5.setVisibility(View.GONE);
            } else {
                yourEditText2.setVisibility(View.VISIBLE);
                yourEditText3.setVisibility(View.VISIBLE);
                yourEditText4.setVisibility(View.VISIBLE);
                yourEditText5.setVisibility(VISIBLE);
            }
       }
    });
    }
}

สมมติว่าฉันคลิกที่ข้อความแก้ไขแล้วมันsetOnFocusChangeListenerจะถูกเรียกว่าฟังจากนั้นฉันกดย้อนกลับไปแล้วมันจะปิดแป้นพิมพ์และ แต่ไม่ได้คลิกที่มุมมองอื่นตอนนี้ฉันคลิกที่ข้อความแก้ไขเดียวกันอีกครั้งซึ่งได้โฟกัสแล้วจะเกิดอะไรขึ้น?
N Sharma

นี่ไม่ใช่คำถามของฉัน โปรดอ่านคำถามของฉันอีกครั้ง - ฉันมีกิจกรรมที่มี 5 EditText เมื่อผู้ใช้คลิกที่ EditText แรกจากนั้นคีย์บอร์ดนุ่มเปิดขึ้นเพื่อป้อนค่าบางอย่างในนั้น ฉันต้องการตั้งค่าการมองเห็นมุมมองอื่น ๆ เป็น Gone เมื่อซอฟต์คีย์บอร์ดเปิดขึ้นเมื่อผู้ใช้คลิกที่ EditText แรกและเมื่อคีย์บอร์ดนุ่มปิดจาก EditText เดียวกันเมื่อกดย้อนกลับฉันต้องการตั้งค่าการมองเห็นมุมมองอื่น ๆ ให้มองเห็นได้ มีผู้ฟังหรือโทรกลับหรือแฮ็คเมื่อซอฟต์คีย์บอร์ดเปิดขึ้นเมื่อคลิกที่ EditText แรกใน Android หรือไม่?
N Sharma

1
เมื่อคุณกดย้อนกลับมันจะปิดแป้นพิมพ์เวลาที่onfocusผู้ฟังไม่เคยโทรนั่นคือฉันกำลังมองหาสิ่งที่คุณไม่แนะนำ
N Sharma

1

ใช้คลาสนี้

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;

public class SoftKeyboard implements View.OnFocusChangeListener
{
private static final int CLEAR_FOCUS = 0;

private ViewGroup layout;
private int layoutBottom;
private InputMethodManager im;
private int[] coords;
private boolean isKeyboardShow;
private SoftKeyboardChangesThread softKeyboardThread;
private List<EditText> editTextList;

private View tempView; // reference to a focused EditText

public SoftKeyboard(ViewGroup layout, InputMethodManager im)
{
    this.layout = layout;
    keyboardHideByDefault();
    initEditTexts(layout);
    this.im = im;
    this.coords = new int[2];
    this.isKeyboardShow = false;
    this.softKeyboardThread = new SoftKeyboardChangesThread();
    this.softKeyboardThread.start();
}

public void openSoftKeyboard()
{
    if(!isKeyboardShow)
    {
        layoutBottom = getLayoutCoordinates();
        im.toggleSoftInput(0, InputMethodManager.SHOW_IMPLICIT);
        softKeyboardThread.keyboardOpened();
        isKeyboardShow = true;
    }
}

public void closeSoftKeyboard()
{
    if(isKeyboardShow)
    {
        im.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0);
        isKeyboardShow = false;
    }
}

public void setSoftKeyboardCallback(SoftKeyboardChanged mCallback)
{
    softKeyboardThread.setCallback(mCallback);
}

public void unRegisterSoftKeyboardCallback()
{
    softKeyboardThread.stopThread();
}

public interface SoftKeyboardChanged 
{
    public void onSoftKeyboardHide();
    public void onSoftKeyboardShow();   
}

private int getLayoutCoordinates()
{
    layout.getLocationOnScreen(coords);
    return coords[1] + layout.getHeight();
}

private void keyboardHideByDefault()
{
    layout.setFocusable(true);
    layout.setFocusableInTouchMode(true);
}

/*
 * InitEditTexts now handles EditTexts in nested views
 * Thanks to Francesco Verheye (verheye.francesco@gmail.com)
 */
private void initEditTexts(ViewGroup viewgroup) 
{
    if(editTextList == null)
        editTextList = new ArrayList<EditText>();

    int childCount = viewgroup.getChildCount();
    for(int i=0; i<= childCount-1;i++) 
    {
        View v = viewgroup.getChildAt(i);

        if(v instanceof ViewGroup) 
        {
            initEditTexts((ViewGroup) v);
        }

        if(v instanceof EditText) 
        {
            EditText editText = (EditText) v;
            editText.setOnFocusChangeListener(this);
            editText.setCursorVisible(true);
            editTextList.add(editText);
        }
    }
}

/*
 * OnFocusChange does update tempView correctly now when keyboard is still shown
 * Thanks to Israel Dominguez (dominguez.israel@gmail.com)
 */
@Override
public void onFocusChange(View v, boolean hasFocus) 
{
    if(hasFocus) 
    {
        tempView = v;
        if(!isKeyboardShow) 
        {
            layoutBottom = getLayoutCoordinates();
            softKeyboardThread.keyboardOpened();
            isKeyboardShow = true;
        }
    }
}

// This handler will clear focus of selected EditText
private final Handler mHandler = new Handler()
{
    @Override
    public void handleMessage(Message m)
    {
        switch(m.what)
        {
        case CLEAR_FOCUS:
            if(tempView != null)
            {
                tempView.clearFocus();
                tempView = null;
            }
            break;
        }
    }
};

private class SoftKeyboardChangesThread extends Thread
{
    private AtomicBoolean started;
    private SoftKeyboardChanged mCallback;

    public SoftKeyboardChangesThread()
    {
        started = new AtomicBoolean(true);
    }

    public void setCallback(SoftKeyboardChanged mCallback)
    {
        this.mCallback = mCallback;
    }

    @Override
    public void run()
    {
        while(started.get())
        {
            // Wait until keyboard is requested to open
            synchronized(this)
            {
                try 
                {
                    wait();
                } catch (InterruptedException e) 
                {
                    e.printStackTrace();
                }
            }

            int currentBottomLocation = getLayoutCoordinates();

            // There is some lag between open soft-keyboard function and when it really appears.
            while(currentBottomLocation == layoutBottom && started.get())
            {
                currentBottomLocation = getLayoutCoordinates();
            }

            if(started.get())
                mCallback.onSoftKeyboardShow();

            // When keyboard is opened from EditText, initial bottom location is greater than layoutBottom
            // and at some moment equals layoutBottom.
            // That broke the previous logic, so I added this new loop to handle this.
            while(currentBottomLocation >= layoutBottom && started.get())
            {
                currentBottomLocation = getLayoutCoordinates();
            }

            // Now Keyboard is shown, keep checking layout dimensions until keyboard is gone
            while(currentBottomLocation != layoutBottom && started.get())
            {
                                    synchronized(this)
                {
                    try 
                    {
                        wait(500);
                    } catch (InterruptedException e) 
                    {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                currentBottomLocation = getLayoutCoordinates();
            }

            if(started.get())
                mCallback.onSoftKeyboardHide();

            // if keyboard has been opened clicking and EditText.
            if(isKeyboardShow && started.get())
                isKeyboardShow = false;

            // if an EditText is focused, remove its focus (on UI thread)
            if(started.get())
                mHandler.obtainMessage(CLEAR_FOCUS).sendToTarget();
        }   
    }

    public void keyboardOpened()
    {
        synchronized(this)
        {
            notify();
        }
    }

    public void stopThread()
    {
        synchronized(this)
        {
            started.set(false);
            notify();
        }
    }

}
}

ในAndroid Manifest, android:windowSoftInputMode="adjustResize"เป็นสิ่งที่จำเป็น

/*
Somewhere else in your code
*/
RelativeLayout mainLayout = findViewById(R.layout.main_layout); // You must use the layout root
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
}

@Override
public void onSoftKeyboardShow() {
    // Code here
}   
});

/*
Open or close the soft keyboard easily
*/
softKeyboard.openSoftKeyboard();
softKeyboard.closeSoftKeyboard();

/* Prevent memory leaks:*/
@Override
public void onDestroy() {
    super.onDestroy();
    softKeyboard.unRegisterSoftKeyboardCallback();
}

PS - นำมาจากที่นี่โดยสิ้นเชิง


1

สำหรับกรณีของadjustResizeและโซลูชันที่ยอมรับ FragmentActivity จาก @Jaap ไม่ได้ผลสำหรับฉัน

นี่คือทางออกของฉัน:

private ViewTreeObserver.OnGlobalLayoutListener keyboardLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
    private int contentDiff;
    private int rootHeight;
    @Override
    public void onGlobalLayout() {
        View contentView = getWindow().findViewById(Window.ID_ANDROID_CONTENT);
        if (rootHeight != mDrawerLayout.getRootView().getHeight()) {
            rootHeight = mDrawerLayout.getRootView().getHeight();
            contentDiff = rootHeight - contentView.getHeight();
            return;
        }
        int newContentDiff = rootHeight - contentView.getHeight();
        if (contentDiff != newContentDiff) {
            if (contentDiff < newContentDiff) {
                onShowKeyboard(newContentDiff - contentDiff);
            } else {
                onHideKeyboard();
            }
            contentDiff = newContentDiff;
        }
    }
};

1

วิธีอื่นคือตรวจสอบเมื่อผู้ใช้หยุดพิมพ์ ...

เมื่อ TextEdit อยู่ในโฟกัส (ผู้ใช้กำลัง / กำลังพิมพ์) คุณสามารถซ่อนมุมมอง (ตัวฟังโฟกัส)

และใช้ Handler + Runnable และตัวฟังการเปลี่ยนแปลงข้อความเพื่อปิดแป้นพิมพ์ (โดยไม่คำนึงถึงการมองเห็น) และแสดงมุมมองหลังจากล่าช้าไปบ้าง

สิ่งสำคัญที่ต้องระวังคือความล่าช้าที่คุณใช้ซึ่งจะขึ้นอยู่กับเนื้อหาของ TextEdits เหล่านี้

Handler timeoutHandler = new Handler();
Runnable typingRunnable = new Runnable() {
    public void run() {
        // current TextEdit
        View view = getCurrentFocus();

        InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        // reset focus
        view.clearFocus();
        // close keyboard (whether its open or not)
        imm.hideSoftInputFromWindow(view.getWindowToken(), InputMethodManager.RESULT_UNCHANGED_SHOWN);

        // SET VIEWS VISIBLE
    }
};

editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        if (hasFocus) {
            // SET VIEWS GONE

            // reset handler
            timeoutHandler.removeCallbacks(typingRunnable);
            timeoutHandler.postDelayed(typingRunnable, TYPING_TIMEOUT);
        }
    }
});

editText.addTextChangedListener(new TextWatcher() {
    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {}

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        // Reset Handler...
        timeoutHandler.removeCallbacks(typingRunnable);
    }

    @Override
    public void afterTextChanged(Editable s) {
        // Reset Handler Cont.
        if (editText.getText().toString().trim().length() > 0) {
            timeoutHandler.postDelayed(typingRunnable, TYPING_TIMEOUT);
        }
    }
});

1

รหัสนี้ใช้งานได้ดีมาก

ใช้คลาสนี้สำหรับมุมมองรูท:

public class KeyboardConstraintLayout extends ConstraintLayout {

private KeyboardListener keyboardListener;
private EditText targetEditText;
private int minKeyboardHeight;
private boolean isShow;

public KeyboardConstraintLayout(Context context) {
    super(context);
    minKeyboardHeight = getResources().getDimensionPixelSize(R.dimen.keyboard_min_height); //128dp
}

public KeyboardConstraintLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
    minKeyboardHeight = getResources().getDimensionPixelSize(R.dimen.keyboard_min_height); // 128dp
}

public KeyboardConstraintLayout(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    minKeyboardHeight = getResources().getDimensionPixelSize(R.dimen.keyboard_min_height); // 128dp
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    if (!isInEditMode()) {
        Activity activity = (Activity) getContext();
        @SuppressLint("DrawAllocation")
        Rect rect = new Rect();
        getWindowVisibleDisplayFrame(rect);

        int statusBarHeight = rect.top;
        int keyboardHeight = activity.getWindowManager().getDefaultDisplay().getHeight() - (rect.bottom - rect.top) - statusBarHeight;

        if (keyboardListener != null && targetEditText != null && targetEditText.isFocused()) {
            if (keyboardHeight > minKeyboardHeight) {
                if (!isShow) {
                    isShow = true;
                    keyboardListener.onKeyboardVisibility(true);
                }
            }else {
                if (isShow) {
                    isShow = false;
                    keyboardListener.onKeyboardVisibility(false);
                }
            }
        }
    }
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

public boolean isShowKeyboard() {
    return isShow;
}

public void setKeyboardListener(EditText targetEditText, KeyboardListener keyboardListener) {
    this.targetEditText = targetEditText;
    this.keyboardListener = keyboardListener;
}

public interface KeyboardListener {
    void onKeyboardVisibility (boolean isVisible);
}

}

และตั้งค่าตัวฟังคีย์บอร์ดในกิจกรรมหรือส่วน:

        rootLayout.setKeyboardListener(targetEditText, new KeyboardConstraintLayout.KeyboardListener() {
        @Override
        public void onKeyboardVisibility(boolean isVisible) {

        }
    });

1

คุณสามารถจัดการการมองเห็นแป้นพิมพ์ได้โดยการลบล้างสองวิธีในกิจกรรมของคุณ: onKeyUp()และonKeyDown()ข้อมูลเพิ่มเติมในลิงค์นี้: https://developer.android.com/training/keyboard-input/commands


1
เอกสารระบุอย่างชัดเจนว่าไม่ควรใช้ฟังก์ชันนี้ในการอ้างอิงถึงแป้นพิมพ์ซอฟต์อินพุต
Piotr Prus

0

น่าเสียดายที่ฉันไม่มีชื่อเสียงสูงพอที่จะแสดงความคิดเห็นเกี่ยวกับคำตอบของ Jaap van Hengstum แต่ผมอ่านไม่กี่ความคิดเห็นของคนที่มีปัญหาที่contentViewTopอยู่เสมอ0และที่ว่าonShowKeyboard(...)เรียกว่าเสมอ

ฉันมีปัญหาเดียวกันและพบปัญหาที่ฉันมี ผมใช้AppCompatActivityแทน Activity'ปกติ' ในกรณีนี้Window.ID_ANDROID_CONTENTหมายถึงContentFrameLayoutและไม่ใช่FrameLayoutกับค่าบนสุดด้านขวา ในกรณีของฉันมันเป็นเรื่องปกติที่จะใช้ 'ปกติ' Activityถ้าคุณต้องใช้ประเภทกิจกรรมอื่น (ฉันเพิ่งทดสอบAppCompatActivityอาจเป็นปัญหากับ acitivy ประเภทอื่น ๆ เช่นFragmentActivity) คุณต้องเข้าถึงFrameLayoutซึ่งก็คือ บรรพบุรุษของContentFrameLayout.


0

เมื่อคีย์บอร์ดแสดง

rootLayout.getHeight() < rootLayout.getRootView().getHeight() - getStatusBarHeight() 

เป็นความจริงอย่างอื่นซ่อน


0
private boolean isKeyboardShown = false;
private int prevContentHeight = 0;
private ViewGroup contentLayout;

private ViewTreeObserver.OnGlobalLayoutListener keyboardLayoutListener =
        new ViewTreeObserver.OnGlobalLayoutListener() {

    @Override
    public void onGlobalLayout() {
        int contentHeight = contentLayout.getHeight();
        int rootViewHeight = contentLayout.getRootView().getHeight();

        if (contentHeight > 0) {

            if (!isKeyboardShown) {
                if (contentHeight < prevContentHeight) {
                    isKeyboardShown = true;
                    onShowKeyboard(rootViewHeight - contentHeight);
                }
            } else {
                if (contentHeight > prevContentHeight) {
                    isKeyboardShown = false;
                    onHideKeyboard();
                }
            }

            prevContentHeight = contentHeight;
        }
    }
};

ฉันได้แก้ไขคำตอบที่ยอมรับของ Jaap เล็กน้อย แต่ในกรณีของฉันมีข้อสันนิษฐานบางประการเช่นandroid:windowSoftInputMode=adjustResizeแป้นพิมพ์ไม่ปรากฏขึ้นที่จุดเริ่มต้นเมื่อแอปเริ่มทำงาน และฉันคิดว่าหน้าจอตรงกับความสูงของผู้ปกครอง

contentHeight > 0การตรวจสอบนี้ช่วยให้ฉันทราบว่าหน้าจอที่เกี่ยวข้องถูกซ่อนอยู่หรือแสดงเพื่อใช้การฟังเหตุการณ์แป้นพิมพ์สำหรับหน้าจอเฉพาะนี้ นอกจากนี้ฉันยังส่งผ่านมุมมองเค้าโครงของหน้าจอที่เกี่ยวข้องattachKeyboardListeners(<your layout view here>)ในกิจกรรมหลักของฉันonCreate()วิธีการทุกครั้งที่ความสูงของหน้าจอที่เกี่ยวข้องเปลี่ยนไปฉันจะบันทึกเป็นprevContentHeightตัวแปรเพื่อตรวจสอบในภายหลังว่าแป้นพิมพ์แสดงหรือซ่อนอยู่

สำหรับฉันจนถึงตอนนี้มันใช้งานได้ดี ฉันหวังว่ามันจะได้ผลกับคนอื่น ๆ ด้วย


0

คำตอบของ "Jaap van Hengstum" ใช้ได้ผลสำหรับฉัน แต่ไม่จำเป็นต้องตั้งค่า "android: windowSoftInputMode" อย่างที่เขาพูด!

ฉันทำให้มันเล็กลง (ตอนนี้ตรวจพบสิ่งที่ฉันต้องการจริงๆแล้วเป็นเหตุการณ์ที่แสดงและซ่อนแป้นพิมพ์):

private ViewTreeObserver.OnGlobalLayoutListener keyboardLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        int heightDiff = rootLayout.getRootView().getHeight() - rootLayout.getHeight();
        int contentViewTop = getWindow().findViewById(Window.ID_ANDROID_CONTENT).getTop();
        if(heightDiff <= contentViewTop){
            onHideKeyboard();
        } else {
            onShowKeyboard();
        }
    }
};

private boolean keyboardListenersAttached = false;
private ViewGroup rootLayout;

protected void onShowKeyboard() {}
protected void onHideKeyboard() {}

protected void attachKeyboardListeners() {
    if (keyboardListenersAttached) {
        return;
    }

    rootLayout = (ViewGroup) findViewById(R.id.CommentsActivity);
    rootLayout.getViewTreeObserver().addOnGlobalLayoutListener(keyboardLayoutListener);

    keyboardListenersAttached = true;
}

@Override
protected void onDestroy() {
    super.onDestroy();

    if (keyboardListenersAttached) {
        rootLayout.getViewTreeObserver().removeGlobalOnLayoutListener(keyboardLayoutListener);
    }
}

และอย่าลืมเพิ่มสิ่งนี้

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_comments);
    attachKeyboardListeners();}

0

ไม่ได้ผลตามที่ต้องการ ...

... เคยเห็นใช้การคำนวณขนาดเพื่อตรวจสอบ ...

ฉันต้องการตรวจสอบว่าเปิดอยู่หรือไม่และฉันพบ isAcceptingText()

ดังนั้นสิ่งนี้จึงไม่ตอบคำถามจริงๆเนื่องจากไม่ได้กล่าวถึงการเปิดหรือปิดมากกว่าเช่นเปิดหรือปิดดังนั้นจึงเป็นรหัสที่เกี่ยวข้องซึ่งอาจช่วยผู้อื่นในสถานการณ์ต่างๆ ...

ในกิจกรรม

    if (((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE)).isAcceptingText()) {
        Log.d(TAG,"Software Keyboard was shown");
    } else {
        Log.d(TAG,"Software Keyboard was not shown");
    }

ในส่วน

    if (((InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE)).isAcceptingText()) {
        Log.d(TAG,"Software Keyboard was shown");
    } else {
        Log.d(TAG,"Software Keyboard was not shown");

    }

0

ตรวจสอบด้วยรหัสด้านล่าง:

รหัส XML:

<android.support.constraint.ConstraintLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/coordinatorParent"
    style="@style/parentLayoutPaddingStyle"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

  .................


</android.support.constraint.ConstraintLayout>

รหัส Java:

//Global Variable
android.support.constraint.ConstraintLayout activityRootView;
boolean isKeyboardShowing = false;
private  ViewTreeObserver.OnGlobalLayoutListener onGlobalLayoutListener;
android.support.constraint.ConstraintLayout.LayoutParams layoutParams;




 //onCreate or onViewAttached
    activityRootView = view.findViewById(R.id.coordinatorParent);
        onGlobalLayoutListener = onGlobalLayoutListener();
        activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(onGlobalLayoutListener);


  //outside oncreate
  ViewTreeObserver.OnGlobalLayoutListener onGlobalLayoutListener() {
        return new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                Rect r = new Rect();
                activityRootView.getWindowVisibleDisplayFrame(r);
                int screenHeight = activityRootView.getRootView().getHeight();
                int keypadHeight = screenHeight - r.bottom;

                if (keypadHeight > screenHeight * 0.15) { // 0.15 ratio is perhaps enough to determine keypad height.
                    if (!isKeyboardShowing) {  // keyboard is opened
                        isKeyboardShowing = true;
                        onKeyboardVisibilityChanged(true);
                   }
                }
                else {
                    if (isKeyboardShowing) {   // keyboard is closed
                        isKeyboardShowing = false;
                        onKeyboardVisibilityChanged(false);
                    }
                }
            }//ends here
        };

    }


    void onKeyboardVisibilityChanged(boolean value) {
        layoutParams = (android.support.constraint.ConstraintLayout.LayoutParams)topImg.getLayoutParams();

        if(value){
           int length = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 90, getResources().getDisplayMetrics());
            layoutParams.height= length;
            layoutParams.width = length;
            topImg.setLayoutParams(layoutParams);
            Log.i("keyboard " ,""+ value);
        }else{
            int length1 = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 175, getResources().getDisplayMetrics());
            layoutParams.height= length1;
            layoutParams.width = length1;
            topImg.setLayoutParams(layoutParams);
            Log.i("keyboard " ,""+ value);
        }
    }


    @Override
    public void onDetach() {
        super.onDetach();
        if(onGlobalLayoutListener != null) {
            activityRootView.getViewTreeObserver().removeOnGlobalLayoutListener(onGlobalLayoutListener);
        }
    }

0

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

implementation 'net.yslibrary.keyboardvisibilityevent:keyboardvisibilityevent:3.0.0-RC2'

จากนั้นคุณก็ใช้ส่วนรหัสนี้เพื่อตรวจสอบการมองเห็นแป้นพิมพ์

KeyboardVisibilityEvent.setEventListener(this, new KeyboardVisibilityEventListener() {
        
@Override
  public void onVisibilityChanged(boolean isOpen) {

if (isOpen) 
  Toast.makeText(MainActivity.this, "keyboard opened",Toast.LENGTH_SHORT).show();
else 
  Toast.makeText(MainActivity.this, "keyboard hidden", Toast.LENGTH_SHORT).show();
}
});

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

        UIUtil.showKeyboard(this,edittext_to_be_focused);
        UIUtil.hideKeyboard(this);

0

มีแป้นพิมพ์ปิดฟัง
คลาสSearchEditTextมาจากandroid.widget.EditTextคลาส มีอินเทอร์เฟซSearchEditText.OnKeyboardDismissListenerในคลาสนี้ คุณสามารถดู docmentation:
https://developer.android.com/reference/androidx/leanback/widget/SearchEditText

บันทึก. ก่อนใช้ SearchEditText คุณต้องตั้งค่า Gradle dependencies ใน build.gradle (: app):

implementation 'androidx.leanback:leanback:1.1.0-alpha05'

อาจจะมีคนเข้ามาสะดวก

คำตอบโดยละเอียด:

import androidx.appcompat.app.AppCompatActivity;
import androidx.leanback.widget.SearchEditText;

import android.os.Bundle;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity
        implements SearchEditText.OnKeyboardDismissListener {

    SearchEditText searchEditText;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        searchEditText = findViewById(R.id.search_edit_text);

        searchEditText.setOnKeyboardDismissListener(this);
    }

    /**
     * Method invoked when the keyboard is dismissed.
     */
    @Override
    public void onKeyboardDismiss() {
        Toast.makeText(this, "The listener worked", Toast.LENGTH_LONG).show();
    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.leanback.widget.SearchEditText
        android:id="@+id/search_edit_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="12dp"
        android:textSize="20sp"
        android:focusableInTouchMode="true"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

หมายเหตุ: Listener ใช้ได้กับ:

android:windowSoftInputMode="adjustPan"
android:windowSoftInputMode="adjustResize"

ฉันใช้สิ่งนี้กับ MainActivity และมี EditText เพียงรายการเดียวใน UI แต่ไม่เรียกใช้เมื่อปิดแป้นพิมพ์
Asad Mukhtar

@AsadMukhtar สวัสดีดูคำตอบโดยละเอียดของฉันด้านบน หวังว่าจะช่วยได้
Justin Case
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.