I have a FragmentActivity
using a ViewPager
to serve several fragments. Each is a ListFragment
with the following layout:
<?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">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="8dp">
<ListView android:id="@id/android:list"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
<EditText android:id="@+id/entertext"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
When starting the activity, the soft keyboard shows. To remedy this, I did the following inside the fragment:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//Save the container view so we can access the window token
viewContainer = container;
//get the input method manager service
imm = (InputMethodManager)getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
. . .
}
@Override
public void onStart() {
super.onStart();
//Hide the soft keyboard
imm.hideSoftInputFromWindow(viewContainer.getWindowToken(), 0);
}
I save the incoming ViewGroup container
parameter from onCreateView
as a way to access the window token for the main activity. This runs without error, but the keyboard doesn't get hidden from the call to hideSoftInputFromWindow
in onStart
.
Originally, I tried using the inflated layout instead of container
, i.e:
imm.hideSoftInputFromWindow(myInflatedLayout.getWindowToken(), 0);
but this threw a NullPointerException
, presumably because the fragment itself isn't an activity and doesn't have a unique window token?
Is there a way to hide the soft keyboard from within a fragment, or should I create a method in the FragmentActivity
and call it from within the fragment?
As long as your Fragment creates a View, you can use the IBinder (window token) from that view after it has been attached. For example, you can override onActivityCreated in your Fragment:
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
final InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getView().getWindowToken(), 0);
}
Nothing but the following line of code worked for me:
getActivity().getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
SOFT_INPUT_STATE_HIDDEN
also worked for me, though I don't know what the difference between that and `SOFT_INPUT_STATE_ALWAYS_HIDDEN' is.
If you add the following attribute to your activity's manifest definition, it will completely suppress the keyboard from popping when your activity opens. Hopefully this helps:
(Add to your Activity's manifest definition):
android:windowSoftInputMode="stateHidden"
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_my, container,
false);
someClass.onCreate(rootView);
return rootView;
}
Keep an instance of my root view in my class
View view;
public void onCreate(View rootView) {
view = rootView;
Use the view to hide the keyboard
public void removePhoneKeypad() {
InputMethodManager inputManager = (InputMethodManager) view
.getContext()
.getSystemService(Context.INPUT_METHOD_SERVICE);
IBinder binder = view.getWindowToken();
inputManager.hideSoftInputFromWindow(binder,
InputMethodManager.HIDE_NOT_ALWAYS);
}
Exception for DialogFragment
though, focus of the embedded Dialog
must be hidden, instead only the first EditText
within the embedded Dialog
this.getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) dialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN)}
This code works for fragments:
getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
Use this static method, from anywhere (Activity / Fragment) you like.
public static void hideKeyboard(Activity activity) {
try{
InputMethodManager inputManager = (InputMethodManager) activity
.getSystemService(Context.INPUT_METHOD_SERVICE);
View currentFocusedView = activity.getCurrentFocus();
if (currentFocusedView != null) {
inputManager.hideSoftInputFromWindow(currentFocusedView.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
}
}catch (Exception e){
e.printStackTrace();
}
}
If you want to use for fragment just call hideKeyboard(((Activity) getActivity()))
.
this will be work in my case when in tabs i switch from one fragment to another fragments
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser) {
try {
InputMethodManager mImm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
mImm.hideSoftInputFromWindow(getView().getWindowToken(), 0);
mImm.hideSoftInputFromWindow(getActivity().getCurrentFocus().getWindowToken(), 0);
} catch (Exception e) {
Log.e(TAG, "setUserVisibleHint: ", e);
}
}
}
Solution that worked for me in fragments:
fun hideKeyboard(){
val imm = requireActivity().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(view?.windowToken, 0)
}
and in an activity:
fun hideKeyboard(){
val inputManager: InputMethodManager = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
inputManager.hideSoftInputFromWindow(currentFocus?.windowToken, InputMethodManager.SHOW_FORCED)
}
Nothing of this worked on API27. I had to add this in the container of the layout, for me it was a ConstraintLayout:
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="true"
android:focusableInTouchMode="true"
android:focusedByDefault="true">
//Your layout
</android.support.constraint.ConstraintLayout>
This worked for me in Kotlin class
fun hideKeyboard(activity: Activity) {
try {
val inputManager = activity
.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
val currentFocusedView = activity.currentFocus
if (currentFocusedView != null) {
inputManager.hideSoftInputFromWindow(currentFocusedView.windowToken, InputMethodManager.HIDE_NOT_ALWAYS)
}
} catch (e: Exception) {
e.printStackTrace()
}
}
Use this code in any fragment button listener:
InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(getActivity().INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getActivity().getCurrentFocus().getWindowToken(), 0);
getActivity().getCurrentFocus().getWindowToken()
is not null otherwise it'll cause error if there's no focused editText. See my answer below
Kotlin code
val imm = requireActivity().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(requireActivity().currentFocus?.windowToken, 0)
Just add this line in you code:
getActivity().getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
In Kotlin:
(activity?.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager).hideSoftInputFromWindow(view?.windowToken,0)
Use this:
Button loginBtn = view.findViewById(R.id.loginBtn);
loginBtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(getActivity().INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
}
});
IN BEGINNING
in fragment, below code(use in onActivityCreated) force to hide keyboard in beginning:
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Objects.requireNonNull(getActivity()).getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
}
DURING FRAGMENT (if need)
and also if you have edittext or sth different needs keyboard, and wanna hide the keyboard when pressing outside the keyboard(in my case I have LinearLayout class in xml), first initialize the layout:
LinearLayout linearLayout;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.<your fragment xml>, container, false);
linearLayout= view.findViewById(R.id.linearLayout);
...
return view;
}
then, you need to below code(use in onViewCreated):
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
linearLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view12) {
try {
InputMethodManager inputMethodManager = (InputMethodManager) Objects.requireNonNull(VideoFragment.this.getActivity()).getSystemService(INPUT_METHOD_SERVICE);
assert inputMethodManager != null;
inputMethodManager.hideSoftInputFromWindow(VideoFragment.this.getActivity().getCurrentFocus().getWindowToken(), 0);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
You can use two ways:
You can create a method inside fragment, but first you must create a View attribute and put the inflater result inside it before it returns in onCreateView:
1° Open your Fragment class. Create attribute
private View view;
2° assign the 'view' attribute the inflater in onCreateView
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
view = inflater.inflate(R.layout.your_activity_main, container, false);
return view;
}
3° create the method 'hideKeyboard'
public void hideKeyboard(Activity activity) {
try{
InputMethodManager inputManager = (InputMethodManager) activity
.getSystemService(view.getContext().INPUT_METHOD_SERVICE);
View currentFocusedView = activity.getCurrentFocus();
if (currentFocusedView != null) {
inputManager.hideSoftInputFromWindow(currentFocusedView.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
}
}catch (Exception e){
e.printStackTrace();
}
}
5° Now just call the method
hideKeyboard(getActivity());
If that doesn't solve your problem, you can try passing the MainActivity class as an object to close the keyboard inside the Frament class
1° In YourClassActivity that you instantiated Fragment, create the method 'hideKeyboard'
public class YourClassActivity extends AppCompatActivity {
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);
}
}
2° Implement the 'Serializable' interface in your Activity that instantiates the Fragment
public class YourClassActivity extends AppCompatActivity implements Serializable {
...
}
3° When you instantiate the Frament in the Activity, you must pass the arguments to that Fragment, which will be the Activity class itself
Bundle bundle = new Bundle();
bundle.putSerializable("activity", this);
YourClassFragment fragment = new YourClassFragment();
fragment.setArguments(bundle);
4° Now let's go to your Fragment class. Create attribute view and activity.
private View view;
private Activity activity;
5° Assign the 'view' attribute the inflater in onCreateView. Here you will retrieve the Activity object that was passed as a parameter of this Fragment
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
view = inflater.inflate(R.layout.your_activity_main, container, false);
activity = (Activity) getArguments().getSerializable("obj");
return view;
}
6° Now just call the method
hideKeyboard(activity);
I did all steps but there is something missing I hide the keyboard in fragments with that method
fun hideKeyBoard(view: View) {
val inputManager =
requireActivity().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
inputManager.hideSoftInputFromWindow(
view.windowToken,
SOFT_INPUT_STATE_ALWAYS_HIDDEN
)
}
but still when I open the fragment the keyboard open also after a lot of search I found the problem I must put those code in my xml layout root
android:focusable="true"
android:focusableInTouchMode="true"
Note: If you delete above method and just put the attributes in root layout, it will work fine.
Success story sharing