2017-08-13 1 views
25

In meiner Anwendung verwende ich ein unteres Blatt (aus der Support-Bibliothek), die gut funktioniert. Jetzt möchte ich eine Layoutänderung animieren, während das Blatt hochgezogen wird. Dazu habe ich eine Unterklasse von BottomSheetCallback erstellt (dies ist normalerweise eine innere Klasse von einem Fragmente so dass nicht alle Objekte in dieser calss verwendet werden, hier initialisiert):Animate Layout Änderung des unteren Blattes

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, ich Scene aus verschiedenen auch zwei erstellt Layout-Dateien und eine benutzerdefinierte Transition zu animieren zwischen den Szenen mit der TransitionManager. Mein Problem ist, dass die Transition sollte auf dem slideOffset Parameter (im Bereich von 0-1) basieren, aber die TransitionManager verwendet die Animation Klasse im Hintergrund, die normalerweise in Android zeitbasiert ist.

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

+3

Können Sie ein visuelles Beispiel bereitstellen. Screenshots zum Beispiel? –

+0

Ich glaube nicht, dass es möglich ist. BottomSheet offset hat einen Wert von -1 bis 1 und springt nicht immer zwischen 0 und 1 oder -1 und 0. In einigen Fällen beginnt es bei 0.3 und geht bis zu 1.0f. Ich hatte in der Vergangenheit dasselbe Problem. Ich musste auf Ereignisse des Statuswechsels hören, die auf der Zeit basieren. –

+0

Welchen Animationstyp benötigen Sie? – Khemraj

Antwort

0

Ich bin nicht sicher, ob das das ist, was Sie wollen, aber vielleicht anstelle von Übergang, können Sie die Funktion animate() verwenden, da Sie mit dieser Funktion alle Dinge über Ihre Animation (Zeit, Sichtbarkeit etc.) ändern können.

0
## 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

Um etwas vom unteren Rand des Bildschirms leicht zu gleiten, Sie Code wie verwenden:

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

wo cardContainer ist die Ansicht, Sie versuchen, vom Bildschirm zu rutschen.

Siehe das blog post für das vollständige Beispiel. Beachten Sie, dass Sie auch translationY anstelle von yBy verwenden können. Ein andere, allgemeinere Art und Weise, es zu tun ist mit diesem 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)); 
} 
1

Basierend auf Ihrer Beschreibung, ich glaube, Sie versuchen, etwas zu erreichen, wie Google unteres Blatt Verhalten abbildet. Das Layout ändert sich, wenn die Unterseite nach oben gezogen wird.

Wenn das, was Sie versuchen dann zu erreichen, brauchen Sie nicht benutzerdefinierte Animationen zu erzwingen, da die bottomsheetdialog selbst jene Animation Verhalten hat, wenn innerhalb eines übergeordneten Coordinator Layout- eingebaut.

Hier ist ein Beispielcode, wie ich das gleiche Verhalten implementiere.Es macht auch die FloatingActionButton unsichtbar, wenn die bottomsheet bis auf volle Bildschirmgröße gezogen wird:

  1. eine bottomsheetdialog erstellen, die Sie

    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 in Ihrem Haupt-Layout verwenden möchten:

    <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. Dieses BottomSheet von Ihrer Aktivität aufrufen:

    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 das, was Sie erreichen möchten.

Verwandte Themen