Ich habe ein Github-Projekt nur mit dem Thema gemacht. Sie können es von hier aus sehen/klonen/erstellen: https://git.io/vMPqb
Ich versuche, gemeinsame Elemente für einen Fragment-Übergang zu erhalten.
Es gibt zwei FABs im Projekt - Feder und Flugzeug. Feder und Flugzeug sind gemeinsame Elemente. Wenn Sie auf Feder klicken, wird der SheetDialog geöffnet, und Feder sollte sich im Ebenendialogfeld befinden. Im Moment tut es das nicht, und ich versuche zu ermitteln, warum.
Es kann sich lohnen, darauf hinzuweisen, dass ich dies auf API 24 ausführte, sodass Probleme mit Übergängen, die nicht unter Version 21 unterstützt werden, nicht das Problem sind.
Kann mir jemand sagen, warum gemeinsame Elementübergänge nicht funktionieren?
Um zu bestätigen, was im Repo enthalten ist, gibt es vier wichtige Dateien:
Hauptaktivität
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 Layout
<?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 Layout
<?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>
Ist es nicht möglich, ein gemeinsames Element an einem Übergang zwischen einer Aktivität und einem Fragment zu haben? Vielleicht ist nur zwischen Aktivität zu Aktivität oder Fragment zu Fragment möglich, jedoch nicht zwischen den beiden Typen? Vielleicht kann ich es deshalb nicht zum Laufen bringen?
Aktualisieren:
Ich habe jetzt versucht, <item name="Android:windowContentTransitions">true</item>
zum Design der App hinzuzufügen.
Ich habe jetzt auch versucht, sicherzustellen, dass beide TransitionName-Werte in beiden Ansichten gleich sind.
keines von ihnen hat dazu beigetragen, das Problem zu beheben.
Lassen Sie uns zunächst einige Punkte hervorheben, wie das Android-Framework den Übergang zu magischen freigegebenen Elementen durchführt.
Ein Übergang zu einem gemeinsamen Element ist nur eine Lüge des Android-Frameworks. Wenn Sie einen Übergang für ein gemeinsames Element durchführen, geben Sie eigentlich keine Ansicht für Ihre Aktivitäten frei, z. B. hat jede Aktivität eine unabhängige Ansichtsbaumstruktur.
Angenommen, Sie versuchen, eine durch element1
identifizierte element
von Activity1
auf einen element2
in Activity2
zu übertragen.
Was das Framework tut, ist, dass es nach bestimmten Informationen sucht, wie z. B. der Größe (width
, height
) und der Position (x
, y
) Ihres element1
im Activity1
. Anschließend übergibt er diese Informationen an Activity2
, wendet sie auf element2
an und startet den Aktivitätsübergang durch die umgekehrte Animation Ihres element2
, wodurch diese Illusion des gemeinsam genutzten Elements entsteht.
Dies setzt jedoch voraus, dass der Activity2
erstellt wird und die view
, die element2
entspricht, gefunden werden muss, bevor eine Animation gestartet werden kann.
Wenn Sie eine Fragment
verwenden, wird der Aufruf von FragmentTransaction.commit()
einfach Ihre Fragmenttransaktion einplanen (das Fragment wird nicht sofort erstellt). Wenn Ihr Activity2
erstellt wird, fehlt Ihr element2
(wie bereits erwähnt, weil das Fragment noch nicht erstellt wurde ).
Stellen Sie sicher, dass Ihr element2
erstellt wurde, bevor die Animation startet. Sie müssen also einen Weg finden, dem Framework mitzuteilen, dass es nicht das Übliche tun soll, sondern warten Sie auf Ihr Signal, bevor Sie die Animation erstellen.
Eine Möglichkeit, dies zu tun, besteht darin, Ihren Code so zu ändern, dass er dem folgenden ähnelt:
class Activity2 extends Activity{
@Override
protected void onCreate(Bundle savedInstanceState) {
// ...
// Tell the framework to wait.
postponeEnterTransition();
}
}
class Fragment2 extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View element2 = getView().findViewById(R.id.element);
sharedview.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
// Tell the framework to start.
sharedview.getViewTreeObserver().removeOnPreDrawListener(this);
getActivity().startPostponedEnterTransition();
return true;
}
});
...
}
}
Was Sie suchen, ist dieses Beispiel: https://github.com/hujiaweibujidao/FabDialogMorph . Beachten Sie, dass das, was Sie zu erreichen versuchen, kein Standard-Übergang von Android ist eigener Morphing-Übergang, basierend auf ChangeBounds
-Übergang. Ursprünglich wurde es in Plaid gezeigt, dank Nick Butcher dafür, sodass Sie weitere Tipps und Hintergründe finden können.
Zitieren Sie einfach die Android-Dokumente :
Aktivität mit einem gemeinsamen Element starten
- Weisen Sie den gemeinsam genutzten Elementen in beiden Layouts einen allgemeinen Namen mit dem Attribut Android: transitionName zu.
Soweit ich sehe, teilen beide XMLs nicht dasselbe Android: transitionName.
Ändern Sie beide Android: transitionName im XML-Layout (activity_main.xml und dialog_sheet.xml) in dieselbe Zeichenfolge. Beispiel: transition_plane_feather
Ich habe die Codes nicht selbst getestet, aber ich denke, das könnte ein guter Ausgangspunkt sein.
Wenn Sie vorhaben, Material Design ohne Kompatibilität mit niedrigeren API-Levels (vor Lollipop) vollständig zu implementieren, empfehle ich Ihnen dringend, ein Beispiel eines Google UI/UX Designers anzusehen: https://github.com/nickbutcher/ kariert
Schauen Sie sich auch das hervorragende YouTube-Video zu diesem Beispiel an: https://www.youtube.com/watch?v=EjTJIDKT72M
Es zeigt Ihnen einige der besten Tricks und Praktiken, die Sie zur vollständigen Implementierung des Materialdesigns sowie für gemeinsame Elementübergänge verwenden können.