Auf dieser Seite

Qt Quick für Android Studio-Projekte

Android-App mit zwei QtQuickView-Bereichen, in denen QML-Inhalte und Java-Steuerelemente zur Interaktion angezeigt werden

Qt Quick Die Beispiele für die Android-API sind Android Studio-Projekte

Die API-Beispiele für „ Qt Quick “ für Android werden als Android Studio-Projekte bereitgestellt. Die Projektordner befinden sich in Ihrem Qt-Installationsverzeichnis.

Beispielsweise befinden sie sich unter dem Standard-Installationspfad für Windows hier:

C:\Qt\Examples\Qt-<patch-release-number>\platforms\android\<example-name>

Diese Projekte sind bereits für die Verwendung einer mit dieser Qt-Version kompatiblen Version des Qt-Gradle-Plugins konfiguriert.

Übersicht

Dieses Beispiel enthält ein Qml-Projekt, das Sie mit dem Plugin „Qt Tools for Android Studio“ in Android Studio importieren können. Es gibt Java- und Kotlin-Projekte, die das Qml-Projekt mithilfe der QtQuickView-API als Ansicht verwenden.

Weitere Informationen zur Funktionsweise von QML finden Sie unter Qt Qml. Diese Dokumentation konzentriert sich darauf, wie eine QML-Komponente mithilfe von Java oder Kotlin in Android-Anwendungen eingebettet wird.

Änderungen in „ main() “ sind aufgrund der „ Qt Quick “ für Android-APIs erforderlich

Die Datei „main.cpp“ einer typischen „ Qt Quick “-Anwendung sieht wie folgt aus:

#include <QGuiApplication>
#include <QQmlApplicationEngine>

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;
    QObject::connect(
        &engine,
        &QQmlApplicationEngine::objectCreationFailed,
        &app,
        []() { QCoreApplication::exit(-1); },
        Qt::QueuedConnection);
    engine.loadFromModule("MyQtQuickProject", "Main");

    return app.exec();
}

In „ main() “ müssen wir keine QML-Engine erstellen oder QML-Dateien laden, da dies später von den Qt Quick -View-APIs übernommen wird. Alles, was wir in „ main() “ benötigen, ist:

#include <QGuiApplication>

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    return app.exec();
}

Einrichten des Layouts

Sowohl für Java- als auch für Kotlin-Projekte müssen wir das Layout für die QtQuickViewsin „ app/src/main/res/layout/activity_main.xml “ einrichten.

Innerhalb von „ LinearLayout “ richten wir für jede QtQuickView zwei „FrameLayouts“ ein.

 <FrameLayout
    android:id="@+id/firstQmlFrame"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_weight="1">
</FrameLayout>

<FrameLayout
    android:id="@+id/secondQmlFrame"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_weight="1">
</FrameLayout>

Auf die Datei „ id “ wird in der in Kotlin oder Java programmierten „MainActivity“ verwiesen.

Importieren automatisch generierter Java-Klassen für QML-Typen

Die Java-Klassen für unsere QML-Typen werden beim Erstellen des Qt Quick -Projekts generiert. Diese müssen importiert werden, bevor wir sie in unserer MainActivity verwenden können.

import org.qtproject.example.qtquickview.QmlModule.Main;
import org.qtproject.example.qtquickview.QmlModule.Second;
import org.qtproject.example.qtquickview.QmlModule.Main
import org.qtproject.example.qtquickview.QmlModule.Second

Hinweis: Weitere Informationen zur Java-Codegenerierung von QML-Komponentenfinden Sie unter der CMake-Variablen ` QT_ANDROID_GENERATE_JAVA_QTQUICKVIEW_CONTENTS `.

Die Methode `onCreate()` von `MainActivity`

Zunächst betrachten wir die Methode `onCreate()` der Klasse ` MainActivity` in den Java- und Kotlin-Projekten.

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    m_qmlViewBackgroundText = findViewById(R.id.qmlViewBackgroundText);
    m_qmlStatus = findViewById(R.id.qmlStatusText);
    m_androidControlsLayout = findViewById(R.id.javaRelative);
    m_colorBox = findViewById(R.id.qmlColorBox);
    m_switch = findViewById(R.id.disconnectQmlListenerSwitch);
    m_switch.setOnClickListener(view -> switchListener());
    QtQuickView m_firstQuickView = new QtQuickView(this);
    QtQuickView m_secondQuickView = new QtQuickView(this);

    // Set status change listener for m_qmlView
    // listener implemented below in OnStatusChanged
    m_firstQmlContent.setStatusChangeListener(this);
    m_secondQmlContent.setStatusChangeListener(this);
    final ViewGroup.LayoutParams params = new FrameLayout.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
    FrameLayout m_firstQmlFrameLayout = findViewById(R.id.firstQmlFrame);
    m_firstQmlFrameLayout.addView(m_firstQuickView, params);
    FrameLayout m_secondQmlFrameLayout = findViewById(R.id.secondQmlFrame);
    m_secondQmlFrameLayout.addView(m_secondQuickView, params);
    m_firstQuickView.loadContent(m_firstQmlContent);
    m_secondQuickView.loadContent(m_secondQmlContent);

    Button m_changeColorButton = findViewById(R.id.changeQmlColorButton);
    m_changeColorButton.setOnClickListener(view -> onClickListener());
    Button m_rotateQmlGridButton = findViewById(R.id.rotateQmlGridButton);
    m_rotateQmlGridButton.setOnClickListener(view -> rotateQmlGrid());
}
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    m_binding = ActivityMainBinding.inflate(layoutInflater)
    val view = m_binding.root
    setContentView(view)

    m_binding.disconnectQmlListenerSwitch.setOnCheckedChangeListener { button, checked ->
        switchListener(
            button,
            checked
        )
    }

    val firstQtQuickView = QtQuickView(this)
    val secondQtQuickView = QtQuickView(this)

    // Set status change listener for m_qmlView
    // listener implemented below in OnStatusChanged
    m_firstQmlContent.setStatusChangeListener(this)
    m_secondQmlContent.setStatusChangeListener(this)

    val params: ViewGroup.LayoutParams = FrameLayout.LayoutParams(
        ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT
    )
    m_binding.firstQmlFrame.addView(firstQtQuickView, params)
    m_binding.secondQmlFrame.addView(secondQtQuickView, params)
    firstQtQuickView.loadContent(m_firstQmlContent)
    secondQtQuickView.loadContent(m_secondQmlContent)

    m_binding.changeQmlColorButton.setOnClickListener { onClickListener() }
    m_binding.rotateQmlGridButton.setOnClickListener { rotateQmlGrid() }
}

Hinweis: Im Kotlin-Projekt verwenden wir „View Binding“, um auf die UI-Komponenten der Anwendung zuzugreifen:

m_binding = ActivityMainBinding.inflate(layoutInflater)
val view = m_binding.root
setContentView(view)

Innerhalb der Methode ` onCreate() ` werden zuvor deklarierte Variablen mit neuen `QtQuickView `-Instanzen initialisiert. Diese Instanzen nehmen die ` Context ` der Java/Kotlin-Aktivität als Argumente entgegen.

QtQuickView m_firstQuickView = new QtQuickView(this);
QtQuickView m_secondQuickView = new QtQuickView(this);
val firstQtQuickView = QtQuickView(this)
val secondQtQuickView = QtQuickView(this)

Die QtQuickView-Instanzen werden mit den entsprechenden Layout-Parametern zum Android-Layout hinzugefügt.

final ViewGroup.LayoutParams params = new FrameLayout.LayoutParams(
        ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
FrameLayout m_firstQmlFrameLayout = findViewById(R.id.firstQmlFrame);
m_firstQmlFrameLayout.addView(m_firstQuickView, params);
FrameLayout m_secondQmlFrameLayout = findViewById(R.id.secondQmlFrame);
m_secondQmlFrameLayout.addView(m_secondQuickView, params);
val params: ViewGroup.LayoutParams = FrameLayout.LayoutParams(
    ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT
)
m_binding.firstQmlFrame.addView(firstQtQuickView, params)
m_binding.secondQmlFrame.addView(secondQtQuickView, params)

Die Java-Klassen „ Main “ und „ Second “ erben von der Klasse „QtQuickViewContent “. Diese Klassen werden aus dem von uns importierten QML-Projekt generiert.

private final Main m_firstQmlContent = new Main();
private final Second m_secondQmlContent = new Second();
private val m_firstQmlContent: Main = Main()
private val m_secondQmlContent: Second = Second()

Der Inhalt von „ Qt Quick “ wird über die Methode „ QtQuickView.loadContent() “ geladen, die ein „QtQuickViewContent“-Objekt als Argument benötigt.

m_firstQuickView.loadContent(m_firstQmlContent);
m_secondQuickView.loadContent(m_secondQmlContent);
firstQtQuickView.loadContent(m_firstQmlContent)
secondQtQuickView.loadContent(m_secondQmlContent)

Interaktion mit QML-Komponenten

Um mit den eingebetteten QML-Komponenten zu interagieren, implementieren wir die Schnittstelle `QtQmlStatusChangeListener` und überschreiben die Methode ` onStatusChanged `, um den Ladestatus des ` QtQuickViewContent ` abzurufen, der gerade in die ` QtQuickView` geladen wird.

public class MainActivity extends AppCompatActivity implements
QtQmlStatusChangeListener {
    ...
}
class MainActivity : AppCompatActivity(), QtQmlStatusChangeListener {
    ...
}

Die Implementierung von „ onStatusChanged “:

@Override
public void onStatusChanged(QtQmlStatus qtQmlStatus, QtQuickViewContent content) {
    Log.i(TAG, "Status of QtQuickView: " + qtQmlStatus);

    // Show current QML View status in a textview
    m_qmlStatus.setText(getString(R.string.qml_view_status, m_statusNames.get(qtQmlStatus)));
    updateColorDisplay();

    if (content == m_firstQmlContent) {
        // Connect signal listener to "onClicked" signal from main.qml
        // addSignalListener returns int which can be used later to identify the listener
        if (qtQmlStatus == QtQmlStatus.READY && m_switch.isChecked()) {
            m_qmlButtonSignalListenerId = m_firstQmlContent.connectOnClickedListener(
                    (String name, Void v) -> {
                        Log.i(TAG, "QML button clicked");
                        m_androidControlsLayout.setBackgroundColor(Color.parseColor(
                                m_colors.getColor()
                        ));
                    });
        }
    }
}
override fun onStatusChanged(status: QtQmlStatus?, content: QtQuickViewContent?) {
    Log.v(TAG, "Status of QtQuickView: $status")

    // Show current QML View status in a textview
    m_binding.qmlStatusText.text = getString(R.string.qml_view_status, m_statusNames[status])

    updateColorDisplay()

    if (content == m_firstQmlContent) {
        // Connect signal listener to "onClicked" signal from main.qml
        // addSignalListener returns int which can be used later to identify the listener
        if (status == QtQmlStatus.READY && m_binding.disconnectQmlListenerSwitch.isChecked) {
            m_qmlButtonSignalListenerId =
                m_firstQmlContent.connectOnClickedListener { _: String, _: Void? ->
                    Log.i(TAG, "QML button clicked")
                    m_binding.kotlinRelative.setBackgroundColor(
                        Color.parseColor(
                            m_colors.getColor()
                        )
                    )
                }
        }
    }
}

Die „ MainActivity “ wird mit der Methode „ QtQuickViewContent.setStatusChangeListener “ als „ statusChangeListener “ der „ m_mainQmlContent “ und „ m_secondQmlContent “ festgelegt.

m_firstQmlContent.setStatusChangeListener(this);
m_secondQmlContent.setStatusChangeListener(this);
m_firstQmlContent.setStatusChangeListener(this)
m_secondQmlContent.setStatusChangeListener(this)

Die überschriebene Callback-Funktion ` onStatusChanged() ` empfängt das Signal ` StatusChanged() `, das den aktuellen Status – eine `QtQmlStatus` -Enumeration – des Ladevorgangs der aktuellen ` QtQuickViewContent ` in die `QtQuickView` enthält. Wenn bestätigt wird, dass dieser ` QtQmlStatus ` den Wert ` QtQmlStatus.READY` hat, können wir mit der Interaktion mit der QML-Ansicht beginnen.

Abrufen und Festlegen von Eigenschaftswerten von QML-Komponenten

Das Abrufen und Setzen von Eigenschaftswerten von QML-Komponenten erfolgt über die in der Klasse „ Main.java “ beschriebenen Methoden. In diesem Fall verwenden wir die Methoden „ m_mainQmlContent.setColorStringProperty() “ und „ m_mainQmlContent.getColorStringProperty() “. Diese Methoden werden entsprechend den Eigenschaften generiert, die die QML-Komponente enthält.

public void onClickListener() {
    // Set the QML view root object property "colorStringFormat" value to
    // color from Colors.getColor()
    m_firstQmlContent.setColorStringFormat(m_colors.getColor());
    updateColorDisplay();
}
private void updateColorDisplay() {
    String qmlBackgroundColor = m_firstQmlContent.getColorStringFormat();
    // Display the QML View background color code
    m_qmlViewBackgroundText.setText(qmlBackgroundColor);

    // Display the QML View background color in a view
    // if qmlBackGroundColor is not null
    if (qmlBackgroundColor != null) {
        m_colorBox.setBackgroundColor(Color.parseColor(qmlBackgroundColor));
    }
}
private fun onClickListener() {
    // Set the QML view root object property "colorStringFormat" value to
    // color from Colors.getColor()
    m_firstQmlContent.colorStringFormat = m_colors.getColor()
    updateColorDisplay()
}

private fun updateColorDisplay() {
    val qmlBackgroundColor = m_firstQmlContent.colorStringFormat
    // Display the QML View background color code
    m_binding.qmlViewBackgroundText.text = qmlBackgroundColor
    // Display the QML View background color in a view
    // if qmlBackgroundColor is not null
    if (qmlBackgroundColor != null) {
        m_binding.qmlColorBox.setBackgroundColor(Color.parseColor(qmlBackgroundColor))
    }
}

Mit der Methode „ m_mainQmlContent.setColorStringProperty() “ setzen wir den Wert der Eigenschaft „ colorStringFormat “ des „ m_mainQmlContent “ auf einen zufälligen Farbwert, der aus der Klasse „ Colors.java “ (oder „ Colors.kt “) abgerufen wird.

Die Methode ` m_mainQmlContent.getColorStringProperty() ` wird hier verwendet, um die aktuelle Hintergrundfarbe des Root-Objekts von `m_mainQmlContent` abzurufen und sie dem Benutzer auf der Java/Kotlin-Android-Seite der Anwendung anzuzeigen.

m_secondQmlContent Es gibt eine QML-Komponente „ Grid “, die wir von der Java-Seite aus mit der generierten Methode „ m_secondQmlContent.setGridRotation() “ drehen können.

private void rotateQmlGrid() {
    Integer previousGridRotation = m_secondQmlContent.getGridRotation();
    if (previousGridRotation != null) {
        m_secondQmlContent.setGridRotation(previousGridRotation + 45);
    }
}
private fun rotateQmlGrid() {
    val previousGridRotation = m_secondQmlContent.gridRotation
    if (previousGridRotation != null) {
        m_secondQmlContent.gridRotation = previousGridRotation + 45
    }
}

Signal-Listener

Die Klasse „ QtQuickViewContent “ bietet die Methoden „ connectSignalListener() “ und „ disconnectSignalListener() “, mit denen Signal-Listener mit Signalen verbunden bzw. von diesen getrennt werden können, die im Stammobjekt der QML-Komponente deklariert sind. Die Methode „ QtQuickViewContent.connectSignalListener() “ gibt eine eindeutige Signal-Listener-ID zurück, die wir speichern und später zur Identifizierung und zum Trennen des Listeners verwenden.

Hier verbinden wir einen Signal-Listener mit dem Signal „ onClicked() “ der QML-Komponente:

if (qtQmlStatus == QtQmlStatus.READY && m_switch.isChecked()) {
    m_qmlButtonSignalListenerId = m_firstQmlContent.connectOnClickedListener(
            (String name, Void v) -> {
                Log.i(TAG, "QML button clicked");
                m_androidControlsLayout.setBackgroundColor(Color.parseColor(
                        m_colors.getColor()
                ));
            });
}
if (status == QtQmlStatus.READY && m_binding.disconnectQmlListenerSwitch.isChecked) {
    m_qmlButtonSignalListenerId =
        m_firstQmlContent.connectOnClickedListener { _: String, _: Void? ->
            Log.i(TAG, "QML button clicked")
            m_binding.kotlinRelative.setBackgroundColor(
                Color.parseColor(
                    m_colors.getColor()
                )
            )
        }
}

Das Signal „ onClicked() “ wird jedes Mal ausgelöst, wenn die Schaltfläche der QML-Komponente angeklickt wird. Dieser Listener empfängt dieses Signal, woraufhin die Hintergrundfarbe des Layouts, das den Android-Teil der Anwendung enthält, auf einen zufälligen Farbwert gesetzt wird, der aus der Klasse „ Colors.java “ abgerufen wird.

Anschließend wird der Signal-Listener mithilfe der Methode „ QtQuickViewContent.disconnectSignalListener() “ getrennt, indem ihm die eindeutige Signal-Listener-ID übergeben wird.

m_firstQmlContent.disconnectSignalListener(m_qmlButtonSignalListenerId);
m_firstQmlContent.disconnectSignalListener(m_qmlButtonSignalListenerId)

Falls Sie es noch nicht getan haben, sehen Sie sich den Kurs „Qt Academy: Einbetten von Qt Quick 3D -Inhalten in eine Android-App“ an, in dem die in diesem Beispiel genannten Tools und APIs vorgestellt werden.

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.