Wie kann man die Layout-Eigenschaften von ViewGroups animieren?

Ich habe folgendes Layout:

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_height="match_parent" android:layout_width="match_parent"> <FrameLayout android:id="@+id/viewgroup_left" android:layout_height="match_parent" android:layout_weight="2" android:layout_width="0dp"> ... children ... </FrameLayout> <LinearLayout android:id="@+id/viewgroup_right" android:layout_height="match_parent" android:layout_weight="1" android:layout_width="0dp" android:orientation="vertical"> ... children ... </LinearLayout> </LinearLayout> 

Ich komme mit so etwas wie folgt aus:

  +------------------------+------------+ | | | | | | | Left | Right | | | | | | | +------------------------+------------+ 

Wenn ein bestimmter Toggle umgeschaltet wird, möchte ich Left animieren, damit seine Breite erweitert wird, um den gesamten Bildschirm zu füllen. Gleichzeitig möchte ich die Breite von rechts animieren, damit sie auf Null schrumpft. Später, wenn der Toggle wieder umgeschaltet wird, muss ich die Dinge in den oben genannten Zustand wiederherstellen.

Ich habe versucht, meine eigene Animation zu schreiben, die View.getWidth() anruft, aber wenn ich auf diesen Wert View.getLayoutParams().width indem View.getLayoutParams().width , ist es breiter als wenn es angefangen hat. Ich vermute, ich mache es einfach falsch Ich habe auch alle Unterlagen über die Waben-Animations-Sachen gelesen, aber ich möchte nicht übersetzen oder skalieren … Ich möchte die Layout-Breite-Eigenschaft animieren. Ich kann kein Beispiel dafür finden.

Was ist der richtige Weg, dies zu tun?

3 Solutions collect form web for “Wie kann man die Layout-Eigenschaften von ViewGroups animieren?”

Da hat mir noch niemand geholfen und meine erste Antwort war so ein Chaos, ich werde versuchen, dir die richtige Antwort zu geben 😉

Eigentlich mag ich die Idee und ich denke, das ist eine großartige visuelle Wirkung, die für eine Gruppe von Menschen nützlich sein könnte. Ich würde einen Überlauf der richtigen Ansicht implementieren (ich denke, das Schrumpfen sieht seltsam aus, da der Text nach unten expandiert).

Aber trotzdem ist hier der Code, der ganz gut funktioniert (man kann sogar umschalten, während er animiert).

Schnelle erklärung :
Sie rufen mit einem Booleschen für Ihre Richtung an und dies startet eine Handler Animation Call Loop. Dies erhöht oder verringert die Gewichte beider Ansichten auf der Grundlage der Richtung und der vergangenen Zeit (für eine reibungslose Berechnung und Animation). Die Animationsrufschleife ruft sich auf, solange sie die Start- oder Endposition nicht erreicht hat.

Das Layout:

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent" android:weightSum="10" android:id="@+id/slide_layout"> <TextView android:layout_weight="7" android:padding="10dip" android:id="@+id/left" android:layout_width="0dip" android:layout_height="fill_parent"></TextView> <TextView android:layout_weight="3" android:padding="10dip" android:id="@+id/right" android:layout_width="0dip" android:layout_height="fill_parent"></TextView> </LinearLayout> 

Die Aktivität:

 public class TestActivity extends Activity { private static final int ANIMATION_DURATION = 1000; private View mSlidingLayout; private View mLeftView; private View mRightView; private boolean mAnimating = false; private boolean mLeftExpand = true; private float mLeftStartWeight; private float mLayoutWeightSum; private Handler mAnimationHandler = new Handler(); private long mAnimationTime; private Runnable mAnimationStep = new Runnable() { @Override public void run() { long currentTime = System.currentTimeMillis(); float animationStep = (currentTime - mAnimationTime) * 1f / ANIMATION_DURATION; float weightOffset = animationStep * (mLayoutWeightSum - mLeftStartWeight); LinearLayout.LayoutParams leftParams = (LinearLayout.LayoutParams) mLeftView.getLayoutParams(); LinearLayout.LayoutParams rightParams = (LinearLayout.LayoutParams) mRightView.getLayoutParams(); leftParams.weight += mLeftExpand ? weightOffset : -weightOffset; rightParams.weight += mLeftExpand ? -weightOffset : weightOffset; if (leftParams.weight >= mLayoutWeightSum) { mAnimating = false; leftParams.weight = mLayoutWeightSum; rightParams.weight = 0; } else if (leftParams.weight <= mLeftStartWeight) { mAnimating = false; leftParams.weight = mLeftStartWeight; rightParams.weight = mLayoutWeightSum - mLeftStartWeight; } mSlidingLayout.requestLayout(); mAnimationTime = currentTime; if (mAnimating) { mAnimationHandler.postDelayed(mAnimationStep, 30); } } }; private void toggleExpand(boolean expand) { mLeftExpand = expand; if (!mAnimating) { mAnimating = true; mAnimationTime = System.currentTimeMillis(); mAnimationHandler.postDelayed(mAnimationStep, 30); } } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.slide_test); mLeftView = findViewById(R.id.left); mRightView = findViewById(R.id.right); mSlidingLayout = findViewById(R.id.slide_layout); mLeftStartWeight = ((LinearLayout.LayoutParams) mLeftView.getLayoutParams()).weight; mLayoutWeightSum = ((LinearLayout) mSlidingLayout).getWeightSum(); } } 

Nur meine 2 Cent hier zu knickedis exzellenter Antwort hinzufügen – nur für den Fall, dass jemand es braucht:

Wenn Sie mit Gewichten animieren, werden Sie am Ende mit Problemen mit Clipping / Nicht-Clipping auf enthaltenen Ansichten und Viewgroups. Dies gilt insbesondere, wenn Sie Viewgroups mit Gewicht als Fragmentbehälter verwenden. Um es zu überwinden, müssten Sie auch die Margen der problematischen Kinderansichten und Viewgroups / Fragment-Container animieren.

Und um all diese Dinge zusammen zu machen, ist es immer besser, für ObjectAnimator und AnimatorSet zu gehen (wenn man sie benutzen kann), zusammen mit einigen Utility-Klassen wie MarginProxy

Ein anderer Weg zur Lösung von @knickedi ist die Verwendung von ObjectAnimator anstelle von Runnable. Die Idee ist, ObjectAnimator zu verwenden, um das Gewicht der linken und rechten Ansichten anzupassen. Die Ansichten müssen jedoch angepasst werden, damit das Gewicht als Eigenschaft für den ObjectAnimator zum Animieren ausgesetzt werden kann.

Also zuerst eine benutzerdefinierte Ansicht definieren (mit einem LinearLayout als Beispiel):

 public class CustomLinearLayout extends LinearLayout { public CustomLinearLayout(Context context) { super(context); } public CustomLinearLayout(Context context, AttributeSet attrs) { super(context, attrs); } public CustomLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } public void setMyWeight(float value) { LinearLayout.LayoutParams p = (LinearLayout.LayoutParams)getLayoutParams(); p.weight = value; requestLayout(); } } 

Dann aktualisiere das Layout-XML, um dieses benutzerdefinierte lineare Layout zu verwenden.

Dann, wenn du die Animation umschalten musst, benutze ObjectAnimator:

 ObjectAnimator rightView = ObjectAnimator.ofFloat(viewgroup_right, "MyWeight", 0.5f, 1.0f); ObjectAnimator leftView = ObjectAnimator.ofFloat(viewgroup_left, "MyWeight", 0.5f, 0.0f); AnimatorSet animatorSet = new AnimatorSet(); animatorSet.setDuration(1000); // 1 second of animation animatorSet.playTogether(rightView, leftView); animatorSet.start(); 

Der obige Code geht davon aus, dass beide Ansichten ein lineares Layout sind und mit einem halben Gewicht beginnen. Die Animation erweitert die richtige Ansicht auf das volle Gewicht (so dass die linke versteckt ist). Beachten Sie, dass ObjectAnimator mit der Eigenschaft "MyWeight" des angepassten linearen Layouts animiert wird. Das AnimatorSet wird verwendet, um sowohl linke als auch rechte ObjectAnimatoren zusammen zu binden, so dass die Animation glatt aussieht.

Dieser Ansatz reduziert die Notwendigkeit, Runnable Code und die Gewichtsberechnung in ihm zu schreiben, aber es braucht eine benutzerdefinierte Klasse definiert werden.

  • Android - Image Warp-Effekt
  • ViewGroup beenden das Ereignis
  • Android: mit MotionEvent zu tun Drag & Drop Positionierung von Views in einer benutzerdefinierten ViewGroup
  • Benutzerdefinierte ViewGroup-Fokusbehandlung
  • Aufbau eines Zoom-fähigen Containers
  • Kraft auf Layout in einem SubView, dessen Dimensionen sich nicht ändern
  • Android machen benutzerdefinierte Layout Form
  • Compound Controls Weiterleitung State
  • Android View und ViewGroup
  • Warum für Constraints Layout gehen, da wir bereits Relatives Layout haben?
  • So erstellen Sie benutzerdefinierte Viewgroup in Android mit Beispiel
  • Das Android ist ein Google Android Fan-Website, Alles über Android Phones, Android Wear, Android Dev und Android Spiele Apps und so weiter.