質問

I'm messing with PropertyAnimations. For this I have a simple (but verbose) setup to play around with. There are two Views which switch position on y-Axis by button click. While this translation, one View will get smaller the other one bigger by scaling the Views.

OK this works! But I discovered a really strange behaviour which surprises me. If I add a additional View in the layout where the other two View already are, the animation will change it's behavior!

There will be no normal y-Axis translation anymore, the animation will now translate the Views in a circle, means in x-Axis too. And I would like to know why is adding a simple View changing the whole animation?

I think I can't describe it better, so here is my complete setup to reproduce the problem. Just remove the View with the height of 1dp after your first button press and you will see.

This is my layout with the Views:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.inputtest.MainActivity$PlaceholderFragment" >

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:orientation="vertical">

        <TextView
               android:id="@+id/origin"
               android:layout_width="match_parent"
               android:layout_height="wrap_content"
               android:paddingLeft="20dp"
               android:paddingRight="20dp"
               android:text="FOO"/>

        <View 
            android:layout_width="wrap_content"
            android:layout_height="1dp"
            android:layout_marginTop="20dp"
            android:layout_marginBottom="20dp"
            android:background="#000000"/>

        <TextView
               android:id="@+id/destination"
               android:layout_width="match_parent"
               android:layout_height="wrap_content"
               android:paddingLeft="20dp"
               android:paddingRight="20dp"
               android:text="BAR"/>

    </LinearLayout>
    <Button
        android:id="@+id/switcher"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:text="Switch"/>

</LinearLayout>

This is the basic start Activity:

public class MainActivity extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if (savedInstanceState == null) {
            getSupportFragmentManager().beginTransaction()
                    .add(R.id.container, new PlaceholderFragment()).commit();
        }
    }

    public static class PlaceholderFragment extends Fragment {

        public PlaceholderFragment() {}

        TextView foo;
        TextView bar;

        @Override
        public View onCreateView(LayoutInflater inflater,
                ViewGroup container,
                Bundle savedInstanceState) {
            View rootView = inflater.inflate(R.layout.fragment_main, container,
                    false);

            foo = (TextView)rootView.findViewById(R.id.origin);
            bar = (TextView)rootView.findViewById(R.id.destination);

            Button btn = (Button)rootView.findViewById(R.id.switcher);
            btn.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {
                    AnimatorSet scale1 = null;
                    AnimatorSet scale2 = null;
                    ObjectAnimator translate1 = null;
                    ObjectAnimator translate2 = null;

                    if (foo.getTranslationY() == 0) {
                        translate1 = ObjectAnimator.ofFloat(foo, "translationY", bar.getTop());
                        translate2 = ObjectAnimator.ofFloat(bar, "translationY", bar.getTop()*(-1));
                        scale1 = (AnimatorSet)AnimatorInflater.loadAnimator(getActivity(), R.animator.scaler);
                        scale2 = (AnimatorSet)AnimatorInflater.loadAnimator(getActivity(), R.animator.scaler2);
                    } else {
                        translate1 = ObjectAnimator.ofFloat(foo, "translationY", 0);
                        translate2 = ObjectAnimator.ofFloat(bar, "translationY", 0);
                        scale1 = (AnimatorSet)AnimatorInflater.loadAnimator(getActivity(), R.animator.scaler2);
                        scale2 = (AnimatorSet)AnimatorInflater.loadAnimator(getActivity(), R.animator.scaler);
                    }

                    translate1.setDuration(500L);
                    translate2.setDuration(500L);

                    scale1.setTarget(foo);
                    scale2.setTarget(bar);

                    AnimatorSet set = new AnimatorSet();
                    set.playTogether(scale1, scale2, translate1, translate2);
                    set.start();
                }
            });
            return rootView;
        }
    }
}

The scaler.xml for the Animation:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" 
    android:ordering="sequentially">

    <set 
        android:ordering="together">

        <objectAnimator
            android:propertyName="scaleX"
            android:duration="250"
            android:valueTo="2.0"/>

        <objectAnimator
            android:propertyName="scaleY"
            android:duration="250"
            android:valueTo="2.0"/>

    </set>

    <set 
        android:ordering="together">

        <objectAnimator
            android:propertyName="scaleX"
            android:duration="250"
            android:valueTo="1.0"/>

        <objectAnimator
            android:propertyName="scaleY"
            android:duration="250"
            android:valueTo="1.0"/>
   </set>
</set>

The scaler2.xml for the Animation:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" 
    android:ordering="sequentially">

    <set 
        android:ordering="together">

        <objectAnimator
            android:propertyName="scaleX"
            android:duration="250"
            android:valueTo="0.5"/>

        <objectAnimator
            android:propertyName="scaleY"
            android:duration="250"
            android:valueTo="0.5"/>
    </set>

    <set 
        android:ordering="together">

    <objectAnimator
            android:propertyName="scaleX"
            android:duration="250"
            android:valueTo="1.0"/>

        <objectAnimator
            android:propertyName="scaleY"
            android:duration="250"
            android:valueTo="1.0"/>
   </set>
</set>
役に立ちましたか?

解決

I played around a bit and found the solution :) For me, the circle animation even appeared when there were only 2 views too, so I figured it got nothing to do with it, first I thought it' some layout limitation, I changed it to RelativeLayout, no difference... the reason is your scaling factor of 0.5 and 2.0! The view width gets doubled and halfed, so it appears the content is moving, but it's just scaled. If you change the scaleX property to 1.0f always, you will see only an y translation.

I'd advise to either create all animation in code or in xml, this seems a bit messy :) And what I wrote here might be interesting ... https://stackoverflow.com/a/22635237/2001247 .

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top