-
-
Save grennis/2e3cd5f7a9238c59861015ce0a7c5584 to your computer and use it in GitHub Desktop.
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; | |
} | |
} | |
} | |
I am able to implement this and the status bar is not flickering anymore, need to let it run in Handler when calling "possiblyResizeChildOfContent". Not sure whether this works on anyone else, but give it a try. The code below is in Kotlin.
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() } }
For me this solution worked perfectly with windowSoftInputMode= adjustPan
and then adjusting my NestedScrollView's parent's top, start, end, and bottom constraints with the parent with 0dp
height
thanks.
Worked for me after I have replaced
int usableHeightNow = contentAreaOfWindowBounds.height();
with
int usableHeightNow = contentAreaOfWindowBounds.bottom;
otherwise I had a large gap at the bottom of the screen.
Thanks Bro it was a problem for me. But a little bit problem while launching the activity, splash like problem. If you found an answer please email me. [email protected]. I'll be waiting to your answer.
Can this be used in fragment...
Actually it works, it just flickers when keyboard size or visibility is changes.