我有一个LinearLayout
,我想使用一个Animation
将该布局向上或向下推动,以便在更改其可见性时显示或隐藏它。
我看过一些示例,但没有符合我的需求。
我已经为动画创建了两个xml文件,但不知道如何在更改LinearLayout
的可见性时启动它们。
我有一个LinearLayout
,我想使用一个Animation
将该布局向上或向下推动,以便在更改其可见性时显示或隐藏它。
我看过一些示例,但没有符合我的需求。
我已经为动画创建了两个xml文件,但不知道如何在更改LinearLayout
的可见性时启动它们。
在 Android 3.0(Honeycomb)中引入的新动画 API 可以非常简单地创建此类动画。
将 View
向下滑动一定距离:
view.animate().translationY(distance);
你可以通过以下方式将 View
滑回到初始位置:
view.animate().translationY(0);
你还可以轻松地组合多个动画。以下动画将同时使一个 View
向下滑动其高度并淡入:// Prepare the View for the animation
view.setVisibility(View.VISIBLE);
view.setAlpha(0.0f);
// Start the animation
view.animate()
.translationY(view.getHeight())
.alpha(1.0f)
.setListener(null);
接下来,您可以将View
淡出并将其滑回到原始位置。 我们还设置了一个AnimatorListener
,以便在动画完成后可以将View
的可见性设置为GONE
:
view.animate()
.translationY(0)
.alpha(0.0f)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
view.setVisibility(View.GONE);
}
});
我曾经遇到了理解和应用所接受的答案的困难,我需要更多的上下文。现在我已经弄清楚了,这里是一个完整的例子:
MainActivity.java
public class MainActivity extends AppCompatActivity {
Button myButton;
View myView;
boolean isUp;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myView = findViewById(R.id.my_view);
myButton = findViewById(R.id.my_button);
// initialize as invisible (could also do in xml)
myView.setVisibility(View.INVISIBLE);
myButton.setText("Slide up");
isUp = false;
}
// slide the view from below itself to the current position
public void slideUp(View view){
view.setVisibility(View.VISIBLE);
TranslateAnimation animate = new TranslateAnimation(
0, // fromXDelta
0, // toXDelta
view.getHeight(), // fromYDelta
0); // toYDelta
animate.setDuration(500);
animate.setFillAfter(true);
view.startAnimation(animate);
}
// slide the view from its current position to below itself
public void slideDown(View view){
TranslateAnimation animate = new TranslateAnimation(
0, // fromXDelta
0, // toXDelta
0, // fromYDelta
view.getHeight()); // toYDelta
animate.setDuration(500);
animate.setFillAfter(true);
view.startAnimation(animate);
}
public void onSlideViewButtonClick(View view) {
if (isUp) {
slideDown(myView);
myButton.setText("Slide up");
} else {
slideUp(myView);
myButton.setText("Slide down");
}
isUp = !isUp;
}
}
activity_mail.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
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"
tools:context="com.example.slideview.MainActivity">
<Button
android:id="@+id/my_button"
android:layout_centerHorizontal="true"
android:layout_marginTop="100dp"
android:onClick="onSlideViewButtonClick"
android:layout_width="150dp"
android:layout_height="wrap_content"/>
<LinearLayout
android:id="@+id/my_view"
android:background="#a6e1aa"
android:orientation="vertical"
android:layout_alignParentBottom="true"
android:layout_width="match_parent"
android:layout_height="200dp">
</LinearLayout>
</RelativeLayout>
.setVisibility(View.INVISIBLE);
,则向上滑动功能在视觉上不会按预期工作。 - Advait SaravadeTranslate Animation
moves the view. If you want to animate view like its scaling itself then use ScaleAnimation anim = new ScaleAnimation(1, 1, 0, 1)
- Zohab AliTranslateAnimation
不会移动它们。它只会移动像素。在大多数情况下,这可能是意外的。请参考此链接以同时移动可点击元素:https://dev59.com/cmox5IYBdhLWcg3wpV3F#34631361 - Kaushal28现在,视图可见性变化的动画应该通过Transition API
来完成,该API在支持(androidx)软件包中提供。只需调用TransitionManager.beginDelayedTransition方法并使用Slide转换,然后改变视图的可见性。
import androidx.transition.Slide;
import androidx.transition.Transition;
import androidx.transition.TransitionManager;
private void toggle(boolean show) {
View redLayout = findViewById(R.id.redLayout);
ViewGroup parent = findViewById(R.id.parent);
Transition transition = new Slide(Gravity.BOTTOM);
transition.setDuration(600);
transition.addTarget(R.id.redLayout);
TransitionManager.beginDelayedTransition(parent, transition);
redLayout.setVisibility(show ? View.VISIBLE : View.GONE);
}
主活动界面布局文件 activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/parent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="play" />
<LinearLayout
android:id="@+id/redLayout"
android:layout_width="match_parent"
android:layout_height="400dp"
android:background="#5f00"
android:layout_alignParentBottom="true" />
</RelativeLayout>
查看这个答案,其中包括另一个默认和自定义转换示例。
minSdkVersion 21
。 - lasec0203android:animateLayoutChanges="true"
。<LinearLayout android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"
>
<Views_which_change_visibility>
</LinearLayout>
您可以在Android开发者网站上了解更多关于此的详细信息。
Kotlin
根据Suragch的答案,这里介绍一种使用View扩展的优雅方式:
fun View.slideUp(duration: Int = 500) {
visibility = View.VISIBLE
val animate = TranslateAnimation(0f, 0f, this.height.toFloat(), 0f)
animate.duration = duration.toLong()
animate.fillAfter = true
this.startAnimation(animate)
}
fun View.slideDown(duration: Int = 500) {
visibility = View.VISIBLE
val animate = TranslateAnimation(0f, 0f, 0f, this.height.toFloat())
animate.duration = duration.toLong()
animate.fillAfter = true
this.startAnimation(animate)
}
然后无论您想在哪里使用它,您只需使用 myView.slideUp()
或 myView.slideDown()
当LinearLayout
的可见性发生改变时,您可以通过创建LinearLayout
的新子类并重写setVisibility()
方法来启动正确的Animation
。考虑实现以下内容:
public class SimpleViewAnimator extends LinearLayout
{
private Animation inAnimation;
private Animation outAnimation;
public SimpleViewAnimator(Context context)
{
super(context);
}
public void setInAnimation(Animation inAnimation)
{
this.inAnimation = inAnimation;
}
public void setOutAnimation(Animation outAnimation)
{
this.outAnimation = outAnimation;
}
@Override
public void setVisibility(int visibility)
{
if (getVisibility() != visibility)
{
if (visibility == VISIBLE)
{
if (inAnimation != null) startAnimation(inAnimation);
}
else if ((visibility == INVISIBLE) || (visibility == GONE))
{
if (outAnimation != null) startAnimation(outAnimation);
}
}
super.setVisibility(visibility);
}
}
View
负责其自身的动画,这绝对不是你想要的。想象一下,如果你想在应用程序的另一个部分以不同的方式动画化View
,那么该怎么办呢?添加一个标志以不自动动画化可见性?子类化View
并覆盖setVisibility()
以删除动画?甚至更糟的是,使用另一个动画实现setVisibility()
?从那里开始,问题只会变得越来越丑陋。不要使用这个“解决方案”。 - Xaver Kapellerandroid:animateLayoutChanges="true"
属性,然后Android会自动为你的出现和消失的视图添加动画效果。 - Xaver Kapellerif (filter_section.getVisibility() == View.GONE) {
filter_section.animate()
.translationY(filter_section.getHeight()).alpha(1.0f)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
super.onAnimationStart(animation);
filter_section.setVisibility(View.VISIBLE);
filter_section.setAlpha(0.0f);
}
});
} else {
filter_section.animate()
.translationY(0).alpha(0.0f)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
filter_section.setVisibility(View.GONE);
}
});
}
setAlpha
是用来做什么的? - IgorGanapolsky您可以使用以下代码在Android应用程序中向上或向下滑动任何视图或布局:
boolean isClicked = false;
LinearLayout mLayoutTab = (LinearLayout) findViewById(R.id.linearlayout);
if(isClicked) {
isClicked = false;
mLayoutTab.animate()
.translationYBy(120)
.translationY(0)
.setDuration(getResources().getInteger(android.R.integer.config_mediumAnimTime));
} else {
isClicked = true;
mLayoutTab.animate()
.translationYBy(0)
.translationY(120)
.setDuration(getResources().getInteger(android.R.integer.config_mediumAnimTime));
}
private fun slideDown(view: View) {
val height = view.height
ObjectAnimator.ofFloat(view, View.TRANSLATION_Y, 0f, height.toFloat()).apply {
duration = 1000
start()
}
}
private fun slideUp(view: View) {
val height = view.height
ObjectAnimator.ofFloat(view, View.TRANSLATION_Y, height.toFloat(), 0f)).apply {
duration = 1000
start()
}
}
0.toFloat()
can also just be 0f
- Tyler使用这个类:
public class ExpandCollapseExtention {
public static void expand(View view) {
view.setVisibility(View.VISIBLE);
final int widthSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
final int heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
view.measure(widthSpec, heightSpec);
ValueAnimator mAnimator = slideAnimator(view, 0, view.getMeasuredHeight());
mAnimator.start();
}
public static void collapse(final View view) {
int finalHeight = view.getHeight();
ValueAnimator mAnimator = slideAnimator(view, finalHeight, 0);
mAnimator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationEnd(Animator animator) {
view.setVisibility(View.GONE);
}
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
mAnimator.start();
}
private static ValueAnimator slideAnimator(final View v, int start, int end) {
ValueAnimator animator = ValueAnimator.ofInt(start, end);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
int value = (Integer) valueAnimator.getAnimatedValue();
ViewGroup.LayoutParams layoutParams = v.getLayoutParams();
layoutParams.height = value;
v.setLayoutParams(layoutParams);
}
});
return animator;
}
}
onAnimationEnd
每次都会被调用,这意味着当视图显示时也会调用onAnimationEnd
,从而将其可见性设置为Gone等。 - oldergodsetListener(null)
将其设置为可见。 - Shahab Rauf