Android – 如何将视图置于屏幕外?
我试图在我的应用程序中创build一个简单的ImageViewanimation,并且我希望它从屏幕底部滑入,并进入静止位置,顶部50px的视图离开屏幕的顶部(例如最终位置的ImageView应该在-50px在X)。 我试图使用AbsoluteLayout来做到这一点,但是这实际上切断了ImageView的顶部50px,使得顶部的50px永远不会被渲染。 我需要让ImageView的顶部50像素可见/呈现animation,然后稍微离开屏幕稍微rest一下。 我希望我已经解释得很好。
这是我目前使用的布局和幻灯片animation(目前不会呈现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>
animation:
<?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>
提前致谢。
我想出了一个解决scheme,应该很容易实现。 它涉及修改布局和活动膨胀的布局…见下文:
活动(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)); } }
新的LinearLayout(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>
animation(/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
)的地方rest,并且底部布局停留在屏幕底部(即LL.getBottom() = 530 = 480 + 50
)。
将我的视图置于屏幕外我使用了下面的代码:
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%的视angular只剩下20%。
不要直接使用layout()方法 – 由于随机的原因,Android会使随后的调用失效,只有layoutParams在无效调用中持久化。 如果您好奇,请查看此文件的第904至912行,看看为什么您必须修改layoutParams。
相反,我们可以简单地给layout_margin(Top / left / right / bottom)给负值,例如:如果你想让你的视图从屏幕顶部离开,你可以指定
android:layout_marginTop="-40dp"
如果你跳跃使用Canvas
,这很容易做到; 那些支持拔出屏幕没有任何麻烦。 但是,实施起来会比较复杂。 你需要实现一个自定义的View
并在代码中编写自己的animation。 本质上,这归结为简单的2Dgraphics处理,而不是使用内置的XMLanimation视图。 可能有一种方法可以用XML来完成,但我对canvas更为熟悉。 在代码中处理这个问题的好地方就是SDK附带的Lunar Lander示例游戏。
大致你需要遵循的步骤是:
-
将自定义视图放在XML文件中,使用
<your.package.AnimatingView>
类的东西,将其大小设置为填充父项。 -
然后定义一个
extends SurfaceView and implements SurfaceHolder.Callback
类,它extends SurfaceView and implements SurfaceHolder.Callback
。 (这样可以立即访问Canvas
画图,而不是使用invalidate()
方法,这很重要,因为invalidate()只在线程空闲的时候刷新,例如在循环结束时。立即绘制)。 -
然后,您可以实现一个循环,在屏幕上绘制运动图像。 循环需要通过绘制整个背景开始(因为canvas不会自动擦除),然后根据已经过的时间在新的位置绘制图像。 例如,如果你想让animation花费1秒钟的时间,那么你知道,如果200ms已经过去了,视图只能从开始位置移动到最终位置的200/1000或1/5 。
你可以看到我在animation问题的其他答案中的一些例子:关于使用SurfaceView的有用性的基本回复, 以及使用 循环的例子 。 注:第二个问题是关于轮换,因此我谈到的一些困难与您无关。 祝你好运!
我有一个有孩子的视图组,并从底部将视图拖入屏幕 – 有点像抽屉。 然后,我会放手,如果视图组顶部边缘在屏幕的上半部分,我会在用户释放触摸后将其设置为顶部。
发生这种情况时,视图组的子项中的图像将在animation期间被裁剪,但会在animation之后显示。
问题:viewgroup的高度是wrap_content。 我通过将高度设置为在animation开始之前从屏幕拉伸的值来解决这个问题。