私は問題だけで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の両方の値が両方のビューで同じであることを確認しながら試してみました。
これらはどちらも問題の解決に役立ちませんでした。
最初に、Androidフレームワークがどのように魔法のShared Element Transitionを実行するか)を簡単に確認しましょう。
Shared Element Transitionは、実際にはAndroidフレームワークのlies真実は、共有要素の遷移を実行しているとき、実際にはActivities
間でビューを共有していない、ei、あなたは2つの個別のビューを処理します。これは、各Activity
に独自の独立したビューツリーがあるためです。
_view_a
_で識別されるビューをActivityA
からActivityB
の_view_b
_に移行しようとしているとします。
フレームワークが行うことは、まず、サイズ(width
、height
)や位置(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つの方法は、コードを次のように変更することです。
_class ActivityB extends Activity{
@Override
protected void onCreate(Bundle savedInstanceState) {
// ...
// Tell the framework to wait.
postponeEnterTransition();
}
}
_
_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;
}
});
...
}
}
_
あなたが探しているのはこの例です https://github.com/hujiaweibujidao/FabDialogMorph 。あなたが達成しようとしているのは標準ではないことに注意してくださいAndroid=トランジション、ChangeBounds
トランジションに基づいて独自のモーフィングトランジションを作成する必要があります。最初はそれが表示されていました Plaid のおかげで Nick Butcher のおかげで、より多くのヒントや背景について確認できます。
Android Docs を引用するだけです:
共有要素でアクティビティを開始します
- 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
マテリアルデザインと共有要素の遷移を完全に実装するために使用できるいくつかの最高のトリックと実践を示しています。