android - example - material design transitions
Animar el cambio de diseƱo de la hoja inferior. (4)
No estoy seguro de si eso es lo que quiere, pero tal vez en lugar de usar la transición, puede usar la función animate()
ya que con esta función puede cambiar todo lo relacionado con su animación (tiempo, visibilidad, etc.).
En mi aplicación, uso una hoja inferior (de la biblioteca de soporte) que funciona muy bien. Ahora me gustaría animar un cambio de diseño mientras la hoja se arrastra hacia arriba. Para esto, he creado una subclase de BottomSheetCallback
(esto normalmente es una clase interna de un Fragmento, por lo que no todos los objetos utilizados en este calss se inicializan aquí):
public class MyBehavior extends BottomSheetBehavior.BottomSheetCallback {
Transition transition;
float lastOffset = 0;
Scene scene;
public PlayerBehavior() {
TransitionInflater inflater = TransitionInflater.from(getContext());
transition = inflater.inflateTransition(R.transition.player);
//transition.setDuration(300);
scene = fullLayout;
transition.setInterpolator(new Interpolator() {
@Override
public float getInterpolation(float v) {
return lastOffset;
}
});
}
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
if(newState == BottomSheetBehavior.STATE_DRAGGING) {
TransitionManager.go(scene, transition);
}
}
@Override
public void onSlide(View bottomSheet, final float slideOffset) {
scene = (slideOffset > lastOffset) ? smallLayout : fullLayout;
lastOffset = slideOffset;
}
}
Como puede ver, también creé dos Escenas de diferentes archivos de diseño y una Transition
personalizada para animar entre las escenas con el TransitionManager
. Mi problema es que la Transition
debe basar en el parámetro slideOffset
(en el rango de 0-1) pero el TransitionManager
usa la clase de Animation
en el fondo, que normalmente se basa en el tiempo en Android.
Intenté crear el Intapolator personalizado pero esto no funciona correctamente. Entonces, ¿cómo puedo crear una Transition
que se base en una variable externa y no a tiempo?
Para deslizar fácilmente algo de la parte inferior de la pantalla, puede usar un código como:
final int activityHeight = findViewById(android.R.id.content).getHeight();
cardContainer.animate().yBy(activityHeight - cardContainer.getY()).setDuration(SLIDE_OUT_DURATION);
donde cardContainer
es la vista que está intentando deslizar fuera de la pantalla.
Ver esta entrada de blog para el ejemplo completo. Tenga en cuenta que también puede usar la translationY
lugar de yBy
. Otra forma más genérica de hacerlo es con este código:
public static ViewPropertyAnimator slideOutToBottom(Context ctx, View view) {
final int screenHeight = ctx.getResources().getDisplayMetrics().heightPixels;
int[] coords = new int[2];
view.getLocationOnScreen(coords);
return view.animate().translationY(screenHeight - coords[Y_INDEX]).setDuration(SLIDE_OUT_DURATION);
}
public static ViewPropertyAnimator slideInFromBottom(Context ctx, View view) {
final int screenHeight = ctx.getResources().getDisplayMetrics().heightPixels;
int[] coords = new int[2];
view.getLocationOnScreen(coords);
view.setTranslationY(screenHeight - coords[Y_INDEX]);
return view.animate().translationY(0).setDuration(SLIDE_IN_DURATION).setInterpolator(new OvershootInterpolator(1f));
}
Según su descripción, creo que está intentando lograr algo como el comportamiento de la hoja inferior de Google Maps. El diseño cambia a medida que la hoja inferior se arrastra hacia arriba.
Si eso es lo que está tratando de lograr, entonces no necesita imponer animaciones personalizadas, ya que el mismo diálogo de la hoja inferior tiene ese comportamiento de animación cuando se incorpora dentro de un diseño de coordinador principal.
Aquí hay un código de ejemplo de cómo estoy implementando el mismo comportamiento. También hace que el FloatingActionButton sea invisible cuando la hoja inferior se arrastra hasta el tamaño de pantalla completa:
Cree un diálogo de hoja inferior que desee usar dentro de su diseño principal
public class CustomBottomDialog extends BottomSheetDialogFragment { String mSomeName; @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); // if some arguments are passed from the calling activity mSomeName = getArguments().getString("some_name"); } @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View bottomSheet = inflater.inflate(R.layout.bottomsheet_layout, container, false); // initialise your bottomsheet_layout items here TextView tvName = bottomSheet.findViewById(R.id.display_name); tvName.setText(mSomeName); tvName.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // do something here ((MainActivity)getActivity()).doSomething(); } }); return bottomSheet; } }
bottomsheet_layout:
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.design.widget.FloatingActionButton android:id="@+id/nav" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/navigation_tilt_grey" app:backgroundTint="@color/colorAccent" app:elevation="3dp" app:fabSize="normal" android:layout_marginEnd="@dimen/activity_horizontal_margin" app:layout_anchor="@+id/live_dash" app:layout_anchorGravity="top|right" /> <!--BottomSheet--> <android.support.v4.widget.NestedScrollView android:id="@+id/live_dash" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#F3F3F3" android:clipToPadding="true" app:layout_behavior="android.support.design.widget.BottomSheetBe havior" tools:layout_editor_absoluteY="150dp"> <!--Include your items here, the height of all items combined will take the main screen layout size with animation--> </android.support.v4.widget.NestedScrollView> </android.support.design.widget.CoordinatorLayout>
Llamando a esta Hoja de Fondo de tu actividad:
public void notifyBottomSheet(String somename){ BottomSheetDialogFragment customDialogFragment = new CustomBottomDialog(); Bundle args = new Bundle(); args.putString("some_name", somename); customDialogFragment.setArguments(args); customDialogFragment.show(getSupportFragmentManager(), customDialogFragment.getTag()); customDialogFragment.setCancelable(false); // if you don''t wish to hide }
Espero que esto resuelva lo que estás tratando de lograr.
## Translation Animation ##
<?xml version="1.0" encoding="utf-8"?>
<set
xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:fillAfter="true"
>
<translate
android:fromYDelta="100%p"
android:toYDelta="-30%p"
android:duration="900" />
</set>
## Actividad principal ##
@Override
protected void onResume() {
super.onResume();
Animation am= AnimationUtils.loadAnimation(this,R.anim.fadeout);
tv5.startAnimation(am);
Animation myanim= AnimationUtils.loadAnimation(this,R.anim.translate);
tv1.startAnimation(myanim);
myanim.setStartOffset(500);
Animation animation= AnimationUtils.loadAnimation(this,R.anim.translate);
animation.setStartOffset(1000);
tv2.startAnimation(animation);
Animation an= AnimationUtils.loadAnimation(this,R.anim.translate);
an.setStartOffset(1500);
tv3.startAnimation(an);
Animation ab= AnimationUtils.loadAnimation(this,R.anim.translate);
ab.setStartOffset(2000);
tv4.startAnimation(ab);
Animation ac= AnimationUtils.loadAnimation(this,R.anim.fadein);
ac.setStartOffset(2500);
btn1.startAnimation(ac);
}