Handling Screen Rotation

567 views
Skip to first unread message

Stephen Lacey

unread,
Jun 9, 2011, 9:02:35 AM6/9/11
to android-qt
Hi All,

I'm working on my first port to Qt for Android.

I was wondering what is the best strategy for handling screen rotation
and different sized screens.

I have a tiny SE X10 mini pro and a big sylvania tablet. If I size the
screens for the X10 then the screens look too small on the tablet and
in reverse if I size for the tablet then the visible form is only the
top corner on the X10.

Is there a way to determine scale and dynamically resize the app?

Another thing I've noticed is that upon rotation some items can become
pushed off the screen ... what's the best way to handle this kind of
thing? Do I need 2 layouts for each form, one portrait and 1
landscape? Any idea how I'd even implement that?

Finally, and kinda unrelated. There seems to be an issue with the app
screen becoming black upon rotation in some cases. This seem to happen
randomly on some forms and also if you close the app in one rotation
and open in in another.

Any help would be appreciated? A bit of sample code would help a lot.

Thanks,

Stephen

Willy Gardiol

unread,
Jun 9, 2011, 10:12:50 AM6/9/11
to andro...@googlegroups.com

I can tell you what is my experience on the issue, even if my
experience is on Symbian and i just started to port to Android.

Its not THAT simple... it takes some effort to reach a good result, but
it can be done and it leads to flexible results.

Ok, this is my approach:

- design your layouts for the optimal screen size for your app... (mine
is 360x640 given the Symbian origin).
- re-design again your layouts for the rotated format (640x360 in my
case)

this requires to create TWO different layouts and intercept the
resizeEvent in your top-level window, then identify your format (if
width > height then...) and apply the proper layout.
In my experience, its way much better to redesign your layout each
time than try to store old layouts around, because this latter option
basically requires you to duplicate your widgets, since as far as i know
there is no way to put a widget into two layouts at the same time. Its
not so slow as it might seems.

This takes care of the orientation.

To cater for more screen sizes, its more complicated. One way is to set
"setSizePolicy" to all your widgets to shrink or expand, but again this
is a major PIA due to weird stuff happening on the screen.

My only solution has been to create my own inputwidgets (labels,
buttons, lists, mostly) given also that almost all input widgets on Qt
are broken on mobiles, and make them "scalable" by dynamically resizing
the font and the default height/width based on the actual device screen
size (read the desktop size for this).

In this way my app can be used on a display as small as 240x300 (Ideos)
or as big as i like (i just stop scaling at a given factor to avoid huge
buttons and the like).

This of course means yout app does not really make use of extra space,
if any, just resizes properly. If you want to make use of different
screen sizes, then you should think about using more layouts and switch
not only based on screen orientation but on screen size too.

Some thing like:
QLayout CreateNormalVerticalLayout();
QLayout CreateNormalHorizontalLayout();
QLayout CreateBigVerticalLayout();
QLayuout CreateBigHorizontalLayout();

and such, then ypu select one or the other in your top-level window
resizeEvent....

For my solution, go to hg.trackaway.org and check both
controls/rotatingdialog.h
controls/rotatingwidget.h

basically i have top-level widgets (rRotatingDialog) that intercepts
resizeEvent and force a re-layouting of all childrens...
and specific widgets that need to change layout are derived from
RotatingWidget, which have virtual CreateVertical and CreateHorizontal
methods.

--
Willy Gardiol
wi...@gardiol.org
www.gardiol.org
www.trackaway.org -> Track YOUR way the way you want!

Stephen Lacey

unread,
Jun 9, 2011, 9:39:03 AM6/9/11
to android-qt
Thanks for the superb and thorough answer.

I'll check that out!
> Ā www.trackaway.org-> Track YOUR way the way you want!

Stephen Lacey

unread,
Jun 14, 2011, 4:25:46 PM6/14/11
to andro...@googlegroups.com
OK, so here's what I worked out...thought I'd share.

Probably just exposes my ignorance of how this should work, but it works quite well in practice.

I have encoded the coordinates of the form controls in portrait and landscape mode into the controls "Stylesheet". When the form resizes then I check if it's portrait or landscape mode and then move the controls accordingly. Scaling is supported. Works well...app designed for my tiny Sony Ericsson X10 mini also look ok on 7" tablet.

Here's the resize event:

void TrackeySummary::resizeEvent(QResizeEvent *e)
{
  // call the base method 
    QDialog::resizeEvent(e);

    /*
  QMainWindow::resizeEvent(e); */
    QString sss = "The app resized...";

    int iOrientationIndex;

    if (this->height() > this->width()) // portrait
    {
        iOrientationIndex=0;
    }
    else // landscape
    {
        iOrientationIndex=1;
    }

    // Now we have the base value...what about scale?
    // base form width = 300 x 240
    // or
    // 240 x300
    double dScaleX = 1;
    double dScaleY = 1;

    switch (iOrientationIndex)
    {
        case 0: // portrait 240 x 300
            dScaleX = this->width() / 240;
            dScaleY = this->height() / 300;
            break;
        case 1: // landscape 300 x 240
            dScaleX = this->width() / 300;
            dScaleY = this->height() / 240;
            break;
        default:
            break;
    }

    // Make sure our scale is reasonable
    if (dScaleX< 1) dScaleX=1;
    if (dScaleY< 1) dScaleY=1;

    QList<QWidget *> widgets = findChildren<QWidget *>();

    QList<QWidget *>::iterator i;
    for (i=widgets.begin();i!=widgets.end();++i)
    {
        QWidget *widget = qobject_cast<QWidget *>(*i);

        // Widget x,y,width,height is encoded into the stylesheet
        // with the portrait coordinates first
        // and landscape second,
        // separated by a bar "|"
        // e.g. 60,130,41,21|0,120,41,21
        // enter "hide" to hide the control on rotation
        QStringList Orientations = widget->styleSheet().split("|");
        if (Orientations.count()==2) // check we got a portrait and landscape set of settings
        {

            widget->setVisible(true); // always make the widget visible.
            QString orientation = Orientations[iOrientationIndex]; // Get the coordinates for our current orientation

            if (orientation ==  "hide") // hide the widget
            {
                widget->setVisible(false);
            }
            else
            {
                QStringList Coordinates = orientation.split(",");   // read the x,y,width,height
                                                                    // 4 numerals separated bya ","

                // we expect 4 coords, if we don't get those then skip out
                if (Coordinates.count() == 4)
                {

                    /* Debug message */
                    QString sMsg = "Got 4 coords from " + orientation;

                    /* Get the x,y,width and height as strings and integers */
                    QString sX = Coordinates[0];
                    int iX = sX.toInt();
                    QString sY = Coordinates[1];
                    int iY = sY.toInt();
                    QString sWidth = Coordinates[2];
                    int iWidth = sWidth.toInt();
                    QString sHeight = Coordinates[3];
                    int iHeight = sHeight.toInt();

                    /* scale the control */
                    iX = round(iX * dScaleX);
                    iWidth = round(iWidth * dScaleX);
                    iY = round(iY * dScaleY);
                    iHeight = round(iHeight * dScaleY);

                    /* move and resize the control */
                    widget->move(iX, iY);
                    widget->resize(iWidth, iHeight);
                }
            }
        }
    }

    // emit the signal, not sure what this does :)
    emit signalResize(e);

}

Afriza N. Arief

unread,
Jun 18, 2011, 11:40:34 AM6/18/11
to andro...@googlegroups.com
what a colorful code snippet!

may i know how you did that?

Mike Shatohin

unread,
Jun 18, 2011, 3:30:42 PM6/18/11
to andro...@googlegroups.com
I think this easy with Gmail + QtCreator + Ctrl+C + Ctrl+V dude!

Like this:

#   pragma omp parallel
    {
#       pragma omp critical
        {
            printf("Thread #%i of %i\n", omp_get_thread_num(), omp_get_num_threads());
        }
    }

    double resultWithoutOpenMP = evalIntegralWithoutOpenMP();
    double resultOpenMP = evalIntegralOpenMP();

    printf("Result without OpenMP: %lf\n", resultWithoutOpenMP);
    printf("Result with OpenMP: %lf\n", resultOpenMP);

2011/6/18 Afriza N. Arief <afriza.na@gmail.com>

Stephen Lacey

unread,
Jun 18, 2011, 4:04:19 PM6/18/11
to andro...@googlegroups.com
There is a link on the groups page, up the the top right that says "View this group in theĀ new Google Groups".

That brings you to a new way of viewing the group and a rich text editor, the rest was achieved through cut and paste.

Stephen
Reply all
Reply to author
Forward
0 new messages