[Android] record the idea of modifying the position of the primary input method

The input method is dialog or full screen dialog and will not be disassigned. The display and hide system call methods are showWindow(true) and hide(). The following is the creation of the input method Window. SoftInputWindow inherits dialog. Needless to say,

mWindow = new SoftInputWindow(this, "InputMethod", mTheme, null, null, mDispatcherState,

                WindowManager.LayoutParams.TYPE_INPUT_METHOD, Gravity.BOTTOM, false);

        mWindow.getWindow().getAttributes().setFitInsetsTypes(statusBars() | navigationBars());

        mWindow.getWindow().getAttributes().setFitInsetsSides(Side.all() & ~Side.BOTTOM);

        mWindow.getWindow().getAttributes().setFitInsetsIgnoringVisibility(true);

For the basis of full screen, you can see the SoftInputWindow initDockWindow method,

Look, windowmanager.layoutparams.flag is written_ LAYOUT_ IN_ SCREEN;

What does this Flag mean? Is to place the window in the whole screen and ignore the restrictions of the parent container,

private void initDockWindow() {

       WindowManager.LayoutParams lp = getWindow().getAttributes();

       lp.type = mWindowType;
       lp.setTitle(mName);

       lp.gravity = mGravity;
       updateWidthHeight(lp);

       getWindow().setAttributes(lp);

       int windowSetFlags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
       int windowModFlags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN |
               WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
               WindowManager.LayoutParams.FLAG_DIM_BEHIND;

       if (!mTakesFocus) {
           windowSetFlags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
       } else {
           windowSetFlags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
           windowModFlags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
       }
       getWindow().setFlags(windowSetFlags, windowModFlags);
   }


If you want the input method and SystemBar to be unobstructed, you must adjust the layout in the dialog,

In the InputMethodService method, initView is as follows:,

mWindow.setContentView(mRootView), key,

mWindow is SoftInputWindow and inherits Dialog, so this is the setting perspective;

How to initialize some members here, such as mInputFrame and mCandidatesFrame. What is this? Call back onCreateView method in setInputView to get the View customized by the three-party input method,

Therefore, the field of vision displayed in front of us is mInputFrame;

void initViews() {

       mInitialized = false;
       mViewsCreated = false;
       mShowInputRequested = false;
       mShowInputFlags =

 0;
       mThemeAttrs = obtainStyledAttributes(android.R.styleable.InputMethodService);
       mRootView = mInflater.inflate(
               com.android.internal.R.layout.input_method, null);
       mWindow.setContentView(mRootView);
       mRootView.getViewTreeObserver().removeOnComputeInternalInsetsListener(mInsetsComputer);
       mRootView.getViewTreeObserver().addOnComputeInternalInsetsListener(mInsetsComputer);
       if (Settings.Global.getInt(getContentResolver(),
               Settings.Global.FANCY_IME_ANIMATIONS, 0) != 0) {
           mWindow.getWindow().setWindowAnimations(
                   com.android.internal.R.style.Animation_InputMethodFancy);
       }
       mFullscreenArea = mRootView.findViewById(com.android.internal.R.id.fullscreenArea);
       mExtractViewHidden = false;
       mExtractFrame = mRootView.findViewById(android.R.id.extractArea);
       mExtractView = null;
       mExtractEditText = null;
       mExtractAccessories = null;
       mExtractAction = null;
       mFullscreenApplied = false;
       mCandidatesFrame = mRootView.findViewById(android.R.id.candidatesArea);
       mInputFrame = mRootView.findViewById(android.R.id.inputArea);
       mInputView = null;
       mIsInputViewShown = false;
       mExtractFrame.setVisibility(View.GONE);
       mCandidatesVisibility = getCandidatesHiddenVisibility();
       mCandidatesFrame.setVisibility(mCandidatesVisibility);
       mInputFrame.setVisibility(View.GONE);
   }

To move the input method up, you tried to start with the attribute parameter of the window, but it failed, because setting the y parameter is invalid for the full screen input method. When the onCreate method of the service new SoftInputWindow is passed in Gravity and Bottom, the input method will display the Bottom by default? When debugging, it is changed to Top, which is still displayed at the Bottom, which is difficult to understand.

FullscreenArea = mRootView.findViewById(com.android.internal.R.id .fullscreenArea); You can't see the specific resources. This should cover the whole screen

To sum up, the input method is similar to the following layout. The screen rotation will not be discussed temporarily. The Gravity will be updated in the SoftInputWindow,

To handle the move up problem, move the mInputFrame up,

How? The mInputFrame itself is a Framelayout, and the location is written dead in the android resource file. It moves dynamically through the code?

I thought about WindowManager's updateLayout, but what about the layout parameters?

Or call setY directly, but the problem is that the effect is similar to animation. The original View does not move, which makes the click event unavailable,

Or the moveTask method of view? It doesn't feel good,

In general, the InputMethodService class needs to be inherited when three-party custom input methods are used. This is a standard,

If the onCreateVIew method is overridden, the user-defined input method layout will be passed in. The system calls back through the following methods,

public void updateInputViewShown() {
       boolean isShown = mShowInputRequested && onEvaluateInputViewShown();
       if (mIsInputViewShown != isShown && mDecorViewVisible) {
           mIsInputViewShown = isShown;
           mInputFrame.setVisibility(isShown ? View.VISIBLE : View.GONE);
           if (mInputView == null) {
               initialize();
               View v = onCreateInputView();
               if (v != null) {
                   setInputView(v);
               }
           }
       }
   }

After that, set the field of view displayed in front of the user through the setInputView method. You can see that the field of view is added to the mInputFrame. For another method, setCandidatesView, it is the candidate view. Not to mention the candidate for the moment.

public void setInputView(View view) {
       mInputFrame.removeAllViews();
       mInputFrame.addView(view, new FrameLayout.LayoutParams(
               ViewGroup.LayoutParams.MATCH_PARENT,
               ViewGroup.LayoutParams.WRAP_CONTENT));
       mInputView = view;
   }

So we need to move the input method. We can do an article here, that is, add a parameter and move the mInputView up a little,

FrameLayout.LayoutParams provides the bottomMargin parameter, that is to move our mInputView a little distance from the bottom. The unit is pixel, not dp

Keywords: Java Android

Added by stoop on Wed, 10 Nov 2021 14:49:33 +0200