ChatGPT解决这个技术问题 Extra ChatGPT

How to hide the soft keyboard inside a fragment?

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?


I
Ian G. Clifton

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

i added this to my project.but when i click on another tab it is crashing.
For those who are doing this and getting a crash with a NullPointerException, just use the InputMethodManager inside your fragment onCreateView method. Doing so, you will have your view and you can change the last line using the view you have inflated to imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
perfect answer , and I suggest to add same function to on Resume to handle it in case of many fragments created inside viewpager and one of them need to hide keypad after created
S
Shajeel Afzal

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.
The first answer didn't work , this one did the trick . Thanks
Thanks for saving my time buddy.
My situation is I am using fragment/TabView. The first tab has "Tips" in a TextView. The second tab has an activity where I have EditText(s) with "editText1.setShowSoftInputOnFocus(false);" command set and my own custom keypad. When I put the app to the background and then bring the app back into view the unwanted soft keyboard would pop-up. Setting the above command in the onStart Life Cycle Override method stops this. Thanks @Shajeel Afzal
E
Eric Schlenz

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"

Thanks, this is what I ended up doing. However, I would still like to know how to use the Input Method Manager to show/hide the keyboard, because I might need to use it sometime after the activity starts.
M
MrEngineer13
    @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);
}

I used this but I used getView() from my fragment instead of keeping an instance of my view.
The onCreate is a class outside the Fragment, so I pass it the rootView to be able to use it to remove the phoneKeyPad in this class. I suppose they wanted it from inside the Fragment not a class in the Fragment.
m
macio.Jun

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

This is the only way to hide keybord, if you have DialogFragment.
where to write this?
@Mstack, works on onActivityCreated() method.override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) dialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN)}
A
André Ramon

This code works for fragments:

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

N
Nazmus Saadat

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())).


M
Meerz

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

if you have tab fragment and want to hide keyboard for few tab only, use this.
A
Ali Nawaz

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

h
hiddeneyes02

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>

it doesn't work on api < 26, but this does (inside fragment class) @Override public void onResume() { super.onResume(); getView().setFocusable(true); getView().setFocusableInTouchMode(true); getView().requestFocus(); }
Q
Quick learner

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

}

You just saved me more than 48 hours of work bro!
S
Stan Peng

Use this code in any fragment button listener:

InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(getActivity().INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getActivity().getCurrentFocus().getWindowToken(), 0);

Works but you have to check if getActivity().getCurrentFocus().getWindowToken() is not null otherwise it'll cause error if there's no focused editText. See my answer below
R
RonaldPaguay

Kotlin code

val imm = requireActivity().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(requireActivity().currentFocus?.windowToken, 0)

M
Mike

Just add this line in you code:

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

t
timeSmith

In Kotlin:

(activity?.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager).hideSoftInputFromWindow(view?.windowToken,0)

D
Duc Trung Mai

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

n
n-y

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

}

M
Moises

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

M
Mohamed Mohamed Taha

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.