Skip to content

Instantly share code, notes, and snippets.

@wswenyue
Forked from grennis/SoftInputAssist.java
Last active April 17, 2024 08:33
Show Gist options
  • Save wswenyue/1f3fad03a6fcf9e07da3ed7171dbb0f7 to your computer and use it in GitHub Desktop.
Save wswenyue/1f3fad03a6fcf9e07da3ed7171dbb0f7 to your computer and use it in GitHub Desktop.
软键盘弹出-整体view布局向上推移
public class SoftInputAssist {
private View rootView;
private ViewGroup contentContainer;
private ViewTreeObserver viewTreeObserver;
private ViewTreeObserver.OnGlobalLayoutListener listener = () -> possiblyResizeChildOfContent();
private Rect contentAreaOfWindowBounds = new Rect();
private FrameLayout.LayoutParams rootViewLayout;
private int usableHeightPrevious = 0;
public SoftInputAssist(Activity activity) {
contentContainer = (ViewGroup) activity.findViewById(android.R.id.content);
rootView = contentContainer.getChildAt(0);
rootViewLayout = (FrameLayout.LayoutParams) rootView.getLayoutParams();
}
public void onPause() {
if (viewTreeObserver.isAlive()) {
viewTreeObserver.removeOnGlobalLayoutListener(listener);
}
}
public void onResume() {
if (viewTreeObserver == null || !viewTreeObserver.isAlive()) {
viewTreeObserver = rootView.getViewTreeObserver();
}
viewTreeObserver.addOnGlobalLayoutListener(listener);
}
public void onDestroy() {
rootView = null;
contentContainer = null;
viewTreeObserver = null;
}
private void possiblyResizeChildOfContent() {
contentContainer.getWindowVisibleDisplayFrame(contentAreaOfWindowBounds);
int usableHeightNow = contentAreaOfWindowBounds.height();
if (usableHeightNow != usableHeightPrevious) {
rootViewLayout.height = usableHeightNow;
rootView.layout(contentAreaOfWindowBounds.left, contentAreaOfWindowBounds.top, contentAreaOfWindowBounds.right, contentAreaOfWindowBounds.bottom);
rootView.requestLayout();
usableHeightPrevious = usableHeightNow;
}
}
}
@wswenyue
Copy link
Author

class SoftInputAssist(activity: Activity) {
    private var contentContainer: ViewGroup?
    private var rootView: View?
    private val rootViewLayout: FrameLayout.LayoutParams?

    private val contentAreaOfWindowBounds: Rect = Rect()
    private var viewTreeObserver: ViewTreeObserver? = null
    private var usableHeightPrevious = 0

    private val listener = OnGlobalLayoutListener {
        possiblyResizeChildOfContent()
    }

    init {
        contentContainer = activity.contentRootView as? ViewGroup
        rootView = contentContainer?.getChildAt(0)
        rootViewLayout = rootView?.layoutParams as? FrameLayout.LayoutParams
    }

    fun onPause() {
        if (viewTreeObserver != null && viewTreeObserver!!.isAlive) {
            viewTreeObserver?.removeOnGlobalLayoutListener(listener)
        }
    }

    fun onResume() {
        viewTreeObserver = rootView?.viewTreeObserver

        if (viewTreeObserver != null) {
            viewTreeObserver?.addOnGlobalLayoutListener(listener)
        }
    }

    fun onDestroy() {
        contentContainer = null
        rootView = null
        viewTreeObserver = null
    }

    private fun possiblyResizeChildOfContent() {
        runOnMainThread {
            contentContainer?.getWindowVisibleDisplayFrame(contentAreaOfWindowBounds)
            val usableHeightNow: Int = contentAreaOfWindowBounds.bottom

            if (usableHeightNow != usableHeightPrevious) {
                rootViewLayout?.height = usableHeightNow

                rootView?.layout(
                    contentAreaOfWindowBounds.left - (contentContainer?.x?.toInt() ?: 0),
                    contentAreaOfWindowBounds.top - (contentContainer?.y?.toInt() ?: 0),
                    contentAreaOfWindowBounds.right - (contentContainer?.x?.toInt() ?: 0),
                    contentAreaOfWindowBounds.bottom - (contentContainer?.y?.toInt() ?: 0)
                )

                rootView?.requestLayout()
                usableHeightPrevious = usableHeightNow
            }
        }
    }
}

val Activity.contentRootView: View?
    get() = window?.decorView?.findViewById(android.R.id.content) ?: findViewById(android.R.id.content)

private object ContextHandler {
    val handler = Handler(Looper.getMainLooper())
}

fun runOnMainThread(action: () -> Unit) {
    ContextHandler.handler.post {
        action()
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment