Câu hỏi Đóng / ẩn Bàn phím Android mềm


tôi có một EditText và một Button trong bố cục của tôi.

Sau khi viết trong trường chỉnh sửa và nhấp vào Button, Tôi muốn ẩn bàn phím ảo. Tôi cho rằng đây là một đoạn mã đơn giản, nhưng tôi có thể tìm thấy ví dụ về nó ở đâu?


3093


gốc


Điều gì sẽ xảy ra nếu bạn chỉ có một EditText và một số nút, như hộp kiểm và radio? Nơi duy nhất bạn cần bàn phím là trong EditText duy nhất. Làm thế nào để bạn đăng ký để biết rằng một cái gì đó khác đã được chọn / bấm để ẩn bàn phím? - AlikElzin-kilaka
tôi cảm thấy ngu ngốc. Tôi không thể ẩn bàn phím trên ICS. Đã thử tất cả các phương pháp ở đây và kết hợp chúng. Không đời nào. Các phương pháp để hiển thị nó hoạt động, nhưng tôi không thể giấu nó không có vấn đề gì windw token, ẩn cờ, thiết lập biểu hiện hoặc nến cho bất kỳ vị thánh. Trên bàn phím hiển thị tôi luôn thấy điều này: I / LatinIME (396): InputType.TYPE_NULL được chỉ định W / LatinIME (396): Lớp đầu vào không mong muốn: inputType = 0x00000000 imeOptions = 0x00000000 - rupps
/ ** * Phương pháp này được sử dụng để ẩn bàn phím mềm. * @param activity * / public void hideSoftKeyboard (Hoạt động hoạt động) {InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService (Activity.INPUT_METHOD_SERVICE); inputMethodManager.hideSoftInputFromWindow (activity.getCurrentFocus (). getWindowToken (), 0); } - Harshal Benake
Thật buồn khi một câu hỏi dường như đơn giản như vậy là rất phổ biến. - lang2
Đúng vậy, như Android có giải pháp một và hai lớp cho những thứ đơn giản. - milosmns


Các câu trả lời:


Để giúp làm rõ sự điên rồ này, tôi muốn bắt đầu bằng cách xin lỗi thay mặt cho tất cả người dùng Android vì điều trị vô lý của Google về bàn phím mềm. Lý do có rất nhiều câu trả lời, mỗi câu trả lời khác nhau, cho cùng một câu hỏi đơn giản là vì API này, giống như nhiều người khác trong Android, được thiết kế khủng khiếp. Tôi có thể nghĩ không có cách lịch sự để tuyên bố nó.

Tôi muốn giấu bàn phím. Tôi hy vọng sẽ cung cấp cho Android tuyên bố sau: Keyboard.hide(). Kết thúc. Cảm ơn nhiều. Nhưng Android có một vấn đề. Bạn phải sử dụng InputMethodManager để ẩn bàn phím. OK, tốt, đây là API của Android cho bàn phím. NHƯNG! Bạn được yêu cầu có một Context để có quyền truy cập vào IMM. Bây giờ chúng tôi có một vấn đề. Tôi có thể muốn ẩn bàn phím khỏi lớp tĩnh hoặc tiện ích không sử dụng hoặc cần bất kỳ Context. hoặc Và tồi tệ hơn, IMM yêu cầu bạn chỉ định những gì View (hoặc thậm chí tệ hơn, những gì Window) bạn muốn ẩn bàn phím FROM.

Đây là những gì làm cho ẩn bàn phím rất khó khăn. Kính gửi Google: Khi tôi tìm công thức cho một chiếc bánh, không có RecipeProvider trên trái đất sẽ từ chối cung cấp cho tôi công thức trừ khi tôi lần đầu tiên trả lời cho WHO bánh sẽ được ăn bởi AND, nơi nó sẽ được ăn !!

Câu chuyện buồn này kết thúc với sự thật xấu xí: để ẩn bàn phím Android, bạn sẽ được yêu cầu cung cấp 2 hình thức nhận dạng: a Context và một trong hai View hoặc một Window.

Tôi đã tạo một phương thức tiện ích tĩnh có thể thực hiện công việc RẤT một cách vững chắc, miễn là bạn gọi nó từ một Activity.

public static void hideKeyboard(Activity activity) {
    InputMethodManager imm = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
    //Find the currently focused view, so we can grab the correct window token from it.
    View view = activity.getCurrentFocus();
    //If no view currently has focus, create a new one, just so we can grab a window token from it
    if (view == null) {
        view = new View(activity);
    }
    imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}

Lưu ý rằng phương thức tiện ích này CHỈ hoạt động khi được gọi từ một Activity! Các cuộc gọi phương thức trên getCurrentFocus của mục tiêu Activity để tìm nạp mã thông báo cửa sổ thích hợp.

Nhưng giả sử bạn muốn ẩn bàn phím khỏi EditText được lưu trữ trong một DialogFragment? Bạn không thể sử dụng phương pháp trên cho điều đó:

hideKeyboard(getActivity()); //won't work

Điều này sẽ không hiệu quả vì bạn sẽ chuyển một tham chiếu đến Fragmentmáy chủ của Activity, sẽ không có kiểm soát tập trung trong khi Fragment được hiển thị! Wow! Vì vậy, để ẩn bàn phím khỏi các mảnh, tôi sử dụng đến cấp độ thấp hơn, thông dụng hơn và xấu hơn:

public static void hideKeyboardFrom(Context context, View view) {
    InputMethodManager imm = (InputMethodManager) context.getSystemService(Activity.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}

Dưới đây là một số thông tin bổ sung được thu thập từ nhiều thời gian hơn lãng phí theo đuổi giải pháp này:

Giới thiệu windowSoftInputMode

Có một điểm tranh luận khác để ý thức. Theo mặc định, Android sẽ tự động chỉ định tiêu điểm ban đầu cho EditText hoặc kiểm soát tiêu điểm trong Activity. Nó tự nhiên sau đó InputMethod (thường là bàn phím mềm) sẽ đáp ứng với sự kiện tập trung bằng cách hiển thị chính nó. Các windowSoftInputMode thuộc tính trong AndroidManifest.xml, khi được đặt thành stateAlwaysHidden, hướng dẫn bàn phím bỏ qua tiêu điểm ban đầu được gán tự động này.

<activity
    android:name=".MyActivity"
    android:windowSoftInputMode="stateAlwaysHidden"/>

Hầu như không thể tin được, nó dường như không làm gì để ngăn bàn phím mở khi bạn chạm vào điều khiển (trừ khi focusable="false" và / hoặc focusableInTouchMode="false" được gán cho điều khiển). Rõ ràng, cài đặt windowSoftInputMode chỉ áp dụng cho các sự kiện lấy nét tự động, không tập trung sự kiện được kích hoạt từ các sự kiện chạm.

Vì thế, stateAlwaysHidden là RẤT kém tên là thực sự. Nó có lẽ nên được gọi là ignoreInitialFocus thay thế.

Hi vọng điêu nay co ich.


CẬP NHẬT: Các cách khác để nhận mã thông báo cửa sổ

Nếu không có chế độ xem tập trung (ví dụ: có thể xảy ra nếu bạn vừa thay đổi đoạn), có các chế độ xem khác sẽ cung cấp mã thông báo cửa sổ hữu ích.

Đây là những lựa chọn thay thế cho mã trên if (view == null) view = new View(activity);  Những điều này không đề cập rõ ràng đến hoạt động của bạn.

Bên trong một lớp phân đoạn:

view = getView().getRootView().getWindowToken();

Đưa ra một đoạn fragment như một tham số:

view = fragment.getView().getRootView().getWindowToken();

Bắt đầu từ nội dung nội dung của bạn:

view = findViewById(android.R.id.content).getRootView().getWindowToken();

CẬP NHẬT 2: Xóa tiêu điểm để tránh hiển thị lại bàn phím nếu bạn mở ứng dụng từ nền

Thêm dòng này vào cuối phương thức:

view.clearFocus();


1024



Tôi không nghĩ bạn nên sửa đổi softInputMode. Thao tác này sẽ ghi đè cài đặt AndroidManifest. - Kyle Ivey
Cảm ơn rất nhiều cho câu trả lời kỹ lưỡng. Eloquent đủ cho một người mới bắt đầu đi kèm với một sự hiểu biết tốt về bàn phím mềm. Tôi muốn ẩn / hiện bàn phím từ mảnh vỡ và đây là câu trả lời hợp lý nhất mà tôi tìm thấy. - Tina
Câu trả lời tốt và hữu ích. Đó là một trong những bài viết cực kỳ hiếm hoi trên StackOverflow, đó là một niềm vui để đọc. - Rameez Hussain
@AlexanderFarber có, thường là EditText, nhưng tôi tin rằng có thể nhìn thấy View sẽ hoạt động (ví dụ: TextView), kể từ khi View chỉ được sử dụng để lấy mã thông báo cửa sổ (điều cần ẩn bàn phím). Ngoài ra, tôi tin rằng View nên đến từ máy chủ Activity thay vì Fragment - rmirabelle
@rmirabelle In a Fragment có vẻ như bạn có thể sử dụng getActivity().getWindow().getDecorView() - McX


Bạn có thể buộc Android ẩn bàn phím ảo bằng InputMethodManager, gọi điện hideSoftInputFromWindow, chuyển vào mã thông báo của cửa sổ chứa chế độ xem được lấy nét của bạn.

// Check if no view has focus:
View view = this.getCurrentFocus();
if (view != null) {  
    InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}

Điều này sẽ buộc bàn phím bị ẩn trong mọi tình huống. Trong một số trường hợp, bạn sẽ muốn chuyển vào InputMethodManager.HIDE_IMPLICIT_ONLY làm thông số thứ hai để đảm bảo bạn chỉ ẩn bàn phím khi người dùng không buộc nó xuất hiện (bằng cách nhấn giữ trình đơn).

Chú thích: Nếu bạn muốn thực hiện điều này trong Kotlin, hãy sử dụng: context?.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager


4176



Cảm ơn điều này dường như làm việc tuyệt vời nếu sử dụng 0 làm tham số thứ hai. Nhưng nếu tôi sử dụng InputMethodManager.HIDE_IMPLICIT_ONLY bàn phím không bao giờ bị ẩn (mặc dù tôi không giữ menu). Bất kỳ gợi ý nào? - RoflcoptrException
Mát mẻ. Chỉ cần làm rõ, điều này chỉ loại bỏ nó nếu có, nhưng sẽ không ngăn chặn nó từ bật lên, phải không? - Cheezmeister
Nó có thể hữu ích để gọi hàm editText.clearFocus () trước khi ẩn softInput - user2224350
Đang gọi editText.clearFocus() sau đó InputMethodManager.HIDE_IMPLICIT_ONLY thậm chí hoạt động trên 4.1 - sprocket12
Điều gì làm việc cho tôi trên 4.4 / htc đã được thực hiện View focused = getCurrentFocus() để có được những gì là chắc chắn chế độ xem hiện đang được tập trung, gọi điện focused.clearFocus(), và sau đó inputMethodManager.hideSoftInputFromWindow(focused.getWindowToken(), 0) (có cờ rõ ràng). - Ionoclast Brigham


Cũng hữu ích cho việc ẩn bàn phím mềm là:

getWindow().setSoftInputMode(
    WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN
);

Điều này có thể được sử dụng để ngăn chặn bàn phím mềm cho đến khi người dùng thực sự chạm vào Chế độ xem editText.


742



Bạn cũng có thể đạt được hiệu ứng tương tự bằng cách thêm android: windowSoftInputMode = "stateHidden" vào hoạt động của bạn trong tệp kê khai. - BoD
Đã thử điều này trong một Fragment (tham khảo hoạt động sở hữu) trên API cấp 9 và nó không hoạt động không may. Đã thử gọi nó trong onResume và onActivityCreated - không có hiệu lực. - AgentKnopf
Tôi đang làm việc trong một hộp thoại và điều này làm việc. Tôi đang sử dụng Android 3.2. Tôi đặt nó vào phương thức onCreateDialog (Bundle). Nó không hoạt động trong phương thức onCreate. Hộp thoại hộp thoại = super.onCreateDialog (savedInstanceState); dialog.getWindow (). setSoftInputMode (WindowManager.LayoutParams. SOFT_INPUT_STATE_ALWAYS_HIDDEN); Kết quả là quan điểm của tôi với EditTexts trong nó hiển thị mà không có bàn phím. Khi người dùng chạm vào văn bản chỉnh sửa, bàn phím sẽ hiển thị. - flobacca
Điều này không hoạt động khi tiêu điểm vẫn còn trong EditText (như sau khi chạm vào một nút). Sử dụng giải pháp của Reto cho điều đó. - Noumenon
Tại sao ghi đè cài đặt tệp kê khai là ý tưởng tồi? Tôi gọi điều này từ một mảnh. Không có cài đặt tệp kê khai nào áp dụng cho một đoạn ... - Greg Ennis


Tôi có thêm một giải pháp để ẩn bàn phím:

InputMethodManager imm = (InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0);

Ở đây vượt qua HIDE_IMPLICIT_ONLY ở vị trí của showFlag và 0 ở vị trí của hiddenFlag. Nó sẽ mạnh mẽ đóng bàn phím mềm.


294



Bạn đang sử dụng cờ ẩn trong thông số thẻ showflags. Điều này chỉ hoạt động vì các hằng số sử dụng cùng một số nguyên. Ví dụ sử dụng đúng cờ - Alex
thử nghiệm trên Android 4.0, tôi thích giải pháp này, bởi vì tôi có nhiều văn bản chỉnh sửa, các nút trên hoạt động đó, có thể tập trung
Tại sao điều này hiển thị bàn phím nếu nó bị ẩn? :)
@Mark: Bởi vì phương thức này được gọi là "toggleSoftInput", không phải là "hideSoftInput" :) - Sver
Giải pháp này hiển thị bàn phím nếu nó bị ẩn. Nó không đúng - Michael Katkov


Giải pháp của Meier cũng làm việc cho tôi. Trong trường hợp của tôi, cấp cao nhất của ứng dụng của tôi là một tabHost và tôi muốn ẩn từ khóa khi chuyển đổi tab - tôi nhận được mã thông báo cửa sổ từ tabHost View.

tabHost.setOnTabChangedListener(new OnTabChangeListener() {
    public void onTabChanged(String tabId) {
        InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(tabHost.getApplicationWindowToken(), 0);
    }
}

128



Tôi cũng đã làm việc này với SearchView. Xem dưới đây cho câu trả lời của tôi. Cảm ơn mckoss! - Azurespot


Vui lòng thử mã dưới đây trong onCreate()

EditText edtView=(EditText)findViewById(R.id.editTextConvertValue);
edtView.setInputType(0);

115



Phương pháp này hoạt động như một phương tiện để tránh lỗi "không thể ẩn bàn phím mềm" trong phiên bản 2.0 và 2.1 như được mô tả trong code.google.com/p/android/issues/detail?id=7115 ... phương thức hideSoftInputFromWindow được liệt kê ở trên không hoạt động khi tôi thử nó, nhưng editView.setInputType (0) đã làm. - Spike Williams
Điều này là hợp pháp trên mỗi Javadoc (không phải là một hack) mặc dù tôi sẽ viết lại các phương pháp như editView.setInputType(InputType.TYPE_NULL); - Bostone
Tuy nhiên, công cụ này ẩn giấu gợi ý android: hint. Tôi đang sử dụng Android 1.5 - Tirtha
@Bostone Điều này không hoạt động cho SearchView - nmxprime
điều này thật tuyệt vời khi bạn cần đóng bàn phím từ hộp thoại, không cần phải lấy một phiên bản hoặc bất kỳ thứ gì và có thể gán nó cho tất cả các văn bản chỉnh sửa khi người dùng nhấn một nút để đóng hộp thoại - I'm_With_Stupid


Cập nhật: Tôi không biết tại sao giải pháp này không hoạt động nữa (tôi vừa mới thử nghiệm trên Android 23). Vui lòng sử dụng giải pháp Saurabh Pareek thay thế. Đây là:

InputMethodManager imm = (InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE);
//Hide:
imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0);
//Show
imm.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, 0);

Câu trả lời cũ:

//Show soft-keyboard:
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
//hide keyboard :
 getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);

108



Tôi nên đặt mã này ở đâu? Tôi đã cố gắng để dán getWindow (). SetSoftInputMode (WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); trong onCreate () nhưng bàn phím không bao giờ bị ẩn - user2236096
không hoạt động, được kiểm tra trong radioGroup.setOnCheckedChangeListener, API 23 - Christian Schäfer
Nếu bạn nhìn kỹ hơn, InputMethodManager.HIDE_IMPLICIT_ONLY và InputMethodManager.SHOW_IMPLICIT có cùng giá trị, là "1", vì vậy không có sự khác biệt giữa các cuộc gọi này. => không hoạt động - Palejandro
nếu gọi imm.toggleSoftInput (InputMethodManager.HIDE_IMPLICIT_ONLY, 0); sau đó bàn phím sẽ hiển thị trên màn hình :) Thực hiện tốt nhất là: github.com/ravindu1024/android-keyboardlistener Xấu hổ trên Android SDK - Duna
I don't know why this solution is not work any more - bởi vì nó Android, mọi thứ sẽ có thể thay đổi, có thể một phần thiết kế tồi tệ ... Chúng tôi viết bất cẩn, rồi chúng tôi tấn công tất cả và viết lại mọi thứ. - King King


protected void hideSoftKeyboard(EditText input) {
    input.setInputType(0);
    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(input.getWindowToken(), 0);    
}

63



Điều này làm việc cho tôi! Nhưng tại sao bạn lại đặt input.setInputType (0) ? Tôi không thể tương tác với EditTextView khi tôi có dòng mã đó (Nó hoạt động khi tôi xóa nó). - ymerdrengene
@ymerdrengene Bạn nói đúng, tôi cũng phải xóa nó. - Lazy


Nếu tất cả các câu trả lời khác ở đây không phù hợp với bạn như bạn muốn, thì có một cách khác để điều khiển bàn phím theo cách thủ công.

Tạo một hàm với điều đó sẽ quản lý một số EditTextThuộc tính của:

public void setEditTextFocus(boolean isFocused) {
    searchEditText.setCursorVisible(isFocused);
    searchEditText.setFocusable(isFocused);
    searchEditText.setFocusableInTouchMode(isFocused);

    if (isFocused) {
        searchEditText.requestFocus();
    }
}

Sau đó, hãy chắc chắn rằng onFocus của EditText bạn mở / đóng bàn phím:

searchEditText.setOnFocusChangeListener(new OnFocusChangeListener() {
    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        if (v == searchEditText) {
            if (hasFocus) {
                // Open keyboard
                ((InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE)).showSoftInput(searchEditText, InputMethodManager.SHOW_FORCED);
            } else {
                // Close keyboard
                ((InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(searchEditText.getWindowToken(), 0);
            }
        }
    }
});

Bây giờ, bất cứ khi nào bạn muốn mở bàn phím theo cách thủ công, hãy gọi:

setEditTextFocus(true);

Và để kết thúc cuộc gọi:

setEditTextFocus(false);

58



+1 - Nếu bạn muốn bắt đầu một hoạt động với bàn phím đóng sử dụng giải pháp này và thêm một onclicklistener đặt setEditTextFocus (true). Hoạt động như charme! - schlingel
Tôi đã nhận 'Không thể giải quyết bối cảnh biểu tượng', trên dòng thứ 7 và thứ 10 của khối thứ hai của mã. - gimmegimme
Sử dụng getContext () để thay thế - Rotemmiz


Saurabh Pareek có câu trả lời tốt nhất cho đến nay.

Cũng có thể sử dụng đúng cờ.

/* hide keyboard */
((InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE))
    .toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, 0);

/* show keyboard */
((InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE))
    .toggleSoftInput(0, InputMethodManager.HIDE_IMPLICIT_ONLY);

Ví dụ về sử dụng thực tế

/* click button */
public void onClick(View view) {      
  /* hide keyboard */
  ((InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE))
      .toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, 0);

  /* start loader to check parameters ... */
}

/* loader finished */
public void onLoadFinished(Loader<Object> loader, Object data) {
    /* parameters not valid ... */

    /* show keyboard */
    ((InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE))
        .toggleSoftInput(0, InputMethodManager.HIDE_IMPLICIT_ONLY);

    /* parameters valid ... */
}

51



Trong 2.1 bàn phím bật lên anyway, sau đó ẩn. Không tốt. - halxinate
Đây là hiệu quả nhất cho phiên bản mới nhất. Người ta sẽ luôn cần phải tinh chỉnh nó cho các phiên bản cũ hơn. Đặc biệt trước v3. - Alex
Không thể giải quyết phương thức getSystemService () với Fragments! - Mazen Kasser
@Mazen: sử dụng fragment.getActivity().getSystemService(); - Johan S
Không. Trên Tab Samsung của tôi, Android 5.0, Cái gọi là "ẩn bàn phím" mã ở trên sẽ TỪ KHÓA bàn phím mềm - nếu nó đã bị ẩn, nó sẽ hiển thị nó. Có một lý do hàm này có TOGGLE trong tên. - ToolmakerSteve


từ tìm kiếm, ở đây tôi tìm thấy câu trả lời phù hợp với tôi

// Show soft-keyboard:
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);

// Hide soft-keyboard:
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);

45