Julien
Julien

Reputation: 1192

How to mix Qt and native iOS user interface elements in a single App?

I'm using Qt 5.2 for iOS.

I'd like to mix QtQuick 1.1 or QWidgets with native iOS user interface elements in a single app.

Embedding a qml view into a UIView, having to switch to another window, embedding a UIView into a qml component, any help in that direction is welcome !

Upvotes: 4

Views: 3183

Answers (2)

Leo
Leo

Reputation: 1025

Coming a bit late, it is possible to show a native UIView on top of the Qt universe. The technique for embedding an UIView is letting the UIView "float" over an in-hierarchy QWidget and update the UIView's geometry whenever the geometry of the in-hierarchy widgets changes. The limitation for this: you can't simply place such a widget inside a QTabWidget (then you need additional code for hiding/showing the UIView). Also QMainWindows being raised over the QMainWindow containing the UIView won't work.

class View : public QWidget
  ...
  private:
    UITextView* m_TextView;
    bool m_scheduled;

implementation

View::View(QWidget* parent):QWidget(parent),m_Scheduled(false)
{
    m_TextView=[[UITextView alloc] init];
    QWidget* w= window();
    UIView *parentView = reinterpret_cast<UIView *>(w->winId());
    [parentView addSubview:m_TextView];
}
View::~View()
{
    [m_TextView removeFromSuperview];
    m_TextView=nil;
}
bool View::event(QEvent* e)
{
    if (e->type()==QEvent::Move || e->type()==QEvent::Resize) {
      if (!m_scheduled) {
        m_scheduled=true;
        QTimer::singleShot( 0, this, SLOT( updateGeo() ) );
      }
    }
    return QWidget::event(e);
}
static inline QRect globalRect(QWidget* widget)
{
    return QRect((widget)->mapToGlobal(QPoint(0,0)), (widget)->size());
}
void View::updateGeo()
{
    m_scheduled=false;
    QRect rg=globalRect(this);
    QRect rw=globalRect(window());
    CGRect cg=CGRectMake(rg.x(), rg.y()-rw.y(), rg.width(), rg.height());
    [m_TextView setFrame:cg];
}

The complete sample project can be found here. Another approach is using a QML viewer and qmlRegisterType to register a QQuickItem descendant.

qmlRegisterType<MyTextView>("MyTextView", 1, 0, "MyTextView");

header

class MyTextView : public QQuickItem
   ...
   private:UITextView* m_view;

in the implementation the geometryChanged method is overriden to compute the new rectangle in UIView coordinates

static inline CGRect toCGRect(const QRectF &rect)
{
  return CGRectMake(rect.x(), rect.y(), rect.width(), rect.height());
}
MyTextView::MyTextView(QQuickItem *parent /*= 0*/)
    : QQuickItem(parent)
    , m_view(0)
{
    connect(this, SIGNAL(windowChanged(QQuickWindow*)), this, SLOT(onWindowChanged(QQuickWindow*)));
    connect(this, SIGNAL(visibleChanged()), this, SLOT(onVisibleChanged()));
}

MyTextView::~MyTextView()
{
    [m_view release];
}
void MyTextView::onWindowChanged(QQuickWindow* window)
{
    if(!m_view) {
        m_view = [[UITextView alloc] init];
    }
    if (window != 0) {
        UIView *parentView = reinterpret_cast<UIView *>(window->winId());
        [parentView addSubview:m_view];
    } else {
        [m_view removeFromSuperView];
    }
}
void MyTextView::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
{
    QQuickItem::geometryChanged(newGeometry, oldGeometry);
    CGRect rc = toCGRect(mapRectToScene(newGeometry).toRect());
    rc.size.width -= 2;
    rc.size.height -= 2;
    [m_view setFrame:rc];
}
void MyTextView::onVisibleChanged()
{
    [m_view setHidden:isVisible()];
}

and in the qml file

...
import MyTextView 1.0

Window {
    visible: true

    Column {
        anchors.fill: parent
        anchors.margins: 5
        spacing: 5

        Rectangle {
            anchors.left: parent.left
            anchors.right: parent.right
            height: 100
            border.width: 1
            border.color: "red"
            color: "#cccccc"

            MyTextView {
                anchors.fill: parent
                anchors.margins: 1
            }
        }
    }
}

The complete sample project can be found here.

Upvotes: 2

Maxim Korobov
Maxim Korobov

Reputation: 2572

It's impossible right now and in near future.

Qt doesn't support native UI for iOS and Android right now.Qt widgets are drawing in opengl context. Qt app is like full-screen game for iOS.

More info.

Upvotes: 0

Related Questions