I have a fragment placed between two other views that I need to transition out of view smoothly. I have set up a fragment animation to scale the fragment out of view. This works fine. However, the fragment's view is immediately taken out of the view hierarchy as soon as the animation starts, causing the view below the fragment to collapse over the fragment's view. How can I get the view below the fragment to transition up and down smoothly with the scaling of the fragment?
Here is an example of what happens:
Here is MainActivity.java
public class MainActivity extends AppCompatActivity {
public final String TAG = "MainActivity";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btnHide = findViewById(R.id.btn_hide);
Button btnShow = findViewById(R.id.btn_show);
final FragmentManager fm = getSupportFragmentManager();
final Fragment fragment = fm.findFragmentById(R.id.frag_middle);
btnHide.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(fragment != null) {
FragmentTransaction ft = fm.beginTransaction();
ft.setCustomAnimations(R.anim.fade_in, R.anim.fade_out);
ft.hide(fragment);
ft.commit();
}else{
Log.d(TAG, "fragment is null!");
}
}
});
btnShow.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(fragment != null){
FragmentTransaction ft = fm.beginTransaction();
ft.setCustomAnimations(R.anim.fade_in, R.anim.fade_out);
ft.show(fragment);
ft.commit();
}else{
Log.d(TAG, "fragment is null!");
}
}
});
}
}
Here is activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="16dp"
tools:context=".MainActivity">
<TextView
android:id="@+id/tv_top"
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_marginStart="20dp"
android:layout_marginEnd="20dp"
android:padding="16dp"
android:text="TextViewTop"
android:textAlignment="center"
android:textStyle="bold"
android:textColor="@android:color/white"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:background="@color/colorPrimary"/>
<fragment
android:id="@+id/frag_middle"
android:name="my.packagename.mytestapplication.TestFragment"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/tv_top"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
<TextView
android:id="@+id/tv_bottom"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginEnd="20dp"
android:padding="16dp"
android:text="TextViewBottom"
android:textAlignment="center"
android:textStyle="bold"
android:textColor="@android:color/white"
app:layout_constraintTop_toBottomOf="@+id/frag_middle"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:background="@color/colorPrimary"/>
<Button
android:id="@+id/btn_hide"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hide Fragment"
app:layout_constraintTop_toBottomOf="@id/tv_bottom"
app:layout_constraintStart_toStartOf="parent"
/>
<Button
android:id="@+id/btn_show"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Show Fragment"
app:layout_constraintTop_toBottomOf="@id/tv_bottom"
app:layout_constraintEnd_toEndOf="parent"/>
Here is an example of the animation xml:
<?xml version="1.0" encoding="utf-8"?>
<set
xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="2000">
<scale
android:fromYScale="0"
android:toYScale="1"
android:fromXScale="1"
android:toXScale="1" />
Any help would be greatly appreciated! Thanks
There is easier way to implement this animation with Transition API
. TransitionManager
can handle and animate view or view hierarchy changes. When you hide/show fragment you just change visibility of fragment view.
private void toggle() {
final FragmentManager fm = getSupportFragmentManager();
final Fragment fragment = fm.findFragmentById(R.id.frag_middle);
ViewGroup parentViewGroup = findViewById(R.id.parentViewGroup);
TransitionManager.beginDelayedTransition(parentViewGroup, new AutoTransition());
FragmentTransaction ft = fm.beginTransaction();
if (show) {
ft.show(fragment);
} else {
ft.hide(fragment);
}
ft.commitNow();
show = !show;
}
Important thing here is to use commitNow
method instead of commit
. Because commitNow
execute fragment transaction immediately and thats why TransitionManager
handle view changes. With commit
it doesnt work because commit
executes transaction asynchronously.
<android.support.constraint.ConstraintLayout
...
android:id="@+id/parentViewGroup">
<fragment
android:id="@+id/frag_middle"
android:name="TestFragment"
android:layout_width="300dp"
android:layout_height="200dp"
app:layout_constraintTop_toBottomOf="@id/tv_top"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
</android.support.constraint.ConstraintLayout>
I've add width
and height
to fragment
in this xml. Here is result: