如何在 Qt/QML 中实现主明细视图(第 2 部分)

How to implement Master Details View in Qt/QML (part 2)

我之前问过如何在 Qt/QML 中实现主详细信息视图:

继续努力,我得出了以下 QML 布局模型:

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
        }
    }
}

主视图本质上是一个包含多个项目的 ListView(每个项目代表一个可选择的元素,这将触发细节视图的更新,当前由绿色矩形表示(见下面的截图)

目前我仍然有以下几点问题:

编辑: 修改代码,在ScrollView中添加ListView。在这种情况下,ScrollView 的高度与屏幕高度相同,这也是我想要的(在顶部减去 50 的偏移量,见下图)。我认为 ListView 的行为符合预期,并没有比它的项目占用更多 space。

现在需要实现的是改变SrollView的Background颜色,使其与ListView的颜色匹配。在那种情况下,它会看起来好像 ListView 占据了整个 space。

  1. 为了让你的ListView占满所有的高度,你可以简单的设置为填满布局的高度。但是,请确保 Layout(及其在您的情况下的父级)也具有正确的大小。对于 QML 中的 Item,大小默认为 (0,0)。

    ListView {
        id: listview
        //...
        Layout.fillHeight: true
        //...
    }
    
  2. 关于"flickering",你可以试试增加ListView cacheBuffer 属性,它对应内容的高度,以像素为单位,是预加载的。但是,如果这是 really flickering,您可能无能为力。

当屏幕刷新率错误的刷新显示时会出现闪烁,通常通过使用多个缓冲区 and/or 同步来解决。 QtQuick 隐藏了所有这些复杂性并使用 OpenGL 进行渲染,但我(还)没有看到 Android 最近的 Qt 版本有任何闪烁。

  1. 您可以通过编辑 Android 清单文件来删除状态栏,如 in this other post 所述,或者更糟的情况是通过 JNI。

要隐藏状态栏,最简单的方法就是指定一个主题并应用到manifest文件中。其他解决方案需要修改 activity 等。

yourApp/android/res/values 中创建具有以下内容的 theme.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="AppTheme" parent="@android:style/Theme.DeviceDefault.Light.NoActionBar">
    </style>
</resources>

然后在清单中,在添加屏幕方向的同一行中,添加主题:

android:theme="@style/AppTheme"

并且在您的主要 window 中使用 Window.FullScreen 可见性而不是最大化。

对于布局,看来您可以做的更少。 Layout 没有任何问题,只是 IMO 它更适合标准的可扩展 "micro" GUI 元素,如按钮等,而不是自定义宏元素。这是一个简洁但实用的示例:

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
    }
  }
}

结果:

虽然垂直偏移的原因并不完全清楚,但如果您想在顶部放置空闲 space,只需不要用根 Row 填充整个父级元素,而是相应地调整它的大小。

我有点懵,怎么会,你认为ScrollView是需要的。

我从你的示例中删除了它,向 ListView 添加了剪辑,我就完成了。

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
            }
        }
    }
}

有几件事你可能会误解:

  1. ListView 没有提供任何背景。如果你想要这样,你需要在它后面画一些东西,例如一个 Rectangle
  2. ListView 本身不提供 ScrollBar。您需要像这样添加它们:

    ScrollBar.vertical: ScrollBar { }

  3. ScrollBar 没有 native 风格。句柄默认会消失。您可以在这里找到多个关于如何设置 ScrollBar.

  4. 样式的问题
  5. 如果不剪裁 ListView,您会看到一些元素突出 ListView 并突然消失。如果你没有任何内容可以涵盖这一点,你应该设置 clip: true