Sep 5, 2018 · 2 min read
Your solution by overriding onApplyWindowInsets is nice so far. But…
android:windowSoftInputMode="adjustResize"do not work with that :-(
here is my solution for that:
I use a custom behavior for my content View:
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="android.support.design.widget.FixScrollBehavior">this ist the behavior:
package android.support.design.widget;
import android.content.Context;
import android.graphics.Rect;
import android.support.v4.view.GravityCompat;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.WindowInsetsCompat;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import java.util.List;
import de.appsfactory.gamification2.sharedcomponents.R;
public class FixScrollBehavior extends AppBarLayout.ScrollingViewBehavior {
public FixScrollBehavior() {
}
public FixScrollBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void layoutChild(CoordinatorLayout parent, View child, int layoutDirection) {
final List<View> dependencies = parent.getDependencies(child);
final View header = findFirstDependency(dependencies);
if (header != null) {
final CoordinatorLayout.LayoutParams lp =
(CoordinatorLayout.LayoutParams) child.getLayoutParams();
final Rect available = mTempRect1;
available.set(parent.getPaddingLeft() + lp.leftMargin,
header.getBottom() + lp.topMargin,
parent.getWidth() - parent.getPaddingRight() - lp.rightMargin,
parent.getHeight() + header.getBottom()
- parent.getPaddingBottom() - lp.bottomMargin);
final WindowInsetsCompat parentInsets = parent.getLastWindowInsets();
if (parentInsets != null && ViewCompat.getFitsSystemWindows(parent)
&& !ViewCompat.getFitsSystemWindows(child)) {
// If we're set to handle insets but this child isn't, then it has been measured as
// if there are no insets. We need to lay it out to match horizontally.
// Top and bottom and already handled in the logic above
available.left += parentInsets.getSystemWindowInsetLeft();
available.right -= parentInsets.getSystemWindowInsetRight();
}
int bottomInset = 0;
if (parentInsets != null) {
bottomInset = parentInsets.getSystemWindowInsetBottom();
available.bottom -= bottomInset;
}
final Rect out = new Rect(available);
GravityCompat.apply(resolveGravity(lp.gravity), child.getMeasuredWidth(),
child.getMeasuredHeight() - bottomInset, available, out, layoutDirection);
final int overlap = getOverlapPixelsForOffset(header);
child.layout(out.left, out.top - overlap, out.right, out.bottom - (overlap));
if (child instanceof ViewGroup) {
ViewGroup group = (ViewGroup) child;
checkChildrenForResize(child, group);
}
} else {
// If we don't have a dependency, let super handle it
super.layoutChild(parent, child, layoutDirection);
}
}
private void checkChildrenForResize(View child, ViewGroup group) {
for (int i = 0; i < group.getChildCount(); i++) {
View c = group.getChildAt(i);
if (c instanceof ViewGroup) {
ViewGroup.LayoutParams params = c.getLayoutParams();
checkViewForResize(child, c, params);
}
}
}
private void checkViewForResize(View child, View c, ViewGroup.LayoutParams params) {
int height = child.getHeight();
if (params.height == ViewGroup.LayoutParams.MATCH_PARENT || isViewTagged(c, params, height)) {
c.setTag(R.id.TAG_MARK_MATCH_PARENT, true);
params.height = height;
c.setLayoutParams(params);
}
}
private boolean isViewTagged(View view, ViewGroup.LayoutParams params, int height) {
return params.height != height && view.getTag(R.id.TAG_MARK_MATCH_PARENT) != null && (Boolean) view.getTag(R.id.TAG_MARK_MATCH_PARENT);
}
private static int resolveGravity(int gravity) {
return gravity == Gravity.NO_GRAVITY ? GravityCompat.START | Gravity.TOP : gravity;
}
}this resource is needed too:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item type="id" name="TAG_MARK_MATCH_PARENT"/>
</resources>