web-dev-qa-db-ja.com

共有要素の移行が機能しない

私は問題だけでgithubプロジェクトを作りました。あなたはそれを見ることができます/それを複製します/ここからビルドします: https://git.io/vMPqb


フラグメントの遷移で共有要素を機能させようとしています。

プロジェクトには2つのFABがあります-FeatherとPlaneです。羽と平面は共有要素です。 Featherをクリックすると、SheetDialogが開き、FeatherがPlaneダイアログにアニメーション表示されます。現時点ではそれはできません。私はその理由を特定しようとしています。

API 24でこれを実行しているので、バージョン21以下でサポートされない遷移の問題は問題にならないことに注意してください。

共有要素の遷移が機能しない理由を誰かに教えてもらえますか?

リポジトリにあるものをエコーするには、4つの重要なファイルがあります。

主な活動

package test.example.fabpop;

import Android.os.Bundle;
import Android.support.design.widget.FloatingActionButton;
import Android.support.transition.ChangeBounds;
import Android.support.transition.Fade;
import Android.support.v4.app.FragmentTransaction;
import Android.support.v7.app.AppCompatActivity;
import Android.view.View;

public class MainActivity extends AppCompatActivity {

    FloatingActionButton fab_feather;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        fab_feather = (FloatingActionButton) findViewById(R.id.initial_fab_feather);
    }

    public void fabClick(View view) {
        SheetDialog dialogFragment = new SheetDialog();

        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();

        // This seemingly has no effect. I am trying to get it to work.
        transaction.addSharedElement(fab_feather, "transition_name_plane");

        dialogFragment.setSharedElementEnterTransition(new ChangeBounds());
        dialogFragment.setSharedElementReturnTransition(new Fade(Fade.OUT));

        dialogFragment.show(transaction, "frag_tag");
    }
}

activity_main.xmlレイアウト

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:tools="http://schemas.Android.com/tools"
    Android:id="@+id/activity_main"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:paddingBottom="@dimen/activity_vertical_margin"
    Android:paddingLeft="@dimen/activity_horizontal_margin"
    Android:paddingRight="@dimen/activity_horizontal_margin"
    Android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="test.example.fabpop.MainActivity">

    <LinearLayout
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_alignParentEnd="true"
        Android:orientation="vertical">
        <TextView
            Android:layout_width="200dp"
            Android:layout_height="wrap_content"
            Android:text="Transition to a BottomSheetDialogFragment that shares this FAB"
            Android:textAlignment="center"/>

        <!--  Feather FAB  -->
        <Android.support.design.widget.FloatingActionButton
            Android:id="@+id/initial_fab_feather"
            Android:layout_width="52dp"
            Android:layout_height="52dp"
            Android:layout_margin="16dp"
            Android:layout_gravity="center"
            Android:onClick="fabClick"
            Android:transitionName="transition_name_feather"
            Android:src="@drawable/ic_feather"
            />
    </LinearLayout>


</RelativeLayout>

SheetDialog

package test.example.fabpop;

import Android.os.Bundle;
import Android.support.annotation.Nullable;
import Android.support.design.widget.BottomSheetDialogFragment;
import Android.view.LayoutInflater;
import Android.view.View;
import Android.view.ViewGroup;

public class SheetDialog extends BottomSheetDialogFragment {

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater,
                             @Nullable ViewGroup container,
                             @Nullable Bundle savedInstanceState) {

        return inflater.inflate(R.layout.dialog_sheet, container, false);
    }
}

dialog_sheet.xmlレイアウト

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:orientation="vertical" Android:layout_width="match_parent"
    Android:layout_height="match_parent">

    <!--  Plane FAB  -->
    <Android.support.design.widget.FloatingActionButton
        Android:id="@+id/final_fab_plane"
        Android:layout_width="75dp"
        Android:layout_height="75dp"
        Android:layout_margin="16dp"
        Android:transitionName="transition_name_plane"
        Android:src="@drawable/ic_plane"
        />

</LinearLayout>

1つのアクティビティと1つのフラグメント間の遷移に共有要素を含めることはできませんか?おそらく、アクティビティ間またはフラグメント間でのみ可能ですが、2つのタイプ間では不可能ですか?多分これが私がそれを機能させることができない理由ですか?

更新:

今追加してみました<item name="Android:windowContentTransitions">true</item>アプリのテーマに。

また、transitionNameの両方の値が両方のビューで同じであることを確認しながら試してみました。

これらはどちらも問題の解決に役立ちませんでした。

18
atwrk

始める前に...

最初に、Androidフレームワークがどのように魔法のShared Element Transitionを実行するか)を簡単に確認しましょう。

Shared Element Transitionは、実際にはAndroidフレームワークのlies真実は、共有要素の遷移を実行しているとき、実際にはActivities間でビューを共有していない、ei、あなたは2つの個別のビューを処理します。これは、各Activityに独自の独立したビューツリーがあるためです。

えっ?

_view_a_で識別されるビューをActivityAからActivityBの_view_b_に移行しようとしているとします。

フレームワークが行うことは、まず、サイズ(widthheight)や位置(x)などの_view_a_の特定のプロパティを最初に検索します。 、y)内のActivityA。次に、これらの情報をActivityBに渡し、これらのプロパティを_view_b_に適用して、ActivityAが閉じたときに_view_a_とまったく同じ場所を占めるようにします。その後、フレームワークは、_view_b_をActivityBにあると想定されるものに逆アニメーション化することで、遷移を開始します。そして、これは共有されているビューの幻想が作成される方法です。マジック!

したがって、

上記から推測できることは、アニメーションを開始する前に、_view_b_がActivityBにすでに作成されていることを確認する必要があるということです。それ以外の場合、これは不可能です。

Fragmentを使用する場合、

FragmentTransaction.commit()を呼び出すと、フラグメントトランザクションがスケジュールされます(フラグメントを含むアクティビティが作成された直後にフラグメントが作成されることはありません)。

したがって、あなたのケースでは、ActivityBが作成されたときに_view_b_が欠落しています(説明されているように、これはそのフラグメントを含むフラグメントがまだ作成されていないためです)。

解決

アニメーションを開始する前に、_view_b_が作成されていることを確認してください。

そのためには、フレームワークに通常のことを行わず、代わりに信号を待ってからアニメーションを作成するようにフレームワークに指示する方法を見つける必要があります。

これを実装する1つの方法は、コードを次のように変更することです。

アクティビティB

_class ActivityB extends Activity{
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // ...
        // Tell the framework to wait.
        postponeEnterTransition();
    }
}
_

フラグメントB

_class FragmentB extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View viewB = getView().findViewById(R.id.view_b);
    sharedview.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
        @Override
        public boolean onPreDraw() {
                // Tell the framework to start.
                sharedview.getViewTreeObserver().removeOnPreDrawListener(this);
                getActivity().startPostponedEnterTransition(); 
                return true;
         }
       });
       ...
    }
}
_

参考文献

アクティビティとフラグメントの遷移の開始

14
Anix PasBesoin

あなたが探しているのはこの例です https://github.com/hujiaweibujidao/FabDialogMorph 。あなたが達成しようとしているのは標準ではないことに注意してくださいAndroid=トランジション、ChangeBoundsトランジションに基づいて独自のモーフィングトランジションを作成する必要があります。最初はそれが表示されていました Plaid のおかげで Nick Butcher のおかげで、より多くのヒントや背景について確認できます。

1
rom4ek

Android Docs を引用するだけです:

共有要素でアクティビティを開始します

  1. Android:transitionName属性を使用して、両方のレイアウトの共有要素に共通の名前を割り当てます。

私が見たところ、両方のXMLが同じAndroid:transitionNameを共有していません。

XMLレイアウトのAndroid:transitionName(activity_main.xmlとdialog_sheet.xml)の両方を同じ文字列に変更してみてください。例:transition_plane_feather

私は自分でコードをテストしていませんが、それは良い出発点になると思います。

ボーナスチップ

より低いAPIレベル(Lollipop以前)との互換性なしにマテリアルデザインを完全に実装することを計画している場合は、Google UI/UXデザイナーによって作成されたサンプルをチェックアウトすることを強くお勧めします: https://github.com/ニックブッチャー/チェック柄

また、そのサンプルの優れた補足YouTubeビデオもご覧ください: https://www.youtube.com/watch?v=EjTJIDKT72M

マテリアルデザインと共有要素の遷移を完全に実装するために使用できるいくつかの最高のトリックと実践を示しています。

1
Nicholas Lie