วิธีการจับภาพเหตุการณ์ "การแสดง / ซ่อนแป้นพิมพ์เสมือน" ใน Android


227

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

เป็นไปได้ไหม?

ขอบคุณ!


คำตอบ:


69

บันทึก

วิธีนี้จะไม่ทำงานกับคีย์บอร์ดที่อ่อนนุ่มและ 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();
    }
}

จากนั้นเพียงเปลี่ยนการมองเห็นของบางมุมมองอัพเดตฟิลด์และเปลี่ยนไฟล์เลย์เอาต์ของคุณ


4
@shiami ลองnewConfig.keyboardHidden == Configuration.KEYBOARDHIDDEN_NO~ Chris
cimnine

3
ใช้งานได้เฉพาะเมื่อคุณลงทะเบียนกิจกรรมเพื่อฟัง configChanges ที่คุณต้องการใน AndroidManifest
Raul Agrait

65
โปรดอัปเดตคำตอบของคุณและบอกว่ามันใช้ไม่ได้กับคีย์บอร์ดอ่อน ฉันเสียเวลาครึ่งวันในการลองใช้โค้ดของคุณ แล้วเห็นความคิดเห็นเหล่านี้
Shirish Herwade

17
นี่ไม่ทำงานกับแป้นพิมพ์ "เสมือน" ซึ่งเป็นคำถามเดิม
brummfondel

18
คำถามคือเกี่ยวกับ SOFT KEYBOARD ทำไมคำตอบที่ยอมรับได้เกี่ยวกับคีย์บอร์ดฮาร์ดแวร์ -1!
Denys Vitali

56

นี่อาจไม่ใช่วิธีที่มีประสิทธิภาพที่สุด แต่สิ่งนี้ใช้ได้กับฉันทุกครั้ง ... ฉันเรียกฟังก์ชั่นนี้ซึ่งฉันจำเป็นต้องฟัง softKeyboard

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

หมายเหตุ: วิธีการนี้จะทำให้เกิดปัญหาหากผู้ใช้ใช้แป้นพิมพ์ลอย


1
addOnGlobalLayoutListener?
coolcool1994

7
ซึ่งมีกลิ่นเหมือนหน่วยความจำรั่ว คุณกำลังเพิ่มผู้ฟังไปยังออบเจกต์ระดับโลกที่จะยึดมั่นกับคุณและไม่ปล่อยให้คุณไป
flexicious.com

9
อันนี้จะไม่ทำงานสำหรับชุดกิจกรรมที่มีandroid:windowSoftInputMode="adjustPan"หรือadjustResizeหน้าต่างเต็มหน้าจอเนื่องจากไม่เคยปรับขนาดเค้าโครง
Ionoclast Brigham

1
ใช้งานได้กับ adjustResize เท่านั้น สำหรับปุ่มปรับความสูงความสูงไม่เคยเปลี่ยนแปลง
alexhilton

2
ทำไมคุณถึงเปรียบเทียบบูลีน
Xerus

37

หากคุณต้องการจัดการแสดง / ซ่อนหน้าต่างแป้นพิมพ์ IMM (เสมือน) จากกิจกรรมของคุณคุณจะต้อง subclass เลย์เอาต์และแทนที่เมธอด onMesure ของคุณ (เพื่อให้คุณสามารถกำหนดความกว้างที่วัดได้และความสูงที่วัดได้ของโครงร่างของคุณ) หลังจากนั้นกำหนดเลย์เอาต์คลาสย่อยเป็นมุมมองหลักสำหรับกิจกรรมของคุณโดย setContentView () ตอนนี้คุณจะสามารถจัดการแสดง / ซ่อนเหตุการณ์หน้าต่างของ 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...

}

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

4
มันไม่ทำงานสำหรับ android: windowSoftInputMode = "adjustPan" ฉันต้องการให้หน้าจอของฉันไม่ควรถูกลดขนาดหลังจากที่คีย์บอร์ดนุ่มปรากฏขึ้น คุณช่วยบอกการแก้ไขใด ๆ เพื่อให้มันทำงานได้แม้สำหรับ adjustPan
Shirish Herwade

มันไม่ทำงานมันจะไปยังส่วนอื่น ๆ ที่นี่เสมอถ้า (ความสูงจริง> ที่นำเสนอความสูง) {// แสดงคีย์บอร์ด} else {// ซ่อน Keyboard}}
Aamirkhan

นอกจากนี้คุณยังสามารถใช้มุมมองที่กำหนดเองกับแนวคิดเดียวกันได้ตามตัวอย่างgist.github.com/juliomarcos/8ca307cd7eca607c8547
Julio Rodrigues

1
จะไม่ทำงานสำหรับกิจกรรมที่ตั้งค่าด้วยandroid:windowSoftInputMode="adjustPan"หรือadjustResizeหน้าต่างเต็มหน้าจอเนื่องจากไม่ได้ปรับขนาดเค้าโครง
Ionoclast Brigham

35

ฉันทำอย่างนี้:

เพิ่ม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();
  }
}

หวังว่านี่จะช่วยคุณได้


2
ขอบคุณ Hiren นี่เป็นโซลูชั่นที่สมบูรณ์แบบ +1
Harin Kaklotar

1
ขอบคุณทำงานให้ฉัน! หากคุณต้องการเพียงแค่ปรับ RecyclerView ของคุณดูวิธีแก้ปัญหาที่นี่: stackoverflow.com/a/43204258/373106
David Papirov

1
การใช้งานที่สมบูรณ์แบบนำมาใช้ใหม่ได้ทำงานในกิจกรรมหรือชิ้นส่วนขอบคุณ
Pelanes

1
ดีมากจริงๆ
ZaoTaoBao

@DavidPapirov คุณวางลิงก์ไปยัง RecyclerView แต่ไม่ได้พูดถึงที่นี่
CoolMind

22

จาก Code จาก 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();
        }
    }

}

ใช้งานได้ดี ... ทำเครื่องหมายว่าโซลูชันนี้จะใช้งานได้เมื่อตั้งค่าโหมดการป้อนข้อมูลอ่อนของกิจกรรมของคุณเป็น "WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE"


3
มันไม่ทำงานสำหรับ android: windowSoftInputMode = "adjustPan" ฉันต้องการให้หน้าจอของฉันไม่ควรถูกลดขนาดหลังจากที่คีย์บอร์ดนุ่มปรากฏขึ้น คุณช่วยบอกการแก้ไขใด ๆ เพื่อให้มันทำงานได้แม้สำหรับ adjustPan
Shirish Herwade

1
อันนี้จะไม่ทำงานสำหรับชุดกิจกรรมที่มีandroid:windowSoftInputMode="adjustPan"หรือadjustResizeหน้าต่างเต็มหน้าจอเนื่องจากไม่เคยปรับขนาดเค้าโครง
Ionoclast Brigham

มันทริกเกอร์ค่อนข้างสองสามครั้ง
zionpi

22

เช่นเดียวกับคำตอบของ @ amalBit ลงทะเบียนผู้ฟังในเลย์เอาต์ทั่วโลกและคำนวณความแตกต่างของด้านล่างที่มองเห็นได้ของ dectorView และด้านล่างที่เสนอถ้าความแตกต่างใหญ่กว่าค่าบางค่า (เดาความสูงของ 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


2
ฉันกำลังจะดึงผมของฉัน !! คุณช่วยผมของฉัน;)
Vijay Singh Chouhan

1
มันเป็นคำตอบที่ดีเพียงอย่างเดียวที่นี่มันทำงานบนแป้นพิมพ์ที่สมบูรณ์แบบขอบคุณ
Z3nk

12

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

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

10

ไม่แน่ใจว่ามีใครโพสต์สิ่งนี้หรือไม่ พบโซลูชันนี้ใช้งานง่าย! . ระดับ softkeyboard อยู่บน 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
                    ...
                }
            });

    }   
});

นี่คือ Git ที่จะได้รับ SoftkeyBoard " gist.github.com/felHR85/… "
douarbou

9

ฉันแก้ปัญหานี้โดยการเอาชนะ onKeyPreIme (int keyCode, KeyEvent event) ใน EditText ที่กำหนดเองของฉัน

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

วิธีใช้ใน Fragment หรือ Activity? @qbait
Maulik Dodia

ใช้งานไม่ได้มันจะถูกเรียกก็ต่อเมื่อฉันออกจากหน้าในกรณี
DysaniazzZ

นี่เป็นวิธีการจาก EditText ดูคำตอบนี้: stackoverflow.com/a/5993196/2093236
Dmide

4

ฉันมีแฮ็คที่จะทำเช่นนี้ แม้ว่าจะมีไม่ได้ดูเหมือนจะเป็นวิธีการในการตรวจสอบเมื่อแป้นพิมพ์อ่อนได้แสดงหรือซ่อนคุณสามารถในความเป็นจริงการตรวจสอบเมื่อมันเป็นเรื่องเกี่ยวกับที่จะแสดงหรือซ่อนโดยการตั้งค่า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);
        }
    });

1
มันไม่ทำงานมิฉะนั้น OnFocusChangeListenerเพียงบอกว่าEditTextมีโฟกัสหลังจากเปลี่ยนสถานะหรือไม่ แต่IMEอาจถูกซ่อนไว้เมื่อEditTextมีโฟกัสวิธีการตรวจสอบกรณีนี้หรือไม่
DysaniazzZ

3

ฉันเชื่อว่าคุณกำลังพยายามแสดงมุมมองที่ถูกบล็อกโดยคีย์บอร์ดนุ่ม ลองhttp://android-developers.blogspot.com/2009/04/updating-applications-for-on-screen.htmlนี้


trackback แรกใน URL นี้ชี้ไปที่เว็บบล็อกของ RussenReaktor ซึ่งระบุว่าเพิ่ม android: windowSoftInputMode = "adjustPan" ในรายการกิจกรรมของ มันใช้งานได้ดีสำหรับฉัน
JohnnyLambada

2

ฉันได้แก้ปัญหาในการเข้ารหัส textview กลับบรรทัดเดียว

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

2
มันไม่ทำงานสำหรับ android: windowSoftInputMode = "adjustPan" ฉันต้องการให้หน้าจอของฉันไม่ควรถูกลดขนาดหลังจากที่คีย์บอร์ดนุ่มปรากฏขึ้น คุณช่วยบอกการแก้ไขใด ๆ เพื่อให้สามารถใช้งานได้กับ adjustPan
Shirish Herwade

เมื่อฟังก์ชั่นซ่อน / แสดงวิธีการฟังนี้จะเรียกสองครั้งหรือสามครั้ง ฉันไม่ได้มีปัญหาอะไรแน่
Jagveer Singh Rajput

2

คุณสามารถตรวจสอบช่องว่างด้านล่างของลูกแรกของ DecorView มันจะถูกตั้งค่าเป็นค่าที่ไม่เป็นศูนย์เมื่อมีการแสดงแป้นพิมพ์

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

1

ซ่อน | แสดงกิจกรรมสำหรับแป้นพิมพ์สามารถฟังผ่านแฮ็คธรรมดาใน 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 คือมุมมองรูทของกิจกรรม


heightDiff ของฉันคือ 160 ในการเริ่มต้นและ 742 กับ kbd ดังนั้นฉันจึงต้องแนะนำและกำหนด initialHeightDiff ในการเริ่มต้น
djdance

0

ใช้viewTreeObserverเพื่อรับเหตุการณ์คีย์บอร์ดอย่างง่ายดาย

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


-2

คำตอบของ Nebojsa Tomcic ไม่มีประโยชน์สำหรับฉัน ฉันมีRelativeLayoutกับTextViewและAutoCompleteTextViewข้างในมัน ฉันต้องเลื่อน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);
        }
    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.