[JAVA] Erstellt eine multifunktionale Routing-Bibliothek für Android, die auch Shared Element - MoriRouter unterstützt

Überblick

Es ist einige Jahre her, seit Material Design angekündigt wurde und Shared Element erschien. Soweit ich die Apps im Store sehen kann, sind nicht viele davon installiert.

Ich wollte es in die Entwicklung einbauen, an der ich mehrmals teilnehme, aber aus irgendeinem Grund bin ich hierher gekommen, ohne es einzubringen.

Dieses Mal, als ich die App entwickelte, wurde ich immer eifriger, eine Routing-Bibliothek zu erstellen, mit der ich zufrieden war, und Annotation Processor zu verwenden. Deshalb entschied ich mich, die Art von Routing zu erstellen, die ich für gut halte. tat.

Ich konnte keine Bibliothek finden, die Shared Element gut aussehen ließ, selbst nachdem ich Github gefolgt war, also beschloss ich, mich auch darauf zu konzentrieren.

Ergebnisse

MoriRouter ezgif-3-5ae226e28e.gif

https://github.com/chuross/mori-router

Eine Bibliothek, die die Entwicklung von Bildschirmübergängen mithilfe von ** Fragment ** mithilfe der automatischen Generierung mithilfe von Anmerkungen unterstützt.

Eigenschaften

Wie benutzt man

Download

repositories {
    maven { url "https://jitpack.io" }
}
dependencies {
    implementation 'com.github.chuross.mori-router:annotation:x.x.x'
    annotationProcessor 'com.github.chuross.mori-router:compiler:x.x.x' // or kpt
}

Basic

Fügen Sie einfach die Annotation "@ RouterPath" zu dem Fragment hinzu, das Sie als Bildschirmübergang verwenden möchten

Der Name von @ RouterPath und @ Argument ist der Methodenname des Routers.

@RouterPath(name = "main")
class MainScreenFragment : Fragment() {

    @Argument
    lateinit var param1: String

    @Argument(name = "hoge", required = false)
    var param3: ArrayList<String> = arrayListOf()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        MoriBinder.bind(this) // @Sie können in jedes Argumentfeld einen Wert eingeben
    }
    ....
}

Wenn Sie dies erstellen, wird automatisch eine Klasse namens "MoriRouter" generiert und eine Methode zum Starten dieses Bildschirms hinzugefügt.

Generieren und verwenden Sie danach einen Router für die Basisaktivität.

val transitionFactory = DefaultTransitionFactory { Fade() } // android.support.Übergang oder Android.Übergangsanimation

val options = MoriRouterOptions.Builder(R.id.container) //FrameLayout-ID zum Zeichnen von Bildschirmübergängen
                .setEnterTransitionFactory(transitionFactory) //Allgemeine Animation beim Start des Bildschirms
                .setExitTransitionFactory(transitionFactory) //Allgemeine Animation am Ende des Bildschirms
                .build()

val router = MoriRouter(supportFragmentManager, options)

//Eine Methode für den Bildschirmübergang wird automatisch generiert
router.main("required1", 1000) // main(String param1, Integer param2)
    .hoge(arrayListOf("fuga")) // optional value
    .launch() //Starten Sie MainScreenFragment

router.pop() //Rufen Sie dies auf, wenn Sie zum vorherigen Bildschirm zurückkehren

Der zuvor in der Anmerkung definierte Inhalt wird unverändert als Methodenname generiert.

Übergeben Sie anschließend bei Bedarf die für den Bildschirmübergang erforderlichen Parameter und rufen Sie am Ende "launch" auf, um den Bildschirmübergang im Layout von R.id.container auszuführen. Praktisch: smiley :: v:

Fragment Builder Durch die Verwendung von "@ RouterPath" wurde es bequem, Bildschirmübergänge zu generieren. In Wirklichkeit kann der Bildschirm jedoch auch aus Fragmenten bestehen, daher möchte ich dies auch genießen.

In einem solchen Fall kann die Builder-Klasse automatisch generiert werden, indem "@ WithArguments" anstelle von "@ RouterPath" hinzugefügt wird.

@WithArguments
class HogeFragment : Fragment() {

    @Argument
    lateinit var hogeName: String
    ....
}

In diesem Fall wird die Klasse "HogeFragmentBuilder" automatisch generiert, sodass Sie wie folgt damit umgehen können.

val fragment: HogeFragment = HogeFragmentBuilder(hogeName).build()

Praktisch: smiley :: v:

Es gibt kein Problem, selbst wenn Sie "FragmentArgs" oder "AutoBundle" verwenden, da es einen Vorteil gibt, dass Sie die Beschreibung hier vereinheitlichen können.

Überschreiben der Übergangsanimation

Der zum Zeitpunkt der Initialisierung von MoriRouter übergebene Enter / Exit-Übergang ist allen Bildschirmen gemeinsam und wird zum Zeitpunkt des Übergangs verwendet.

Es gibt jedoch Fälle, in denen Sie eine dedizierte Animation auf einem bestimmten Bildschirm angeben möchten.

In einem solchen Fall kann dies durch Angabe von "overrideEnterTransitionFactory" und "overrideExitTransitionFactory" in "@ RouterPath" definiert werden.

@RouterPath(
    name = "main",
    overrideEnterTransitionFactory = MainScreenTransitionFactory::class,
    overrideExitTransitionFactory = MainScreenTransitionFactory::class
)
class MainScreenFragment : Fragment() {

Übergang von der URL zu einem bestimmten Bildschirm

Durch Angabe des URL-Formats in "@ RouterPath" können Sie einen bestimmten Bildschirm über die URL starten.

Da mehrere Zielformate angegeben werden können, kann es ordnungsgemäß mit einem benutzerdefinierten Schema oder http / https verwendet werden.

@RouterPath(
  name = "second",
  uris = [
    "example://hoge/{hoge_id}/{fuga}",
    "https://example.com/hoge/{hoge_id}/{fuga}"
  ]
)
class SecondScreenFragment : Fragment() {

    @UriArgument(name = "hoge_id")
    var hogeId: Int

    @UriArgument
    var fuga: String

    // @Bei Verwendung von UriArgument@Argument(required=true)Kann nicht verwendet werden
    @Argument(required = false)
    var piyo: String? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        MoriBinder.bind(this)
    }
}

Durch Verwendung von {}} im Format kann der Wert erhalten werden, indem er dem Feld in der View-Klasse zugeordnet wird.

Danach gibt es in "MoriRouter" eine Methode namens "Versand". Wenn Sie also Uri dort passieren, können Sie den Bildschirm wechseln.

router.dispatch(Uri.parse("example://hoge/123/test")) // launch SecondScreenFragment (hogeId = 123, fuga=test)
router.dispatch(Uri.parse("https://example.com/hoge/123/test")) // launch SecondScreenFragment (hogeId = 123, fuga=test)

Praktisch: smiley :: v:

Unterstützung für gemeinsam genutzte Elemente

Die Implementierung von Shared Element wird gut animiert, wenn Sie denselben Übergangsnamen für die Übergangsquelle und das Übergangsziel angeben ... Ich hatte eine Zeit, in der ich das dachte.

Wenn es ein einfaches Muster ist, wird es immer noch funktionieren, aber in Wirklichkeit gibt es viele Muster, die nicht so einfach sind.

In dieser Bibliothek möchte ich sie vorstellen, da sie so weit wie möglich vereinfacht und einfach zu implementieren ist.

Basic

Setzen Sie zunächst den TransitionName auf die Übergangsquelle von XML oder Code. ** Stellen Sie sicher, dass View eine ID hat **

<YourLayout
    android:id="@+id/your_id" <!-- must have view id -->
    android:transitionName="your_transition_name" />

--Code

ViewCompat.setTransitionName(yourView, "your_transition_name");

Definieren Sie als Nächstes die Übergangszielklasse so, dass sie SharedElement empfängt.

** Stellen Sie sicher, dass die Animation für gemeinsam genutzte Elemente in "sharedEnterTransitionFactory" und "sharedExitTransitionFactory" festgelegt ist. **

Danach übergeben Sie die ID der Ansicht des Übergangsziels an das "bindElement" von "MoriBinder" und Sie sind fertig. Stellen Sie sicher, dass die Ansichten Quellquelle und Übergangsziel dieselbe ID haben.

@RouterPath(
    name = "third",
    sharedEnterTransitionFactory = ThirdScreenSharedTransitionFactory::class,
    sharedExitTransitionFactory = ThirdScreenSharedTransitionFactory::class
)
class ThirdScreenFragment : Fragment() {
   ....
   override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        //Geben Sie dieselbe ID an, die für das View-Element angegeben wurde, das Sie in der Übergangsquelle freigeben möchten
        //Die Ansichten für die Übergangsquelle und das Übergangsziel haben dieselbe ID
        MoriBinder.bindElement(this, R.id.your_id)
   }
}

Nachdem Sie es bisher definiert haben, müssen Sie nur noch das Element Ansicht hinzufügen, das Sie zum Zeitpunkt des Bildschirmübergangs freigeben möchten.

router.third()
       .addSharedElement(yourView) //Legen Sie die Ansicht fest, die Sie freigeben möchten
       .launch()

Danach wird es mit der "TransitionFactory" animiert, die zum Zeitpunkt des Übergangs gut angegeben ist.

Wenn Sie es mit RecyclerView oder ViewPager verwenden, wird es in den folgenden Hinweisen ausführlich beschrieben. Beachten Sie, dass ** TransitionName eindeutig sein muss **

Wenn sich das freigegebene Element dynamisch ändert

Das Übergangsziel kann ein freigegebenes Element für ViewPager sein, und eine andere Ansicht kann am Ende des Bildschirms als freigegebenes Element zurückgegeben werden.

In diesen Fällen kann "addSharedElement" nicht verwendet werden und muss manuell zugeordnet werden. Diese Bibliothek generiert jedoch auch automatisch Klassen, die die manuelle Zuordnung unterstützen, sodass dies ein einfacher Gewinn ist.

Legen Sie zunächst denselben Übergangsnamen in der Ansicht der Übergangsquelle und des Übergangsziels fest. Im Gegensatz zu früher muss bei der manuellen Zuordnung bekannt sein, wie der TransitionName der Übergangsquelle sowie das Übergangsziel generiert werden.

Ich bin so Ich wollte ein Präfix von der Übergangsquelle bekommen.

ViewCompat.setTransitionName(yourView, "your_transition_name");

Definieren Sie danach "manualSharedViewNames" in "@ RouterPath" der Übergangszielansicht. Dies wird als Name verwendet, der die Übergangsquelle und das Übergangsziel getrennt vom Übergangsnamen verbindet. (Ein anderer Name als TransitionName ist gut)

@RouterPath(
    name = "third",
    manualSharedViewNames = ["shared_view_image"],
    sharedEnterTransitionFactory = ThirdScreenSharedTransitionFactory::class,
    sharedExitTransitionFactory = ThirdScreenSharedTransitionFactory::class
)
class ThirdScreenFragment : Fragment() {
   ....

   override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)

       val callback = ThirdSharedElementCallBack()
                          .sharedViewImage({ /*Rufen Sie das aktuelle Fragment aus dem ViewPager ab und geben Sie die Ansicht zurück, in der das SharedElement enthalten sein soll*/ })

       setEnterSharedElementCallback(callback)
   }
}

Setzen Sie danach "setEnterSharedElementCallback", um das Übergangsziel zu vervollständigen.

ThirdSharedElementCallBack ist ein automatisch generierter Code, der die manuelle Zuordnung vereinfacht, indem über ihn ein Rückruf erstellt wird.

Als nächstes definieren wir die Übergangsquelle

@RouterPath(
    name = "second"
)
class SecondScreenFragment : Fragment() {
   ....

   override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)

       val callback = ThirdSharedElementCallBack()
                        .sharedViewImage({ /*Prozess zum Abrufen der Ansicht von RecyclerView*/ })

       setExitSharedElementCallback(callback)
   }

   ....

   override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        ....

        // call manualSharedMapping
        router.third().manualSharedMapping(context).launch()
   }
}

Setzen Sie nun setExitSharedElementCallback. SharedElementCallback ist das gleiche wie das vorherige.

Danach können Sie beim Aufrufen des Übergangsprozesses "manualSharedMapping" anstelle von "addSharedElement" aufrufen.

Praktisch: smiley :: v:

Hinweise zu gemeinsam genutzten Elementen

Der Übergangsname muss im Prinzip ** eindeutig ** sein (ich bin süchtig)

Dies gilt natürlich auch für RecyclerView und ViewPager. Selbst wenn Sie dieselbe Ansicht erneut verwenden, wird sie nicht animiert, wenn Sie auch den Übergangsnamen verwenden.

Im Fall von RecyclerView muss beispielsweise für jede Position ein anderer TransitionName angegeben werden, z. B. Transition_view_image_0 Transition_view_image_1.

Wenn Sie dasselbe Fragment mit RecyclerView in ViewPager verwenden möchten, müssen Sie es durch "ViewPager-Index" + "RecyclerView-Index" wie "Transition_view_image_1_1" teilen. (Mendo)

Nachwort

Ich denke, es gibt noch viele Dinge zu ändern, aber ich denke, dass das SharedElement und der Routing-Code sauberer sein werden.

Ich habe vor, es weiter zu pflegen, also möchte ich es weiter verbessern. Ich denke, es gibt immer noch einen guten Weg, also werde ich vielleicht einen anderen Ansatz versuchen.

Wenn Sie das Beispiel lesen, können Sie möglicherweise etwas wie "Wie implementiere ich das ?: Denken:" verstehen.

https://github.com/chuross/mori-router/tree/master/app

Recommended Posts

Erstellt eine multifunktionale Routing-Bibliothek für Android, die auch Shared Element - MoriRouter unterstützt
Erstellt eine Bibliothek, die die Handhabung von freigegebenen Android-Einstellungen erleichtert
LazyBLE Wrapper (hat eine Bibliothek erstellt, die Android BLE sehr einfach macht) v0.14
Ich habe eine Bibliothek zum Anzeigen von Tutorials auf Android erstellt.
Suchen Sie eine Java-Bibliothek für ein mögliches basianisches Netzwerk