Анимация макета не работает при первом запуске - PullRequest
42 голосов
/ 21 декабря 2010

У меня есть действие со списком элементов, и когда вы нажимаете на элемент, я хочу, чтобы элементы управления воспроизведением этого элемента скользили вверх из нижней части экрана и становились видимыми.Я определил набор анимации для слайда и слайда, и они работают.Я настроил свой animationListener в своей деятельности и начал мой слайд в анимации при щелчке элемента.Моя проблема в том, что при первом запуске приложения, когда я нажимаю на элемент, выполняется обратный вызов onClick, но анимация не происходит.Второй раз, когда я нажимаю, происходит слайд в анимации, но не слайд.В третий и последующий раз все работает как положено.Вот мои наборы анимации.

vm_slide_in.xml

    <?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" 
           android:fillAfter="true">
    <translate
        android:fromYDelta="800"
        android:toYDelta="0"
        android:duration="600" />
</set>

vm_slide_out.xml

    <?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" 
           android:fillAfter="true">
    <translate
        android:fromYDelta="0"
        android:toYDelta="800"
        android:duration="600" />
</set>

Вот макет моей активности

    <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    style="@style/AppBG">
    <RelativeLayout 
        style="@style/LogoBar" 
        android:id="@+id/logo_bar"      
        android:layout_alignParentTop="true">
        <include layout="@layout/logobar"></include>
    </RelativeLayout>
    <RelativeLayout 
        style="@style/TitleBar" 
        android:id="@+id/title_bar"     
        android:layout_below="@+id/logo_bar">
        <include layout="@layout/titlebar"></include>"
        <Button style="@style/TitleBarButton"
            android:id="@+id/vm_speaker_btn"
            android:text="@string/vm_speaker_btn_label" 
            android:layout_alignParentLeft="true"
            android:layout_margin="4dp">
        </Button>
        <Button style="@style/TitleBarButton"
            android:id="@+id/vm_edit_btn"
            android:text="@string/vm_edit_btn_label" 
            android:layout_alignParentRight="true"
            android:layout_margin="4dp">
        </Button>
    </RelativeLayout>
    <ListView
        android:id="@+id/@android:id/list"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/title_bar"/>
    <RelativeLayout
        android:id="@+id/vm_control_panel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@+id/footer"
        android:visibility="gone">
        <include layout="@layout/vm_control"/>
    </RelativeLayout>
    <RelativeLayout
        android:id="@+id/footer"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true">
        <include layout="@layout/taskbar"/>
    </RelativeLayout>
</RelativeLayout>

Вот макет для включенного элемента управления

    <?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
    <RelativeLayout 
        android:id="@+id/vm_control"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="@color/dark_grey">
        <TextView
            android:id="@+id/vm_ctl_branding"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="5dp"
            android:text="@string/branding"
            android:textColor="@color/white">
        </TextView>
        <TextView style="@style/TimeMark"
            android:id="@+id/vm_timestamp"
            android:layout_toLeftOf="@+id/vm_progress"
            android:layout_below="@+id/vm_ctl_branding"
            android:layout_marginRight="3dp"
            android:text="0:00">
        </TextView>
        <SeekBar
            android:id="@+id/vm_progress"
            android:layout_width="200dp"
            android:layout_height="wrap_content"
            android:layout_below="@+id/vm_ctl_branding"
            android:layout_centerHorizontal="true">
        </SeekBar>
        <TextView style="@style/TimeMark"
            android:id="@+id/vm_timeleft"
            android:layout_toRightOf="@+id/vm_progress"
            android:layout_below="@+id/vm_ctl_branding"
            android:layout_marginLeft="3dp"
            android:text="-0:00">
        </TextView>
        <LinearLayout
            android:id="@+id/vm_action_button_layout"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_alignLeft="@+id/vm_timestamp"
            android:layout_alignRight="@+id/vm_timeleft"
            android:orientation="horizontal"
            android:layout_below="@+id/vm_progress">
            <TextView style="@style/Vm_Action_Button"
                android:background="@drawable/vm_action_btn_call"
                android:id="@+id/vm_callback_btn"
                android:layout_marginRight="5dp"
                android:text="@string/vm_action_btn_callback">
            </TextView>
            <TextView style="@style/Vm_Action_Button"
                android:background="@drawable/vm_action_btn_delete"
                android:id="@+id/vm_delete_btn"
                android:layout_marginLeft="5dp"
                android:text="@string/vm_action_btn_delete">
            </TextView>
        </LinearLayout>
    </RelativeLayout>
</merge>

Из моего метода onCreate ...

// Handle list item selections
ListView lv = getListView();
lv.setOnItemClickListener(new OnItemClickListener() {
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        final Voicemail vmItem = (Voicemail) vmla.getItem(position);
        Toast.makeText(ctx, "Name: " + vmItem.getCallerName() + " Position: " + position, Toast.LENGTH_SHORT)
                .show();
        vVm_controls.startAnimation(mSlideIn);
    }
});

И моих обратных вызовов анимации ...

@Override
public void onAnimationStart(Animation animation) {
    vm_controls_in = !vm_controls_in;
    if (vm_controls_in) {
        vVm_controls.setVisibility(View.GONE);
    } else {
        vVm_controls.setVisibility(View.VISIBLE);
        // vVm_controls.bringToFront();
    }
}

@Override
public void onAnimationEnd(Animation animation) {
    if (!vm_controls_in) {
        try {
            Thread.sleep(1000);
            vVm_controls.startAnimation(mSlideOut);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

@Override
public void onAnimationRepeat(Animation animation) {
    // TODO Auto-generated method stub

}

Ответы [ 7 ]

111 голосов
/ 12 марта 2012

Как вы обнаружили, проблема заключается в видимости.Когда представление изначально установлено как пропавшее в файле xml, Android не будет отображать макет, пока видимость не будет изменена на видимую или невидимую.Если вы попытаетесь анимировать представление, которое еще не было отрисовано, анимация будет происходить в представлении без макета.После завершения анимации она будет визуализирована, и вид внезапно появится без анимации.Это работает в последующее время, потому что представление имеет макет, даже если для него установлено значение.Когда анимация происходит в первый раз, вид появляется и будет двигаться, как и ожидалось.

11 голосов
/ 21 декабря 2010

Конечно, не через 20 минут после публикации этого вопроса я разобрался в своей проблеме.Так как я устанавливал видимость моего макета на «GONE», когда я пытался запустить анимацию, он не запускался с первого раза.Не уверен, почему это происходит во 2-й и последующие периоды, но если я установил видимость «VISIBLE» прямо перед тем, как запустить анимацию, это решило проблему.Вот код, где я его изменил ...

// Handle list item selections
ListView lv = getListView();
lv.setOnItemClickListener(new OnItemClickListener() {
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        final Voicemail vmItem = (Voicemail) vmla.getItem(position);
        Toast.makeText(ctx, "Name: " + vmItem.getCallerName() + " Position: " + position, Toast.LENGTH_SHORT)
                .show();
        vVm_controls.setVisibility(View.VISIBLE);
        vVm_controls.startAnimation(mSlideIn);
    }
});
5 голосов
/ 15 июня 2015

Я не знаю, является ли это все еще актуальным, но да, это проблема с видимостью. Поэтому я установил видимость в xml-файле на невидимый и вызывал в том месте, где инициализируется ваше представление:

view.post(new Runnable() {
    @Override
    public void run() {
        view.animate().translationY(view.getHeight());
    }
};

Теперь звонок

view.animate().translationY(0).setListener(new AnimatorListenerAdapter() {
    @Override
    public void onAnimationStart(Animator animation) {
        super.onAnimationStart(animation);
        view.setVisibility(View.VISIBLE);
    }
}

работает и в первый раз.

2 голосов
/ 01 апреля 2017

У меня была точно такая же проблема, хотя я устанавливал видимость в начале анимации.Я последовал совету Брокколи и сделал его видимым, прежде чем запустить анимацию, и это сработало как шарм.

ДО:

Animation animation = AnimationUtils.loadAnimation(getContext(), R.anim.slide_left);
animation.setAnimationListener(new Animation.AnimationListener() {
    @Override
    public void onAnimationStart(Animation animation) {
        view.setVisibility(View.VISIBLE);
    }

    @Override
    public void onAnimationEnd(Animation animation) { }

    @Override
    public void onAnimationRepeat(Animation animation) {       }
);
view.startAnimation(animation);

ПОСЛЕ:

Animation animation = AnimationUtils.loadAnimation(getContext(), R.anim.slide_left);
view.setVisibility(View.VISIBLE);
view.startAnimation(animation);
1 голос
/ 12 августа 2016

У меня была похожая проблема в Android 4.4.3.Я перепробовал большую часть предложенного решения, но только одно решение сработало для меня.Вы должны запустить анимацию после того, как окно завершит рендеринг, и лучший способ - запустить ее внутри onWindowFocusChanged .Не используйте задержку при запуске, так как это повлияет на производительность вашего приложения на высокоскоростных телефонах.

@Override
public void onWindowFocusChanged (boolean hasFocus) {
   super.onWindowFocusChanged(hasFocus);
   if (hasFocus)
      yourView.startAnimation(anim);
}

Более подробную информацию можно найти в этом сообщении: https://damianflannery.wordpress.com/2011/06/08/start-animation-in-oncreate-or-onresume-on-android/

0 голосов
/ 02 января 2019

Я знаю, что этот вопрос старый, но мой ответ может помочь другим. Когда нам нужно анимировать вид, но по умолчанию его видимость исчезла тогда, пожалуйста, установите все свойства скрыть код в XML Для моего случая я использовал перевод Y и альфа в Java-файле. Я сделал простые вещи, чтобы решить проблему при первом запуске. Затем добавлены все атрибуты в XML, которые используются в коде.

0 голосов
/ 07 июня 2014

У меня была точно такая же проблема, но с использованием ViewPropertyAnimator.Например, вы объявляете GridView с именем mGridView.Все, что вам нужно сделать сейчас, это позвонить mGridView.animate() с нужными вам изменениями.

Анимация моего GridView была запущена, но из-за неизвестных обстоятельств не было видимой реальной анимации.Я также изменил все View.GONE на View.VISIBLE, но это ничего не изменило.В моем случае я понял, что мне просто нужно удалить android:requiresFadingEdge="vertical" в моем XML этого конкретного GridView.Может быть невозможно использовать Fading Edge в сочетании с ViewPropertyAnimator.

...