webentwicklung-frage-antwort-db.com.de

Animieren Sie die Layoutänderung des unteren Blattes

In meiner Anwendung verwende ich ein unteres Blatt (aus der Support-Bibliothek), das hervorragend funktioniert. Jetzt möchte ich eine Layoutänderung animieren, während das Blatt nach oben gezogen wird. Hierfür habe ich eine Unterklasse von BottomSheetCallback erstellt (dies ist normalerweise eine innere Klasse eines Fragments, daher werden nicht alle in dieser Klasse verwendeten Objekte hier initialisiert):

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;
    }
}

Wie Sie sehen, habe ich auch zwei Scene aus verschiedenen Layoutdateien und eine benutzerdefinierte Transition erstellt, um die Szenen mit der TransitionManager zu animieren. Mein Problem ist, dass die Transition auf dem slideOffset-Parameter (im Bereich von 0-1) basieren sollte, die TransitionManager jedoch die Animation-Klasse im Hintergrund verwendet, die normalerweise auf Android basiert.

Ich habe versucht, den benutzerdefinierten Intapolator zu erstellen, dies funktioniert jedoch nicht ordnungsgemäß. Wie kann ich also eine Transition erstellen, die auf einer externen Variablen basiert und nicht rechtzeitig?

26
Cilenco

Basierend auf Ihrer Beschreibung, denke ich, versuchen Sie so etwas wie Google Maps-Bottom-Sheet-Verhalten. Das Layout ändert sich, wenn das Bottomsheet nach oben gezogen wird.

Wenn Sie dies erreichen möchten, müssen Sie keine benutzerdefinierten Animationen erzwingen, da der bottomsheetdialog selbst dieses Animationsverhalten aufweist, wenn er in ein übergeordnetes Koordinatorlayout integriert ist.

Hier ist ein Beispielcode, wie ich dasselbe Verhalten implementiere. Dadurch wird FloatingActionButton unsichtbar, wenn das Bottom Sheet auf die volle Bildschirmgröße gezogen wird:

  1. Erstellen Sie ein unteres Dialogfenster, das Sie in Ihrem Hauptlayout verwenden möchten

    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;
    }
    }
    
  2. 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>
    
  3. Aufruf dieses BottomSheet aus Ihrer Aktivität:

    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
    }
    

    Hoffe, das löst, was du erreichen willst.

1
Prashant Kumar
## 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>

## Hauptaktivität ##

@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);
}
0
akshat saini

Um etwas vom unteren Rand des Bildschirms zu verschieben, können Sie folgenden Code verwenden:

final int activityHeight = findViewById(Android.R.id.content).getHeight();
cardContainer.animate().yBy(activityHeight - cardContainer.getY()).setDuration(SLIDE_OUT_DURATION);

dabei ist cardContainer die Ansicht, die Sie vom Bildschirm verschieben möchten.

In diesem Blogbeitrag finden Sie das vollständige Beispiel. Beachten Sie, dass Sie anstelle von translationY auch yBy verwenden können. Eine andere, allgemeinere Methode ist der folgende Code:

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));
}
0

Ich bin mir nicht sicher, ob Sie das wollen, aber anstatt Übergang zu verwenden, können Sie die Funktion animate() verwenden, da Sie mit dieser Funktion alle Dinge zu Ihrer Animation (Zeit, Sichtbarkeit usw.) ändern können.

0
oumaya saratoon