我试图在其父视图之外设置一个视图的动画,当我这样做时,子视图无法在其父视图之外进行动画处理.我通过使用setClipChildren(false)解决了这个问题,并且它有效……当视图动画化时.当我为视图设置动画时,图像仍然是隐藏的.
这是有效的代码.此代码会将平铺按钮设置为屏幕顶部的动画:
private voID setGameBoard(){ brickWall.setClipChildren(false); brickWall.setClipTopadding(false); //Build game board for(int ii = 0; ii < brickRows;ii++){ final int x = ii; //Build table rows row = new tableRow(this.getApplicationContext()); row.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, 50)); row.setClipChildren(false); row.setClipTopadding(false); // row.setBackgroundcolor(ResourcesCompat.getcolor(getResources(), R.color.colorAccent, null)); //Build table tiles for(int jj=0; jj < brickColumns; jj++){ final int y = jj; final Brick tile = new Brick(this); tile.setClipBounds(null); tile.setBackgroundcolor(ResourcesCompat.getcolor(getResources(), R.color.colorPrimary, null)); //Set margins to create look of tic-tac-toe tableRow.LayoutParams lp = new tableRow.LayoutParams( 150, 75); lp.setmargins(0,0,0,0); //lp.weight = 1; tile.setLayoutParams(lp); tile.setWIDth(3); tile.setHeight(10); tile.setonClickListener(new VIEw.OnClickListener() { @OverrIDe public voID onClick(VIEw v) { if(tile.getHits() == 0){ tile.setBackgroundcolor(ResourcesCompat.getcolor(getResources(), R.color.colorGreen, null)); tile.addHit(); } else if (tile.getHits() == 1){ tile.setBackgroundcolor(ResourcesCompat.getcolor(getResources(), R.color.colorYellow, null)); tile.addHit(); }else if(tile.getHits() == 2){ brokenBricks++; float bottomOfScreen = getResources().getdisplayMetrics() .heightPixels; ObjectAnimator objectAnimator = ObjectAnimator.offloat(tile, "translationY", -2000);// 2 objectAnimator.setDuration(2000); tile.setHapticFeedbackEnabled(true); objectAnimator.start(); //tile.setVisibility(VIEw.INVISIBLE); if(isRevealComplete()){ brickWall.setVisibility(VIEw.INVISIBLE); } } } }); row.addVIEw(tile); } brickWall.addVIEw(row); } }
但是当我调整视图到屏幕底部的位置时,它下面的视图被“吞噬”并且当它到达父视图的底部时被隐藏:
private voID setGameBoard(){ brickWall.setClipChildren(false); brickWall.setClipTopadding(false); //Build game board for(int ii = 0; ii < brickRows;ii++){ final int x = ii; //Build table rows row = new tableRow(this.getApplicationContext()); row.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, 50)); row.setClipChildren(false); row.setClipTopadding(false); // row.setBackgroundcolor(ResourcesCompat.getcolor(getResources(), R.color.colorAccent, null)); //Build table tiles for(int jj=0; jj < brickColumns; jj++){ final int y = jj; final Brick tile = new Brick(this); tile.setClipBounds(null); tile.setBackgroundcolor(ResourcesCompat.getcolor(getResources(), R.color.colorPrimary, null)); //Set margins to create look of tic-tac-toe tableRow.LayoutParams lp = new tableRow.LayoutParams( 150, 75); lp.setmargins(0,0,0,0); //lp.weight = 1; tile.setLayoutParams(lp); tile.setWIDth(3); tile.setHeight(10); tile.setonClickListener(new VIEw.OnClickListener() { @OverrIDe public voID onClick(VIEw v) { if(tile.getHits() == 0){ tile.setBackgroundcolor(ResourcesCompat.getcolor(getResources(), R.color.colorGreen, null)); tile.addHit(); } else if (tile.getHits() == 1){ tile.setBackgroundcolor(ResourcesCompat.getcolor(getResources(), R.color.colorYellow, null)); tile.addHit(); }else if(tile.getHits() == 2){ brokenBricks++; float bottomOfScreen = getResources().getdisplayMetrics() .heightPixels; ObjectAnimator objectAnimator = ObjectAnimator.offloat(tile, "translationY", 2000); objectAnimator.setDuration(2000); tile.setHapticFeedbackEnabled(true); objectAnimator.start(); //tile.setVisibility(VIEw.INVISIBLE); if(isRevealComplete()){ brickWall.setVisibility(VIEw.INVISIBLE); } } } }); row.addVIEw(tile); } brickWall.addVIEw(row); } }
所以我的问题是:如何在子视图下面的父视图之外设置子视图的动画?
更新1
如果我移除瓷砖下面的瓷砖,我试图放下,然后我能够看到所需的效果,直到它下面有另一个瓷砖,此时下降的瓷砖将“仍然”在仍然存在的瓷砖“后面”.那么如何让掉落的瓷砖移动到它下面的孩子身上呢?
更新2
我注意到的一件新事情是,如果我向左或向上移动按钮,它可以正常工作;但是,如果将其向下或向右移动,它会落后于其他视图.这让我相信在当前图块之后创建的按钮具有不同的效果.
解决方法:
好吧,所以在我建议的替代方法中,我会使用一个帮助类FlyOverVIEw,它可以获取任何视图的“照片”,然后将其设置为任意所需的坐标.一旦动画运行,您就可以隐藏/删除原始视图,因为在屏幕上移动的内容只是在画布上显示的图像.您不必担心剪切其他视图等.
您需要在砖块系统的外部容器上声明此FlyOverVIEw,并且该布局必须覆盖您希望动画可见的整个区域.因此我建议在root容器中使用以下内容,它只是一个FrameLayout,您可以在其中绘制内容.
package whatever;public class GameRootLayout extends FrameLayout { // the currently-animating effect, if any private FlyOverVIEw mFlyOverVIEw; public GameRootLayout(Context context, AttributeSet attrs) { super(context,attrs); } @OverrIDe public voID dispatchDraw(Canvas canvas) { // draw the children super.dispatchDraw(canvas); // draw our stuff if (mFlyOverVIEw != null) { mFlyOverVIEw.delegate_draw(canvas); } } /** * Starts a flyover animation for the specifIEd vIEw. * It will "fly" to the desired position with an Alpha / translation / rotation effect * * @param vIEwToFly The vIEw to fly * @param targetX The target X coordinate * @param targetY The target Y coordinate */ public voID addFlyOver(VIEw vIEwToFly, @Px int targetX, @Px int targetY) { if (mFlyOverVIEw != null) mFlyOverVIEw.cancel(); mFlyOverVIEw = new FlyOverVIEw(this, vIEwToFly, targetX, targetY, new FlyOverVIEw.OnFlyOverFinishedListener() { @OverrIDe public voID onFlyOverFinishedListener() { mFlyOverVIEw = null; } }); }}
你可以用作容器
<whatever.GameRootLayout androID:ID="@+ID/gameRootLayout" androID:layout_wIDth="match_parent" androID:layout_height="match_parent"> . . </whatever.GameRootLayout>
然后是FlyOverVIEw本身:
package com.regaliz.gui.fx;import androID.animation.Animator;import androID.animation.ObjectAnimator;import androID.animation.PropertyValuesHolder;import androID.graphics.Bitmap;import androID.graphics.Canvas;import androID.graphics.Matrix;import androID.graphics.Paint;import androID.util.Log;import androID.vIEw.VIEw;import androID.support.annotation.Px;import androID.vIEw.animation.AccelerateDecelerateInterpolator;/** * Neat animation that captures a layer bitmap and "flIEs" it to the corner of the screen, used to create * an "added to playList" effect or something like that. The method delegate_draw() must be called from the * parent vIEw to update the animation * * @author rupps'2014 * license public domain, attribution appreciated */@SuppressWarnings("unused")public class FlyOverVIEw { public static final int DEFAulT_DURATION = 1000; private static final String TAG = "FlyOverVIEw"; private static final boolean LOG_ON = false; private ObjectAnimator mFlyoverAnimation; private float mCurrentX, mCurrentY; private Matrix mMatrix = new Matrix(); private Bitmap mBitmap; private Paint mPaint = new Paint(); private VIEw mParentVIEw = null; private OnFlyOverFinishedListener mOnFlyOverFinishedListener; public interface OnFlyOverFinishedListener { voID onFlyOverFinishedListener(); } /** * Creates the FlyOver effect * * @param parent Container VIEw to invalIDate. That vIEw has to call this class' delegate_draw() in its dispatchDraw(). * @param vIEwToFly Target VIEw to animate * @param finalX Final X coordinate * @param finalY Final Y coordinate */ public FlyOverVIEw(VIEw parent, VIEw vIEwToFly, @Px int finalX, @Px int finalY, OnFlyOverFinishedListener Listener) { setupFlyOver(parent, vIEwToFly, finalX, finalY, DEFAulT_DURATION, Listener); } /** * Creates the FlyOver effect * * @param parent Container VIEw to invalIDate. That vIEw has to call this class' delegate_draw() in its dispatchDraw(). * @param vIEwToFly Target VIEw to animate * @param finalX Final X coordinate * @param finalY Final Y coordinate * @param duration Animation duration */ public FlyOverVIEw(VIEw parent, VIEw vIEwToFly, @Px int finalX, @Px int finalY, int duration, OnFlyOverFinishedListener Listener) { setupFlyOver(parent, vIEwToFly, finalX, finalY, duration, Listener); } /** * cancels current animation from the outsIDe */ public voID cancel() { if (mFlyoverAnimation != null) mFlyoverAnimation.cancel(); } private voID setupFlyOver(VIEw parentContainer, VIEw vIEwToFly, @Px int finalX, @Px int finalY, int duration, OnFlyOverFinishedListener Listener) { int[] location = new int[2]; mParentVIEw = parentContainer; mOnFlyOverFinishedListener = Listener; vIEwToFly.getLocationInWindow(location); int sourceX = location[0], sourceY = location[1]; if (LOG_ON) Log.v(TAG, "FlyOverVIEw, item " + vIEwToFly+", finals "+finalX+", "+finalY+", sources "+sourceX+", "+sourceY+ " duration "+duration); /* Animation deFinition table */ mFlyoverAnimation = ObjectAnimator.ofPropertyValuesHolder( this, PropertyValuesHolder.offloat("translationX", sourceX, finalX), PropertyValuesHolder.offloat("translationY", sourceY, finalY), PropertyValuesHolder.offloat("scaleAlpha", 1, 0.2f) // not to 0 so we see the end of the effect in other propertIEs ); mFlyoverAnimation.setDuration(duration); mFlyoverAnimation.setRepeatCount(0); mFlyoverAnimation.setInterpolator(new AccelerateDecelerateInterpolator()); mFlyoverAnimation.addListener(new SimpleAnimationListener() { @OverrIDe public voID onAnimationEnd(Animator animation) { if (LOG_ON) Log.v(TAG, "FlyOver: End"); mParentVIEw.invalIDate(); if (mBitmap != null) mBitmap.recycle(); // just for safety mBitmap = null; mOnFlyOverFinishedListener.onFlyOverFinishedListener(); } }); // take snapshot of vIEwToFly vIEwToFly.setDrawingCacheEnabled(true); mBitmap = Bitmap.createBitmap(vIEwToFly.getDrawingCache()); vIEwToFly.setDrawingCacheEnabled(false); mFlyoverAnimation.start(); } // ANIMATOR setter public voID setTranslationX(float position) { mCurrentX = position; } // ANIMATOR setter public voID setTranslationY(float position) { mCurrentY = position; } // ANIMATOR setter // as this will be called in every iteration, we set here all parameters at once then call invalIDate, // rather than separately public voID setScaleAlpha(float position) { mPaint.setAlpha((int) (100 * position)); mMatrix.setScale(position, position); mMatrix.postRotate(360 * position); // asemos de to' mMatrix.postTranslate(mCurrentX, mCurrentY); mParentVIEw.invalIDate(); } /** * This has to be called from the root container's dispatchDraw() * in order to update the animation. */ public voID delegate_draw(Canvas c) { if (LOG_ON) Log.v(TAG, "CX " + mCurrentX + ", CY " + mCurrentY); c.drawBitmap(mBitmap, mMatrix, mPaint); } private abstract class SimpleAnimationListener implements Animator.AnimatorListener { @OverrIDe public voID onAnimationStart(Animator animation) {} @OverrIDe public voID onAnimationRepeat(Animator animation) {} @OverrIDe public voID onAnimationCancel(Animator animation) {} }}
然后,当您想要为任何视图设置动画时,您只需在游戏根布局中调用该函数:
GameRootLayout rootLayout = (GameRootLayout)findVIEwByID(...);..rootLayout.addFlyOver(yourBrick, targetX, targetY);
此示例还将Alpha和旋转应用于视图,但您可以根据需要轻松调整它.
我希望这可以激励你,如果你有任何问题随时可以问!
总结以上是内存溢出为你收集整理的android – 在父级之外设置动画子视图全部内容,希望文章能够帮你解决android – 在父级之外设置动画子视图所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)