Android Two-Way Databinding between multiple Tab Layouts in ViewPager2

31 Views Asked by At

at the moment, i'm using single fragments or activities together with firebase ui and two-way databinding to display and edit my firestore data.

After downloading data from firebase in suspend fun, i call "binding.data = document".

Then i hide the ContentLoadingProgressBar and make the NestedScrollView visible.

After editing all textfields i collect the data with "Serializer().serialize(binding.data)" and forward it to my firebase upload service.


Now the question:

If i'm using ViewPager2 with TabLayout (see developer.android.com), how can i connect my firestore document to all "binding.data" of all tab fragments at the same time, so i can edit different parts of data in different tabs and collect them all at the end with "Serializer().serialize(binding.data)" to upload them?


Thanks in advance for your help!

Kotlin class containing data (compatible with Firestore up- and download)

package com.project.items.firestore

import android.text.format.DateFormat
import androidx.databinding.BaseObservable
import androidx.databinding.Bindable
import com.google.firebase.firestore.DocumentId
import com.google.firebase.firestore.Exclude
import com.project.BR
import java.util.*

class ArticleFirestoreDocument : BaseObservable() {
    companion object {
        fun build(
            id: String,
            ueberschrift: String,
            kategorie: String,
            zeit: Date,
            inhalt: String,
            links: ArrayList<String>,
            bilder: ArrayList<String>,
            visibility: String
        ): ArticleFirestoreDocument {
            val document = ArticleFirestoreDocument()
            document.id = id
            document.ueberschrift = ueberschrift
            document.kategorie = kategorie
            document.zeit = zeit
            document.inhalt = inhalt
            document.links = links
            document.bilder = bilder
            document.visibility = visibility
            return document
        }
    }

    @DocumentId
    @get:Bindable
    var id: String = ""
        set(value) {
            if (field != value) {
                field = value
                notifyPropertyChanged(BR.id)
            }
        }

    @get:Bindable
    var ueberschrift: String = ""
        set(value) {
            if (field != value) {
                field = value
                notifyPropertyChanged(BR.ueberschrift)
            }
        }

    @get:Bindable
    var kategorie: String = ""
        set(value) {
            if (field != value) {
                field = value
                notifyPropertyChanged(BR.kategorie)
            }
        }

    @get:Bindable
    var zeit: Date = Date()
        set(value) {
            if (field != value) {
                field = value
                notifyPropertyChanged(BR.zeit)
            }
        }

    @get:Bindable
    var inhalt: String = ""
        set(value) {
            if (field != value) {
                field = value
                notifyPropertyChanged(BR.inhalt)
            }
        }

    @get:Bindable
    var links: ArrayList<String> = arrayListOf()
        set(value) {
            if (field != value) {
                field = value
                notifyPropertyChanged(BR.links)
            }
        }

    @get:Bindable
    var bilder: ArrayList<String> = arrayListOf()
        set(value) {
            if (field != value) {
                field = value
                notifyPropertyChanged(BR.bilder)
            }
        }

    @get:Bindable
    var visibility: String = ""
        set(value) {
            if (field != value) {
                field = value
                notifyPropertyChanged(BR.visibility)
            }
        }

    fun getDateTime(date: Date?): String {
        return if (date != null) {
            val cal = Calendar.getInstance(TimeZone.getTimeZone("Europe/Berlin"))
            cal.time = date
            DateFormat.format("EEEE dd.MM.yyyy HH:mm", cal).toString() + " Uhr"
        } else {
            ""
        }
    }

    fun getDateTimeShort(date: Date?): String {
        return if (date != null) {
            val cal = Calendar.getInstance(TimeZone.getTimeZone("Europe/Berlin"))
            cal.time = date
            DateFormat.format("E dd.MM.yy HH:mm", cal).toString() + " Uhr"
        } else {
            ""
        }
    }

    fun getDate(date: Date?): String {
        return if (date != null) {
            val cal = Calendar.getInstance(TimeZone.getTimeZone("Europe/Berlin"))
            cal.time = date
            DateFormat.format("dd.MM.yyyy", cal).toString()
        } else {
            ""
        }
    }

    fun getTime(date: Date?): String {
        return if (date != null) {
            val cal = Calendar.getInstance(TimeZone.getTimeZone("Europe/Berlin"))
            cal.time = date
            DateFormat.format("HH:mm", cal).toString() + " Uhr"
        } else {
            ""
        }
    }

    @Exclude
    fun getEmojiText(): String {
        return ("${this.ueberschrift}\n\n" +
                "\uD83D\uDCC5 Datum: ${getDate(this.zeit)}\n" +
                "\uD83D\uDD50 Uhrzeit: ${getTime(this.zeit)}\n" +
                "\uD83D\uDDC3 Kategorie: ${this.kategorie}\n\n" +
                "\uD83D\uDCDD ${this.inhalt.replace("[ ]*\\\\n[ ]*".toRegex(), "\n").replace("\\\\t".toRegex(), "\t").trim()}\n\n" +
                this.links.joinToString(separator = "\n"))
            .trim()
    }
}

XML Layout (with data variable "ArticleFirestoreDocument" and two-way databinding, e.g. "@={data.kategorie}")

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>

        <variable
            name="data"
            type="com.project.items.firestore.ArticleFirestoreDocument" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <include
            android:id="@+id/toolbar"
            layout="@layout/include_material_toolbar_edit"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <androidx.core.widget.NestedScrollView
            android:id="@+id/nsv"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:background="?attr/colorSurface"
            app:layout_behavior="@string/appbar_scrolling_view_behavior"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/toolbar">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:fitsSystemWindows="true"
                android:orientation="vertical">

                <include
                    android:id="@+id/visibility"
                    layout="@layout/include_material_textfield_clickable_icon"
                    app:hint="@{@string/hint_rule}"
                    app:icon="@{@drawable/ic_outline_rule_24}"
                    app:iconDescription="@{@string/icon_rule}"
                    app:text="@={data.visibility}" />

                <include
                    android:id="@+id/headline"
                    layout="@layout/include_material_textfield"
                    app:hint="@{@string/hint_headline}"
                    app:text="@={data.ueberschrift}" />

                <include
                    android:id="@+id/category"
                    layout="@layout/include_material_textfield_clickable_icon"
                    app:hint="@{@string/hint_category}"
                    app:icon="@{@drawable/ic_outline_category_24}"
                    app:iconDescription="@{@string/icon_category}"
                    app:text="@={data.kategorie}" />

                <include
                    android:id="@+id/content"
                    layout="@layout/include_material_textfield_icon"
                    app:hint="@{@string/hint_content}"
                    app:icon="@{@drawable/ic_outline_notes_24}"
                    app:iconDescription="@{@string/icon_notes}"
                    app:text="@={data.inhalt}" />

                <include
                    android:id="@+id/links"
                    layout="@layout/include_material_textfield_icon_end"
                    app:hint="@{@string/hint_link}"
                    app:icon="@{@drawable/ic_outline_link_24}"
                    app:iconDescription="@{@string/icon_link}"
                    app:iconEnd="@{@drawable/ic_outline_add_24}"
                    app:iconEndDescription="@{@string/icon_add}" />

                <include
                    android:id="@+id/links_recyclerview"
                    layout="@layout/include_material_recyclerview"
                    app:isBottom="@{false}"
                    app:isDivider="@{false}"
                    app:isFull="@{false}" />

                <include
                    android:id="@+id/pictures"
                    layout="@layout/include_material_textfield_clickable_icon"
                    app:icon="@{@drawable/ic_outline_photo_24}"
                    app:iconDescription="@{@string/icon_photo}"
                    app:text="@{@string/hint_images + @string/append_select}" />

                <include
                    android:id="@+id/pictures_recyclerview"
                    layout="@layout/include_material_recyclerview_horizontal"
                    app:isBottom="@{true}"
                    app:isDivider="@{false}"
                    app:isFull="@{true}" />
            </LinearLayout>
        </androidx.core.widget.NestedScrollView>

        <androidx.core.widget.ContentLoadingProgressBar
            android:id="@+id/clpb"
            style="?android:attr/progressBarStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:indeterminate="true"
            android:visibility="gone"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/toolbar" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>
0

There are 0 best solutions below