2011-09-22 4 views
8

私は以下のレイアウトがあります。私はこのようなもので終わるViewGroupsのアニメーションレイアウトプロパティはどのようにしますか?

<?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> 

を:特定のトグルがトグルされると

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

、私はその幅がいっぱいに拡張されるように左をアニメーション化します画面全体。同時に、Rightの幅をアニメーション化してゼロに縮小したいと思います。後でトグルをもう一度切り替えると、私は物事を上記の状態に戻す必要があります。

View.getWidth()を呼び出す独自のアニメーションを作成しようとしましたが、設定した値(View.getLayoutParams().width)に戻ってアニメーションを開始したときよりも広いです。私はそれが間違っていると思う。ハニカムアニメーションのすべてのドキュメントも読んでいますが、翻訳や拡大/縮小はしたくありません...レイアウト幅のプロパティをアニメーション化したいと思います。私はこれの例を見つけることができません。

これを行う正しい方法は何ですか?誰もがまだあなたを助け、私の最初の答えは、私が正しい答えにあなたに実際に;-)

は、私がアイデアを気に入っこの時間を与えるためにみますと、私は、これは偉大な視覚効果であると考え、このような混乱だったので

答えて

12

たくさんの人々に役立つ可能性があります。私は右のビューのオーバーフローを実装するだろう(私はテキストが下部に拡大しているので、縮小が奇妙に見えると思う)。

しかし、とにかく、ここでは完璧に動作するコードがあります(アニメーション中に切り替えても可能です)。

クイック説明
あなたの方向のブールでtoggleを呼び出し、これはハンドラアニメーションコールループを開始します。これは、方向と過去の時間に基づいて両方のビューの重みを増減します(滑らかな計算とアニメーションのために)。アニメーションコールループは、開始位置または終了位置に達していない限り、それ自体を呼び出します。

レイアウト:

<?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> 

アクティビティ:

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(); 
    } 
} 
2

だけKnickediの優れた答えをここに私の2セントを追加する - 念のために誰かがそれを必要とする:

あなたが使用してアニメーション化した場合あなたが含まれているビューとビューグループのクリッピング/ノンクリッピングに関する問題を解決します。これは、フラグメントコンテナとしての重みを持つビューグループを使用する場合に特に当てはまります。これを克服するには、問題の子ビューとビューグループ/フラグメントコンテナのマージンをアニメートする必要があります。

そして、これらすべてのことを行うために、その常により良いによって投稿液にMarginProxy

1

のようないくつかのユーティリティクラスと一緒に、ObjectAnimatorとAnimatorSet(あなたがそれらを使用することができる場合)のために別の道を行くために@ knickediは、Runnableの代わりにObjectAnimatorを使用することです。この考え方は、ObjectAnimatorを使用して左右のビューの重みを調整することです。ただし、ObjectAnimatorがアニメートするためのプロパティとしてウェイトを公開できるように、ビューをカスタマイズする必要があります。

したがって、最初、(一例としてのLinearLayoutを使用して)カスタマイズされたビューを定義:

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

そして、このカスタム線形レイアウトを使用するレイアウトXMLを更新します。その後

、あなたが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(); 

上記のコードでは、両方のビューが線形レイアウトされているとして起動する重量で半分ある前提としています。アニメーションは、右のビューをフルウェイトに展開します(左のものは隠されています)。 ObjectAnimatorは、カスタマイズされた線形レイアウトの "MyWeight"プロパティを使用してアニメートされます。 AnimatorSetは、左右両方のObjectAnimatorを結合するために使用されるため、アニメーションは滑らかに見えます。

このアプローチでは、実行可能コードとその中の重み計算を書く必要はなくなりますが、カスタマイズされたクラスを定義する必要があります。

関連する問題