66

我正在尝试在我的应用程序中为一个简单的 ImageView 设置动画,我希望它从屏幕底部滑入并到达视图顶部 50px 离开屏幕顶部的静止位置(例如最终位置ImageView 的 X 值应为 -50px)。我尝试使用 AbsoluteLayout 来执行此操作,但这实际上切断了 ImageView 的顶部 50px,因此顶部 50px 永远不会呈现。我需要让 ImageView 的顶部 50px 在动画时可见/渲染,然后让它稍微离开屏幕。我希望我已经解释得足够好。

这是我目前用作布局和滑入动画的内容(目前不渲染 ImageView 的顶部 50px):

布局:

<?xml version="1.0" encoding="utf-8"?>
   <AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_height="fill_parent" 
      android:layout_width="fill_parent" 
      android:id="@+id/QuickPlayClipLayout">
      <ImageView android:id="@+id/Clip"
         android:background="@drawable/clip" 
         android:layout_width="fill_parent" 
         android:layout_height="wrap_content" 
         android:layout_y="-50dp">
      </ImageView>
   </AbsoluteLayout>

动画片:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
   <translate android:fromYDelta="100%p" 
       android:toYDelta="0"
       android:duration="1000"/>
   <alpha android:fromAlpha="0.0" 
       android:toAlpha="1.0"
       android:duration="1000" />
</set>

提前致谢。

4

6 回答 6

36

相反,我们可以简单地为 layout_margin(Top/left/right/bottom) 赋予负值,例如:如果您希望视图远离屏幕顶部,您可以指定

android:layout_marginTop="-40dp"
于 2015-05-13T09:29:42.440 回答
33

我想出了一个应该很容易实现的解决方案。它涉及修改布局和使布局膨胀的活动......见下文:

活动(QuickPlay.java):

public class QuickPlay extends Activity implements AnimationListener
{
    private ImageView myImageView;
    private LinearLayout LL;

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

        myImageView = (ImageView) this.findViewById(R.id.Clip);
        LL = (LinearLayout) this.findViewById(R.id.QuickPlayClipLayout);

        //finally
        Animation anim = AnimationUtils.loadAnimation(this, R.anim.slide_in_quickplay);
        anim.setAnimationListener(this);
        LL.startAnimation(anim);
    }
    @Override
    public void onAnimationEnd(Animation animation){}

    @Override
    public void onAnimationRepeat(Animation animation){}

    @Override
    public void onAnimationStart(Animation animation)
    {
        // This is the key...
        //set the coordinates for the bounds (left, top, right, bottom) based on the offset value (50px) in a resource XML
        LL.layout(0, -(int)this.getResources().getDimension(R.dimen.quickplay_offset), 
                LL.getWidth(), LL.getHeight() + (int)this.getResources().getDimension(R.dimen.quickplay_offset));
    }
}

新的线性布局(CustomLinearLayout.java):

public class CustomLinearLayout extends LinearLayout
{
    private Context myContext;

    public CustomLinearLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        myContext = context;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec+((int)myContext.getResources().getDimension(R.dimen.quickplay_offset)));
    }
}

布局(/res/layout/quick_play_screen.xml):

<?xml version="1.0" encoding="utf-8"?>
   <com.games.mygame.CustomLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_height="fill_parent" 
      android:layout_width="fill_parent" 
      android:id="@+id/QuickPlayClipLayout">
      <ImageView android:id="@+id/Clip"
         android:background="@drawable/clip" 
         android:layout_width="fill_parent" 
         android:layout_height="wrap_content">
      </ImageView>
   </com.games.mygame.CustomLinearLayout>

资源(/res/values/constants.xml):

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <dimen name="quickplay_offset">50dp</dimen>
</resources>

动画(/res/anim/slide_in_quickplay.xml):

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
   <translate android:fromYDelta="100%p" 
       android:toYDelta="0"
       android:duration="1000"/>
   <alpha android:fromAlpha="0.0" 
       android:toAlpha="1.0"
       android:duration="1000" />
</set>

该程序现在完全符合我的需要。整个布局从屏幕底部开始,在 1 秒内滑入并停止,布局顶部实际上距离屏幕顶部 50px(即LL.getTop() = -50),而布局底部位于屏幕(即LL.getBottom() = 530 = 480 + 50)。

于 2010-04-02T02:38:28.143 回答
30

要将我的视图定位在屏幕外,我使用了以下代码:

View myView = /* view you want to position offscreen */
int amountOffscreen = (int)(myView.getWidth() * 0.8); /* or whatever */
boolean offscreen = /* true or false */


int xOffset = (offscreen) ? amountOffscreen : 0;
RelativeLayout.LayoutParams rlParams = 
    (RelativeLayout.LayoutParams)myView.getLayoutParams();
rlParams.setMargins(-1*xOffset, 0, xOffset, 0);
myView.setLayoutParams(rlParams);

此代码将 myView 定位到屏幕外的 amountOffscreen,在这种情况下,将 80% 的视图放在屏幕外,仅留下 20% 的屏幕。

不要直接使用 layout() 方法 - Android 会出于随机原因进行后续调用以使您的视图无效,并且只有 layoutParams 会在无效调用中持久化。如果您好奇,请查看该文件的第 904 到 912行,了解为什么必须修改 layoutParams。

于 2012-04-19T06:46:28.000 回答
9

如果您跳到使用Canvas;这很容易做到。那些支持没有任何麻烦地画出屏幕。但是,实现起来会比较复杂。您需要实现自定义View并用代码编写自己的动画。本质上,这归结为简单的 2D 图形处理,而不是使用内置 XML 动画的视图。可能有一种使用 XML 的方法,但我对画布更熟悉。SDK 附带的 Lunar Lander 示例游戏是了解如何在代码中处理的一个很好的地方。

您需要遵循的大致步骤是:

  1. 在 XML 文件中放置一个自定义视图,使用类似的东西<your.package.AnimatingView>,将其大小设置为 fill-parent。

  2. 然后定义一个 AnimatingView 类,其中extends SurfaceView and implements SurfaceHolder.Callback. (这使您可以立即访问绘图Canvas,而不是使用该invalidate()方法。这很重要,因为 invalidate() 仅在线程空闲时刷新,例如在循环结束时。要实现动画,您需要让它绘图立即地。)

  3. 然后,您可以实现一个循环,在屏幕上绘制您的移动图像。循环需要从绘制整个背景开始(因为画布不会自动擦除),然后根据已经过去的时间在新位置绘制图像。例如,如果你想让你的动画花 1 秒的时间来完成,那么你知道如果 200 毫秒过去了,视图应该只移动了 200/1000 或 1/5,从它的起始位置到最终位置.

您可以在我对动画问题的其他答案中看到一些我的意思的示例:关于使用 SurfaceView 的有用性的基本回复和使用循环的示例。注意:第二个问题是关于轮换的,因此我所说的一些困难与你无关。祝你好运!

于 2010-04-01T13:40:51.040 回答
8

android:translationX和_android:translationY

<RelativeLayout
        android:translationX="-600dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent">
于 2018-09-20T16:25:22.390 回答
2

我有一个带有孩子的视图组,并且正在将视图从底部拖到屏幕中 - 有点像抽屉。然后我会放手,如果视图组上边距在屏幕的上半部分,我会在用户释放触摸后将其动画到顶部。

发生这种情况时,视图组子项中的图像将在动画期间被裁剪,但随后会在动画之后显示。

问题:视图组的高度是 wrap_content。我通过将高度设置为在动画开始之前从屏幕上延伸的值来解决这个问题。

于 2014-01-23T20:07:55.253 回答