我有一个自定义搜索面板,它是主要布局的一部分。大多数时候面板都是隐藏的。我想在面板中添加出现/消失的动画。这是简化的布局摘录:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<RelativeLayout
android:id="@+id/layoutSearch"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:visibility="gone" >
<EditText
android:id="@+id/editSearch"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<<Other inner views to be animated>>
</RelativeLayout>
<<Other views, which should not be affected by the animation>>
</LinearLayout>
尝试1 :我添加了动画资源,并使用XML格式的这一行将它们附加到@ id / layoutSearch:
android:layoutAnimation="@anim/search_in_layout"
动画/ search_in.xml:
<translate
xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/overshoot_interpolator"
android:fromYDelta="-100%p"
android:toYDelta="0"
android:duration="@android:integer/config_longAnimTime" />
动画/ search_in_layout.xml:
<layoutAnimation
xmlns:android="http://schemas.android.com/apk/res/android"
android:animation="@anim/search_in" />
动画效果很好,但仅适用于出现的面板。当我隐藏它时,面板会在没有动画的情况下消失:
mSearchLayout.setVisibility(View.GONE);
尝试2 :我猜上面的解决方案不起作用,因为动画目标参数与当前面板位置匹配。好的,我创建了两个动画资源:anim / search_out.xml和anim / search_out_layout.xml。唯一的区别是交换“fromYDelta”和“toYDelta”值并更新“android:animation”值。然后我在代码中加载资源并将它们设置为@ id / layoutSearch,如下所示:
LayoutAnimationController controller =
AnimationUtils.loadLayoutAnimation(this, R.anim.search_out_layout);
mSearchLayout.setLayoutAnimation(controller);
调用setLayoutAnimation()时触发“out”动画。在动画之后,搜索面板返回到它在“out”动画之前的屏幕上的原始位置。如果我尝试在setLayoutAnimation()之后调用mSearchLayout.setVisibility(View.GONE),我看不到动画,面板立即消失。
试试3 :我想我需要在代码中创建动画,然后在其上设置一个监听器。然后我应该在onAnimationEnd()处理程序中调用mSearchLayout.setVisibility(View.GONE)以在播放动画后隐藏面板。我还没试过这个。我认为这太复杂了。
我想我错过了重要的事情。有没有办法实现GONE动画有点容易?
答案 0 :(得分:7)
继续上面的答案:这是我如何解决这个问题。
请注意,在动画中设置 setFillBefore 和 setFillAfter 会导致以下错误! Issue 5272: View with visibility View.GONE still generates touch events http://code.google.com/p/android/issues/detail?id=5272
文件: MyWebViewActivity.java
private View mBottomOverlay;
private View mTopOverlay;
private boolean mControlsOverlayVisible;
private Animation mSlideBottomUpAnimation;
private Animation mSlideBottomDownAnimation;
private Animation mSlideTopDownAnimation;
private Animation mSlideTopUpAnimation;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.reader_layout);
// load the overlay resources
mTopOverlay = findViewById(R.id.reader_overlay_top_toolbar);
mBottomOverlay = findViewById(R.id.reader_overlay_bottom_toolbar);
initAnimations();
}
private void initAnimations() {
final AnimationListener makeTopGone = new AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {}
@Override
public void onAnimationRepeat(Animation animation) {}
@Override
public void onAnimationEnd(Animation animation) {
Log.d(TAG, "onAnimationEnd - makeTopGone");
mTopOverlay.setVisibility(View.GONE);
}
};
final AnimationListener makeBottomGone = new AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {}
@Override
public void onAnimationRepeat(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
Log.d(TAG, "onAnimationEnd - makeBottomGone");
mBottomOverlay.setVisibility(View.GONE);
}
};
final AnimationListener makeTopVisible = new AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
Log.d(TAG, "onAnimationStart - makeTopVisible");
mTopOverlay.setVisibility(View.VISIBLE);
}
@Override
public void onAnimationRepeat(Animation animation) {}
@Override
public void onAnimationEnd(Animation animation) {}
};
final AnimationListener makeBottomVisible = new AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
Log.d(TAG, "onAnimationStart - makeBottomVisible");
mBottomOverlay.setVisibility(View.VISIBLE);
}
@Override
public void onAnimationRepeat(Animation animation) {}
@Override
public void onAnimationEnd(Animation animation) {}
};
mSlideTopUpAnimation = AnimationUtils.loadAnimation(this, R.anim.slide_top_up);
mSlideBottomDownAnimation = AnimationUtils.loadAnimation(this, R.anim.slide_bottom_down);
mSlideTopUpAnimation.setAnimationListener(makeTopGone);
mSlideBottomDownAnimation.setAnimationListener(makeBottomGone);
mSlideTopDownAnimation = AnimationUtils.loadAnimation(this, R.anim.slide_top_down);
mSlideBottomUpAnimation = AnimationUtils.loadAnimation(this, R.anim.slide_bottom_up);
mSlideTopDownAnimation.setAnimationListener(makeTopVisible);
mSlideBottomUpAnimation.setAnimationListener(makeBottomVisible);
}
private void hideControlOverlays() {
Log.d(TAG, "hideControlOverlays");
mTopOverlay.startAnimation(mSlideTopUpAnimation);
mBottomOverlay.startAnimation(mSlideBottomDownAnimation);
mControlsOverlayVisible = false;
}
private void showControlOverlays() {
Log.d(TAG, "showControlOverlays");
mTopOverlay.startAnimation(mSlideTopDownAnimation);
mBottomOverlay.startAnimation(mSlideBottomUpAnimation);
mControlsOverlayVisible = true;
}
文件: /res/layout/reader_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/reader_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<WebView
android:id="@+id/webview"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/reader_overlay_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:id="@+id/reader_overlay_top_toolbar"
android:layout_width="fill_parent"
android:layout_height="140dp"
android:background="#80000000" >
<include layout="@layout/toolbar_top" />
</LinearLayout>
<LinearLayout
android:id="@+id/reader_overlay_bottom_toolbar"
android:layout_width="fill_parent"
android:layout_height="140dp"
android:layout_gravity="bottom"
android:background="#80000000"
android:orientation="horizontal" >
<include layout="@layout/toolbar_bottom_left" />
</LinearLayout>
</FrameLayout>
</FrameLayout>
文件: /res/anim/slide_bottom_down.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillEnabled="true"
android:interpolator="@android:anim/accelerate_interpolator" >
<translate
android:duration="@android:integer/config_shortAnimTime"
android:fromYDelta="0"
android:toYDelta="100%" />
</set>
文件: /res/anim/slide_bottom_up.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_interpolator" >
<translate
android:duration="@android:integer/config_shortAnimTime"
android:fromYDelta="100%"
android:toYDelta="0" />
</set>
文件: /res/anim/slide_top_down.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_interpolator" >
<translate
android:duration="@android:integer/config_shortAnimTime"
android:fromYDelta="-100%"
android:toYDelta="0" />
</set>
文件: /res/anim/slide_top_up.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillEnabled="true"
android:interpolator="@android:anim/accelerate_interpolator" >
<translate
android:duration="@android:integer/config_shortAnimTime"
android:fromYDelta="0"
android:toYDelta="-100%" />
</set>
答案 1 :(得分:4)
尝试3:我想我需要在代码中创建动画,然后在其上设置一个监听器。然后我应该在onAnimationEnd()处理程序中调用mSearchLayout.setVisibility(View.GONE)以在播放动画后隐藏面板。我还没试过这个。我认为这太复杂了。
这就是你应该做的事情,实际上并不难实现。
示例代码:
public class YourClass extends Foo implements AnimationListener {
//...
@Override
public void onAnimationEnd(Animation a) {
// Do stuff.
}
@Override
public void onAnimationRepeat(Animation a) {
}
@Override
public void onAnimationStart(Animation a) {
}
}
答案 2 :(得分:4)
你需要调用动画类的 setFillAfter()来播放后保存动画。
RelativeLayout layout = (RelativeLayout) findViewById(R.id.layoutSearch);
Animation a = AnimationUtils.loadAnimation(this, R.anim.push_down);
a=setFillAfter(true);
layout.setLayoutAnimation(new LayoutAnimationController(a));
layout.startLayoutAnimation();
答案 3 :(得分:2)
将视图设置为GONE
会有效地将其从布局中删除。相反,您应该在动画完成后将其设置为INVISIBLE
,然后再设置为GONE
。