My solution has a lot of different pieces, so I'll start with the full XML and java code, and then talk about the important bits:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<View
android:id="@+id/green"
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="#0f0" />
<View
android:id="@+id/red"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#f00"/>
</LinearLayout>
In the XML, the only really important part is that the red view uses a height of 0dp and weight of 1. This means it takes up all extra vertical space, which will be important when we get rid of the green view.
public class MainActivity extends AppCompatActivity {
private int originalHeight;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final View green = findViewById(R.id.green);
final View red = findViewById(R.id.red);
green.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
green.getViewTreeObserver().removeGlobalOnLayoutListener(this);
originalHeight = green.getHeight();
}
});
green.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
animateHeightOfView(green, originalHeight, 0);
}
});
red.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
animateHeightOfView(green, 0, originalHeight);
}
});
}
private void animateHeightOfView(final View view, int start, int end) {
ValueAnimator animator = ValueAnimator.ofInt(start, end);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
int height = (int) valueAnimator.getAnimatedValue();
ViewGroup.LayoutParams params = view.getLayoutParams();
params.height = height;
view.setLayoutParams(params);
}
});
animator.start();
}
}
In the Java, the two main parts are the ViewTreeObserver.OnGlobalLayoutListener and the animateHeightOfView() method.
The OnGlobalLayoutListener exists to capture the green view's original height. We have to use a listener to do this instead of just writing originalHeight = green.getHeight() inside onCreate() because the green view isn't actually laid out at that point, so getHeight() would return 0 if we tried that.
The animateHeightOfView() method leverages the ValueAnimator class to animate the height of whatever view you pass to it. Since there's no direct setter for a view's height, we can't use simpler methods like .animate(). We set up the ValueAnimator to produce int values on every frame, and then we use a ValueAnimator.AnimatorUpdateListener to modify the view's LayoutParams to set the height.
Feel free to play with it. I'm using click listeners to trigger the animation, and you mentioned focus, but you should be able to call animateHeightOfView() in a different way if it suits you.
