2

Android開発者サイトの次の例でFrameLayoutをズームしようとしています: http://developer.android.com/training/animation/zoom.html

私の具体的な問題は、アニメーションが最初に正しく、thumbView から展開され、2 回目にアニメーションが「どこか」(中央/上から中央) から来ることです。

私はほぼ同じですが、相違点は、ImageView の代わりに Framelayout があり、追加のメソッドでビューを最小化する関数を抽出することです。これは次のようになります。

private void zoomImageFromThumb(final View thumbView) {

    if (mCurrentAnimator != null) {
        mCurrentAnimator.cancel();
    }

    // here i building my custome layout

    startBounds = new Rect();
    final Rect finalBounds = new Rect();
    final Point globalOffset = new Point();

    thumbView.getGlobalVisibleRect(startBounds);
    findViewById(R.id.container)
            .getGlobalVisibleRect(finalBounds, globalOffset);
    startBounds.offset(-globalOffset.x, -globalOffset.y);
    finalBounds.offset(-globalOffset.x + 15, -globalOffset.y + 60);

    float startScale;
    if ((float) finalBounds.width() / finalBounds.height()
            > (float) startBounds.width() / startBounds.height()) {

        startScale = (float) startBounds.height() / finalBounds.height();
        float startWidth = startScale * finalBounds.width();
        float deltaWidth = (startWidth - startBounds.width()) / 2;
        startBounds.left -= deltaWidth;
        startBounds.right += deltaWidth;
    } else {

        startScale = (float) startBounds.width() / finalBounds.width();
        float startHeight = startScale * finalBounds.height();
        float deltaHeight = (startHeight - startBounds.height()) / 2;
        startBounds.top -= deltaHeight;
        startBounds.bottom += deltaHeight;
    }

    thumbView.setAlpha(0f);
    expandedImageView.setVisibility(View.VISIBLE);

    expandedImageView.setPivotX(0f);
    expandedImageView.setPivotY(0f);

    AnimatorSet set = new AnimatorSet();
    set
            .play(ObjectAnimator.ofFloat(expandedImageView, View.X,
                    startBounds.left, finalBounds.left))
            .with(ObjectAnimator.ofFloat(expandedImageView, View.Y,
                    startBounds.top, finalBounds.top))
            .with(ObjectAnimator.ofFloat(expandedImageView, View.SCALE_X,
            startScale, 1f)).with(ObjectAnimator.ofFloat(expandedImageView,
                    View.SCALE_Y, startScale, 1f));
    set.setDuration(mShortAnimationDuration);
    set.setInterpolator(new DecelerateInterpolator());
    set.addListener(new AnimatorListenerAdapter() {
        @Override
        public void onAnimationEnd(Animator animation) {
            mCurrentAnimator = null;
        }

        @Override
        public void onAnimationCancel(Animator animation) {
            mCurrentAnimator = null;
        }
    });
    set.start();
    mCurrentAnimator = set;
}

startBounds 変数はグローバルです。これは、最小化プロセスの位置を知るために必要なためです。ここで最小化メソッド:

    private void minimizeViewFromThumb(final View thumbView) {
    if (mCurrentAnimator != null) {
                    mCurrentAnimator.cancel();
                }

                AnimatorSet set = new AnimatorSet();
                set.play(ObjectAnimator
                            .ofFloat(expandedImageView, View.X, startBounds.left))
                            .with(ObjectAnimator
                                    .ofFloat(expandedImageView, 
                                            View.Y,startBounds.top))
                            .with(ObjectAnimator
                                    .ofFloat(expandedImageView, 
                                            View.SCALE_X, startScaleFinal))
                            .with(ObjectAnimator
                                    .ofFloat(expandedImageView, 
                                            View.SCALE_Y, startScaleFinal));
                set.setDuration(mShortAnimationDuration);
                set.setInterpolator(new DecelerateInterpolator());
                set.addListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {


                thumbView.setAlpha(1f);
                    expandedImageView.setVisibility(View.GONE);
                    mCurrentAnimator = null;
                }

                @Override
                public void onAnimationCancel(Animator animation) {
                    thumbView.setAlpha(1f);
                    expandedImageView.setVisibility(View.GONE);
                    mCurrentAnimator = null;
                }
            });
            set.start();
            mCurrentAnimator = set;
}

このプロセス全体をデバッグすると、zoomViewFromThumb メソッドの getGlobalVisibleRect メソッドが別の値を与えることがわかります。

行をデバッグすると

finalBounds.offset(-globalOffset.x, -globalOffset.y);

最初の 2 つのパラメータは 0 と -60 で、2 回目 (最小化して再作成した後は 15 と 360 です。

なぜそれが起こるのか分かりません。

指定されたthumbViewからView.XおよびView.Yパラメーターの追加を設定しようとしました.ObjectAnimatorでView.X、View.Yパラメーターの定数値を操作しようとしましたが、問題を解決するものはありません。

今私を助けてください。

マヌに挨拶

1. 編集: Android バージョン 4.1.2 で失敗しました。Android 4.0 のエミュレーターでテストしたところ、正常に動作しました。

2. 編集: xml ファイルは次のとおりです。最初のファイルは、メインのアクティビティを表す xml ファイル (アニメーション付き) で、2 番目のファイルは、メインの xml の FrameLayout にプッシュする TableLayout を表します。(注意してください、現在私は仕事をしていて、元のファイルにアクセスできません。覚えている限り、これらの xml ファイルは正常です)

最初

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/relZoom"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <FrameLayout
        android:id="@+id/frameZoomOne"
        android:layout_width="160dp"
        android:layout_height="215dp"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:layout_marginBottom="10dp"
        android:layout_marginLeft="10dp" >
    </FrameLayout>

    <FrameLayout
        android:id="@+id/frameZoomTwo"
        android:layout_width="160dp"
        android:layout_height="215dp"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:layout_marginRight="10dp"
        android:layout_marginTop="10dp" >
    </FrameLayout>

    <FrameLayout
        android:id="@+id/container"
        android:layout_width="300dp"
        android:layout_height="408dp"
        android:visibility="invisible" >
    </FrameLayout>

    <FrameLayout
        android:id="@+id/containerTwo"
        android:layout_width="300dp"
        android:layout_height="408dp"
        android:visibility="invisible" >
    </FrameLayout>

</RelativeLayout>

二番目

    <?xml version="1.0" encoding="utf-8"?>
    <TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/tableLayout1"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" >
        <TableRow
        android:id="@+id/tableRow1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="5dip" >

        <TextView
            android:id="@+id/textView1"
            android:text="Column 1"
            android:textAppearance="?android:attr/textAppearanceLarge" />

         <TextView
            android:id="@+id/textView2"
            android:text="Column 2"
            android:textAppearance="?android:attr/textAppearanceLarge" />
    </TableRow>
    <TableRow
        android:id="@+id/tableRow2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="5dip" >

        <ImageView
            android:id="@+id/imgView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/android" />
    </TableRow>
    <TableRow
        android:id="@+id/tableRow3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="5dip" >

        <TextView
            android:id="@+id/textView3"
            android:text="Column 3"
            android:textAppearance="?android:attr/textAppearanceLarge" />

         <TextView
            android:id="@+id/textView4"
            android:text="Column 4"
            android:textAppearance="?android:attr/textAppearanceLarge" />
    </TableRow>
</TableLayout>

3. 編集: xml ファイルを修正し、アクティビティを追加します。

public class SinglePlayerSp extends Activity implements OnClickListener
{
    private final Context mContext = this;
    private boolean mBackZoomOne = false;
    private FrameLayout frameZoomOne;
    private FrameLayout frameZoomTwo;
    private static Animator mCurrentAnimatorOne;
    private int mShortAnimationDuration;
    private float startScaleOne;
    private static Animator mCurrentAnimatorTwo;
    private float startScaleTwo;
    private Rect startBoundsOne;
    private Rect startBoundsTwo;
    private static View lastViewOne;
    private static View lastViewTwo;

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

        frameZoomOne = (FrameLayout) findViewById(R.id.frameZoomOne);
        frameZoomTwo = (FrameLayout) findViewById(R.id.frameZoomTwo);
        frameZoomOne.setOnClickListener(this);
        frameZoomTwo.setOnClickListener(this);

        mShortAnimationDuration = getResources().getInteger(android.R.integer.config_mediumAnimTime);

        cardItems = getIntent().getParcelableArrayListExtra(CARD_ITEMS);

        java.util.Collections.shuffle(cardItems);

    }

private void flipCard(boolean playerOneDeck, final int selectionFromPlayer, final boolean result)
    {
        Card cardItemOne = null;

            if (oneCards.get(0) != null)
            {
                cardItemOne = oneCards.get(0);
            }

            if (!mBackZoomOne)
            {
                getFragmentManager().beginTransaction().setCustomAnimations(R.animator.card_flip_right_in,
                        R.animator.card_flip_right_out, R.animator.card_flip_left_in, R.animator.card_flip_left_out).replace(
                        R.id.frameZoomOne, new CardBackFragment()).commit();
                mBackZoomOne = true;
            }
            else
            {
                getFragmentManager().beginTransaction().setCustomAnimations(R.animator.card_flip_right_in,
                        R.animator.card_flip_right_out, R.animator.card_flip_left_in, R.animator.card_flip_left_out).replace(
                        R.id.frameZoomOne,
                        CardFrontFragment.newInstance(cardItemPlayerOne, selectionFromPlayer, playerOneDeck)).commit();
                mBackZoomOne = false;

                zoomViewOneFromThumb(frameZoomOne, cardItemOne);
            }
    }

private void zoomViewOneFromThumb(final View thumbView, final Card cardItem)
    {
        if (mCurrentAnimatorOne != null)
        {
            mCurrentAnimatorOne.cancel();
        }

        lastViewOne = thumbView;
        View.getDefaultSize(0, 0);
        final FrameLayout expandFrameLayout = (FrameLayout) findViewById(R.id.container);

        LayoutInflater inflater =
                (LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View layout = inflater.inflate(R.layout.fragment_card_front_clickable, null);

        TableRow rowOne = (TableRow) layout.findViewById(R.id.tableRow1);
        rowOne.setOnClickListener(this);

        TextView cardone = (TextView) layout.findViewById(R.id.textView1);
        TextView cardtwo = (TextView) layout.findViewById(R.id.textView2);
        TextView cardthree = (TextView) layout.findViewById(R.id.textView3);
        TextView cardfour = (TextView) layout.findViewById(R.id.textView4);

        Locale locale = getApplicationContext().getResources().getConfiguration().locale;

        cardone.setText(cardItem.TextOne());
        cardtwo.setText(cardItem.getTextTwo());
        cardthree.setText(cardItem.getTextThree());
        cardfour.setText(cardItem.TextFour());

        expandFrameLayout.addView(layout);

        startBoundsOne = new Rect();
        final Rect finalBounds = new Rect();
        final Point globalOffset = new Point();

        thumbView.getGlobalVisibleRect(startBoundsOne);
        findViewById(R.id.containerSp).getGlobalVisibleRect(finalBounds, globalOffset);
        startBoundsOne.offset(-globalOffset.x, -globalOffset.y);
        finalBounds.offset(-globalOffset.x + 15, -globalOffset.y + 50);

        if ((float) finalBounds.width() / finalBounds.height() > (float) startBoundsOne.width()
                / startBoundsOne.height())
        {
            startScaleOne = (float) startBoundsOne.height() / finalBounds.height();
            float startWidth = startScaleOne * finalBounds.width();
            float deltaWidth = (startWidth - startBoundsOne.width()) / 2;
            startBoundsOne.left -= deltaWidth;
            startBoundsOne.right += deltaWidth;
        }
        else
        {
            startScaleOne = (float) startBoundsOne.width() / finalBounds.width();
            float startHeight = startScaleOne * finalBounds.height();
            float deltaHeight = (startHeight - startBoundsOne.height()) / 2;
            startBoundsOne.top -= deltaHeight;
            startBoundsOne.bottom += deltaHeight;
        }

        thumbView.setAlpha(0f);
        expandFrameLayout.setVisibility(View.VISIBLE);

        expandFrameLayout.setPivotX(0f);
        expandFrameLayout.setPivotY(0f);

        AnimatorSet set = new AnimatorSet();
        set.play(ObjectAnimator.ofFloat(expandFrameLayout, View.X, startBoundsOne.left, finalBounds.left)).with(
                ObjectAnimator.ofFloat(expandFrameLayout, View.Y, startBoundsOne.top, finalBounds.top)).with(
                ObjectAnimator.ofFloat(expandFrameLayout, View.SCALE_X, startScaleOne, 1f)).with(
                ObjectAnimator.ofFloat(expandFrameLayout, View.SCALE_Y, startScaleOne, 1f));
        set.setDuration(mShortAnimationDuration);
        set.setInterpolator(new DecelerateInterpolator());
        set.addListener(new AnimatorListenerAdapter()
        {
            @Override
            public void onAnimationEnd(Animator animation)
            {
                mCurrentAnimatorOne = null;
            }

            @Override
            public void onAnimationCancel(Animator animation)
            {
                mCurrentAnimatorOne = null;
            }
        });
        set.start();
        mCurrentAnimatorOne = set;
        startScaleFinal = startScaleOne; // with this or without this, i have the same problem
    }

private void minimizeViewOne(final View expandFrameLayout)
    {
        AnimatorSet set = new AnimatorSet();
        set.play(ObjectAnimator.ofFloat(expandFrameLayout, View.X, startBoundsOne.left)).with(
                ObjectAnimator.ofFloat(expandFrameLayout, View.Y, startBoundsOne.top)).with(
                ObjectAnimator.ofFloat(expandFrameLayout, View.SCALE_X, startScaleFinal)).with(
                ObjectAnimator.ofFloat(expandFrameLayout, View.SCALE_Y, startScaleFinal));
        set.setDuration(mShortAnimationDuration);
        set.setInterpolator(new DecelerateInterpolator());
        set.addListener(new AnimatorListenerAdapter()
        {
            @Override
            public void onAnimationEnd(Animator animation)
            {
                lastViewOne.setAlpha(1f);
                expandFrameLayout.setVisibility(View.GONE);
                mCurrentAnimatorOne = null;
            }

            @Override
            public void onAnimationCancel(Animator animation)
            {
                lastViewOne.setAlpha(1f);
                expandFrameLayout.setVisibility(View.GONE);
                mCurrentAnimatorOne = null;
            }
        });
        set.start();
        mCurrentAnimatorOne = set;
    }
}

これで完全なコードになりました。最後に onClick メソッドがあり、そこでユーザー アクションを受け取ります。そこから、minimizeView メソッドを呼び出し、いくつかのチェックを行った後、flipCard を呼び出します。それで全部です。

4

2 に答える 2