问题
I previously asked how to implement a Master Details View in Qt/QML here: How to implement a master-details view Qt/QML on an Android tablet?.
Having continued working on this, I came out with the following mockup QML layout:
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.0
import QtQuick.Controls 1.4
Item {
y: 50
Layout.fillHeight: true
width: appWindow.width
RowLayout {
id: mainLayout
anchors.fill: parent
ListModel {
id: navigation
ListElement {
item: "Item 1"
}
ListElement {
item: "Item 2"
}
ListElement {
item: "Item 3"
}
ListElement {
item: "Item 4"
}
ListElement {
item: "Item 5"
}
ListElement {
item: "Item 6"
}
ListElement {
item: "Item 7"
}
ListElement {
item: "Item 8"
}
ListElement {
item: "Item 9"
}
ListElement {
item: "Item 10"
}
ListElement {
item: "Item 11"
}
}
ScrollView{
Layout.fillHeight: true
verticalScrollBarPolicy: Qt.ScrollBarAlwaysOn
horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff
ListView {
id: listview
Layout.fillHeight: true
Layout.preferredWidth: 300
contentWidth: 300
model: navigation
delegate: Rectangle {
id: wrapper
width: 300
height: 50
Text {
id: itemInfo
text: item
color: "red"
}
}
}
}
Rectangle {
x: 300
y: 50
Layout.preferredWidth: appWindow.width - listview.width-4
height: appWindow.height - 50
color: "green"
border.width: 1
}
}
}
The master view is essentially a ListView with a number of items (each item represents a selectable element, which will trigger an update of the details view, which is currently represented by the green rectangle (see attached screenshot below)
At the moment I am still having a couple of issues with the following points:
How should I modify the Layout so that the ListView covers the entire screen height?
When I "scroll" through the ListView, I have noticed a lot of screen flickering? How can I minimize this?
How can I prevent the entire upper status bar (where device system information such as battery charge is shown) from being displayed?
Edit: Modified the code by adding the ListView in a ScrollView. In this case, the ScrollView's height is the same as the screen height, which is also what I wanted (minus a 50 offset at the top, see Figure below). I think that the ListView is behaving as expected and not occupying more space that its items.
What needs to be achieved now is to change the Background color of the SrollView so that it matches the ListView color. In that case it will appear as if the ListView is occupying the entire space.
回答1:
I am a bit clueless, how it comes, that you consider the ScrollView
to be needed.
I removed it from your example, added clipping to the ListView
and I was done.
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.0
ApplicationWindow
{
id: appWindow
width: 1024
height: 800
visible: true
Item {
y: 50
Layout.fillHeight: true
width: appWindow.width
RowLayout {
id: mainLayout
anchors.fill: parent
ListModel {
id: navigation
ListElement { item: "Item 1" }
Component.onCompleted: {
for (var i = 2; i < 50; i++) append({ item: 'Item' + i })
}
}
ListView {
id: listview
Layout.fillHeight: true
Layout.preferredWidth: 300
contentWidth: 300
model: navigation
clip: true //<--- Add this, so there won't be no elements outside the ListView-area
delegate: Rectangle {
id: wrapper
width: 300
height: 50
Text {
id: itemInfo
text: item
color: "red"
}
}
}
Rectangle {
x: 300
y: 50
Layout.preferredWidth: appWindow.width - listview.width-4
height: appWindow.height - 50
color: "green"
border.width: 1
}
}
}
}
There are a few things you might misunderstand:
- The
ListView
provides no background. If you want such, you need to draw something behind it, e.g. aRectangle
The
ListView
does not provideScrollBar
s by itself. You need to add them like this:ScrollBar.vertical: ScrollBar { }
The
ScrollBar
has no native style. And the handle will disapear by default. You can find more than one question here, on how to style aScrollBar
.- If you don't clip the
ListView
you will see some elements protruding theListView
and suddenly disappear. If you have nothing that covers this anyway, you should setclip: true
回答2:
In order to hide the status bar, the easiest thing to do is to specify a theme and apply it in the manifest file. Other solutions require modifying the activity and such.
In yourApp/android/res/values
create a theme.xml
with the following content:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppTheme" parent="@android:style/Theme.DeviceDefault.Light.NoActionBar">
</style>
</resources>
Then in the manifest, on the same line where you added the screen orientation, add the theme:
android:theme="@style/AppTheme"
And in your main window use Window.FullScreen
visibility instead of maximized.
For the layouting, it appears you could do with less. There is nothing wrong with Layout
, just IMO it is more suited to standard scalable "micro" GUI elements like buttons and such rather than custom macro elements. Here is a condensed but functional example:
Row {
anchors.fill: parent
ListView {
id: lv
width: 200
height: parent.height
model: 30
delegate: Rectangle {
width: 200
height: 50
color: index == lv.currentIndex ? "lightgray" : "white"
Text {
text: "item " + index
color: "red"
anchors.centerIn: parent
}
MouseArea {
anchors.fill: parent
onClicked: lv.currentIndex = index
}
}
Rectangle {
anchors.right: parent.right
width: 5
height: parent.height * parent.visibleArea.heightRatio
color: "grey"
y: parent.height * parent.visibleArea.yPosition
}
}
Rectangle {
width: parent.width - lv.width
height: parent.height
color: "green"
Text {
anchors.centerIn: parent
text: "selected item n" + lv.currentIndex
color: "white"
font.pointSize: 15
}
}
}
The result:
Although it is not exactly clear the reason you offset things vertically, if you want to have the free space at the top, simply don't fill the entire parent with the root Row
element but rather size it accordingly.
回答3:
For your ListView to take all the height, you can simply set it to fill the height of the layout. However make sure the Layout (and its parent in your case) have the right size too. Size defaults to (0,0) for
Item
in QML.ListView { id: listview //... Layout.fillHeight: true //... }
Regarding the "flickering", you can try increasing the ListView
cacheBuffer
property, which corresponds to the content height, in pixels, which is preloaded. However if this is really flickering, there's probably little you can do.
Flickering appears when display is refreshed with the wrong timings regarding screen refresh rate, and typically solved by using multiple buffers and/or synchronization. QtQuick hides all this complexity and uses OpenGL for rendering, but I didn't saw (yet) any flickering on Android with recent Qt versions.
- You can remove the status bar by editing the Android manifest file as explained in this other post, or worse case, through JNI.
来源:https://stackoverflow.com/questions/42566250/how-to-implement-master-details-view-in-qt-qml-part-2