我有一个包含项目列表的活动,当您点击某个项目时,我希望该项目的播放控件从屏幕底部向上滑动并变为可见。我为幻灯片定义了一个动画集并且滑出了它们并且它们起作用。我已经在我的活动中设置了我的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
}
答案 0 :(得分:111)
正如您所发现的,问题在于可见性。当视图最初在xml文件中设置为已消失时,Android将不会呈现布局,直到可见性更改为可见或不可见。如果您尝试在尚未渲染的视图上设置动画,则动画将在没有布局的视图上进行。动画完成后,它将渲染它并突然显示视图而不显示动画。它随后会工作,因为即使设置为已经过去,视图也会有布局。
关键是将可见性设置为不可见而不是在xml文件中消失,以便将其呈现为隐藏状态。当动画第一次出现时出现动画并按预期移动。
答案 1 :(得分:11)
当然,在发布这个问题后20分钟,我发现了我的问题。因为我将布局的可见性设置为“GONE”,所以当我尝试在其上启动动画时,它没有第一次触发。不知道为什么它会在第二次及以后的时间进行,但如果我在开始动画之前将可见性设置为“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);
}
});
答案 2 :(得分:5)
我不知道它是否仍然是最新的但是,这是可见性的问题。因此,我将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);
}
}
也是第一次工作。
答案 3 :(得分:3)
目前的许多答案对我都不起作用,唯一有效的是使用 onFocusWindowChange()
,但我不喜欢该解决方案。
我解决这个问题的方法:首先在您的 xml 布局中将您尝试设置动画的当前 view
设置为 invisible
。
接下来在 onCreate
中向布局添加一个侦听器,以在 view
完成绘制时通知您:
mLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
mLayout.setVisibility(View.GONE);
mLayout.animate()
.translationX(-mLayout.getWidth());
mLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
});
在完成渲染后将其移出屏幕
答案 4 :(得分:2)
即使我在动画开始时将视图设置为可见,也会出现完全相同的问题。我遵循了brockoli的建议并在开始动画之前将其设置为可见,它就像一个魅力。
在:
@echo OFF
echo Installing service...
sc create "MyService" binpath= %~dp0\MyService.exe start= auto
sc start MyService
echo Installing service complete
pause
在:
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);
答案 5 :(得分:1)
我在Android 4.4.3中遇到了类似的问题。我尝试了大部分解决方案,但只有一种解决方案适合我。 您在窗口完成渲染后运行动画,最好的方法是在 onWindowFocusChanged 中运行它。不要通过runnable使用延迟,因为它会影响您在高速手机中的应用程序性能。
@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/
答案 6 :(得分:0)
我有完全相同的问题,但使用ViewPropertyAnimator
。例如,您声明了一个名为GridView
的{{1}}。您现在要做的就是给mGridView
调用所需的更改。
我的mGridView.animate()
动画被触发,但由于未知情况,没有可见的实际动画。我还将所有GridView
更改为View.GONE
,但它没有改变任何内容。在我的情况下,我发现,我只需删除此特定View.VISIBLE
的XML中的android:requiresFadingEdge="vertical"
。可能无法将淡化边缘与GridView
结合使用。
答案 7 :(得分:0)
如果可见性是问题,则只需要在渲染后延迟动画即可:
vVm_controls.setVisibility(View.INVISIBLE);
vVm_controls.post(() -> vVm_controls.startAnimation(mSlideIn));
答案 8 :(得分:0)
即使根本不使用Visibility.GONE,整个SO的答案都没有对我有用。
所以我最终得到了创可贴,有一天我会研究它的。
我的临时解决方案是将高度设置为1px(而不是0dp,这使得在我的情况下无法工作),并且将可见性设置为“不可见”。因此我最终损失了1px,但很难注意到。
代码:
ResizeAnimation.kt
class ResizeAnimation(private val view: View, private val newHeight: Int) : Animation() {
private val initialHeight: Int = view.layoutParams.height
private val deltaHeight: Int
init {
deltaHeight = newHeight - initialHeight
}
override fun applyTransformation(interpolatedTime: Float, t: Transformation?) {
view.layoutParams.height = (initialHeight + deltaHeight * interpolatedTime).toInt()
view.requestLayout()
}
override fun willChangeBounds(): Boolean {
return true
}
}
用法:
private fun displayProgressBar() {
progressBar.visibility = View.VISIBLE
val animation = ResizeAnimation(progressBar, 78).apply {
duration = inAnimationDuration
}
progressBar.startAnimation(animation)
}
private fun removeProgressBar() {
val animation = ResizeAnimation(progressBar, 1).apply {
duration = outAnimationDuration
}
progressBar.startAnimation(animation)
progressBar.visibility = View.INVISIBLE
}
请不要将其作为最终解决方案,而应将其视为创可贴。
答案 9 :(得分:0)
如果您使用RecyclerView 设置适配器后加载列表项 可以使用这个
recyclerView.scheduleLayoutAnimation();
之后
adapter.notifyDataSetChanged();
这是我的案子
答案 10 :(得分:-1)
我知道这个问题很旧,但是我的回答可能会对他人有所帮助。 当我们需要为视图设置动画时,默认情况下它的可见性消失了 然后请在xml中设置所有属性隐藏代码 就我而言,我在java文件中使用了translationY和alpha。 我做了简单的事情来解决第一次运行中的问题。 然后在代码中使用XML添加所有属性。