android– 在父级之外设置动画子视图

android– 在父级之外设置动画子视图,第1张

概述我试图在其父视图之外设置一个视图的动画,当我这样做时,子视图无法在其父视图之外进行动画处理.我通过使用setClipChildren(false)解决了这个问题,并且它有效……当视图动画化时.当我为视图设置动画时,图像仍然是隐藏的.这是有效的代码.此代码会将平铺按钮设置为屏幕顶部的动画:p

我试图在其父视图之外设置一个视图的动画,当我这样做时,子视图无法在其父视图之外进行动画处理.我通过使用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 – 在父级之外设置动画子视图所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1115229.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-29
下一篇 2022-05-29

发表评论

登录后才能评论

评论列表(0条)

保存