问题
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
ListViewprovides no background. If you want such, you need to draw something behind it, e.g. aRectangle The
ListViewdoes not provideScrollBars by itself. You need to add them like this:ScrollBar.vertical: ScrollBar { }The
ScrollBarhas 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
ListViewyou will see some elements protruding theListViewand 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 Rowelement 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
Itemin QML.ListView { id: listview //... Layout.fillHeight: true //... }Regarding the "flickering", you can try increasing the ListView
cacheBufferproperty, 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