Câu hỏi hóc búa của tôi nói chung là: thông qua một số hành động bên ngoài GridView, tôi muốn tìm ra tọa độ của một mục đại biểu cụ thể trong GridView chỉ dựa trên một mục mẫu hoặc chỉ mục cụ thể được chọn trước đó.Làm thế nào để có được một thành phần ủy nhiệm tức thời từ một GridView hoặc ListView trong QML
Tôi đã có GridView với một số mục trong mô hình. Các đại biểu của GridView tạo ra một cái nhìn hình thu nhỏ của mỗi mục. Khi được nhấp, nó sẽ hiển thị chế độ xem chi tiết, toàn màn hình của mục. Tôi muốn có một quá trình chuyển đổi tốt đẹp cho thấy hình thu nhỏ mở rộng ra khỏi vị trí của nó trong GridView và khi chế độ xem chi tiết bị loại bỏ, hãy thu hẹp lại vào GridView tại chỗ.
Bí quyết là, chế độ xem chi tiết tự nó là đại biểu của một ListView để bạn có thể trang giữa các lần xem chi tiết một màn hình tại một thời điểm. Điều này có nghĩa là một giải pháp đơn giản là thay đổi kích thước mục đại biểu của GridView hoặc một cái gì đó sẽ không hoạt động. Ngoài ra, vì bạn có thể trang cho bất kỳ mục nào trong ListView, nên việc quay trở lại GridView phải được thực hiện chỉ dựa trên thông tin có sẵn trong mô hình hoặc chỉ mục của mục mẫu (ví dụ: tôi không thể lưu trữ các liên kết của MouseArea được sử dụng để khởi chạy xem chi tiết hoặc một cái gì đó).
Hoạt ảnh mở rộng khá dễ dàng, vì mục đại biểu có MouseArea cho trình xử lý nhấp chuột biết vị trí riêng của nó, để có thể truyền cho hàm bắt đầu hoạt ảnh. Đó là ngược lại tôi không thể tìm ra: từ mô hình mục/chỉ mục trong ListView, làm thế nào để tôi tìm ra các tọa độ của các mục liên quan trong GridView?
Tôi không thể tìm thấy bất kỳ nội dung nào trong tài liệu dường như cho phép bạn có quyền truy cập vào một cá thể đại biểu từ một cá thể mẫu hoặc thậm chí là chỉ mục. GridView có indexAt()
trả về chỉ mục dựa trên tọa độ. Tôi nghĩ tôi có thể làm được điều ngược lại, nhưng nó dường như không tồn tại.
Dưới đây là ví dụ cụ thể hơn. Xin lỗi cho chiều dài; đây là mã ví dụ ngắn nhất tôi có thể nghĩ ra chính xác mô tả sự cố của tôi:
import QtQuick 1.1
Item {
id: window
width: 400
height: 200
state: "summary"
states: [
State { name: "summary"; },
State { name: "details"; }
]
transitions: [
Transition { from: "summary"; to: "details";
SequentialAnimation {
PropertyAction { target: animationRect; property: "visible"; value: true; }
ParallelAnimation {
NumberAnimation { target: animationRect; properties: "x,y"; to: 0; duration: 200; }
NumberAnimation { target: animationRect; property: "width"; to: 400; duration: 200; }
NumberAnimation { target: animationRect; property: "height"; to: 200; duration: 200; }
}
PropertyAction { target: detailsView; property: "visible"; value: true; }
PropertyAction { target: summaryView; property: "visible"; value: false; }
PropertyAction { target: animationRect; property: "visible"; value: false; }
}
},
Transition { from: "details"; to: "summary";
SequentialAnimation {
PropertyAction { target: summaryView; property: "visible"; value: true; }
// How to animate animationRect back down to the correct item?
PropertyAction { target: detailsView; property: "visible"; value: false; }
}
}
]
Rectangle {
id: animationRect
z: 1
color: "gray"
visible: false
function positionOverSummary(summaryRect) {
x = summaryRect.x; y = summaryRect.y;
width = summaryRect.width; height = summaryRect.height;
}
}
ListModel {
id: data
ListElement { summary: "Item 1"; description: "Lorem ipsum..."; }
ListElement { summary: "Item 2"; description: "Blah blah..."; }
ListElement { summary: "Item 3"; description: "Hurf burf..."; }
}
GridView {
id: summaryView
anchors.fill: parent
cellWidth: 100
cellHeight: 100
model: data
delegate: Rectangle {
color: "lightgray"
width: 95; height: 95;
Text { text: summary; }
MouseArea {
anchors.fill: parent
onClicked: {
var delegateRect = mapToItem(window, x, y);
delegateRect.width = width; delegateRect.height = height;
animationRect.positionOverSummary(delegateRect);
detailsView.positionViewAtIndex(index, ListView.Beginning);
window.state = "details";
}
}
}
}
ListView {
id: detailsView
anchors.fill: parent
visible: false
orientation: ListView.Horizontal
snapMode: ListView.SnapOneItem
model: data
delegate: Rectangle {
color: "gray"
width: 400; height: 200;
Column {
Text { text: summary; }
Text { text: description; }
}
MouseArea {
anchors.fill: parent
onClicked: {
// How do I get the coordinates to where animationRect should return?
summaryView.positionViewAtIndex(index, GridView.Visible);
window.state = "summary";
}
}
}
}
}
Bất kỳ ý tưởng nào? Có thể tôi đang đi về điều này một cách sai lầm. Nếu những gì tôi đang cố gắng làm đặc biệt là không thể, có cách nào khác tôi nên kiến trúc này? Cảm ơn!
Edit: Một số ý tưởng tôi đã có (không ai trong số đó tôi tin là khả thi):
Giữ một danh sách tất cả các mặt hàng đại biểu được tạo ra, sử dụng
Component.onCompleted
vàComponent.onDestruction
. Để hữu ích, nó phải là một bản đồ của mục mẫu hoặc chỉ mục => mục đại biểu. Rắc rối là, basic types docs (đặc biệt là variant) dường như chỉ ra rằng loại bản đồ này không thể tạo trong QML thuần túy. Vì vậy, có vẻ như điều này có nghĩa là tạo bản đồ này dưới dạng lớp C++ và sử dụng bản đồ đó trong QML vớionCompleted
/onDestruction
trong thành phần đại biểu để luôn cập nhật. Có vẻ hơi nguy hiểm và nặng tay cho một thứ đơn giản.This mailing list post dường như cho biết thuộc tính
contentItem
của Flickable có thể được sử dụng để liệt kê các mục đại biểu. Sau đó, tôi tìm thấy this post gọi đó là thực tiễn không tốt. Tôi vẫn đang xem xét nó, nhưng tôi hoài nghi đây sẽ là một giải pháp hợp pháp. Có vẻ như quá khó để làm việc đáng tin cậy.
Đó là tất cả những gì tôi có cho đến nay.
Chỉ cần tự hỏi nếu bạn đã gặp phải bất kỳ giải pháp tốt hơn hoặc triển khai tốt hơn để truy cập các đại biểu của một mô hình từ một tệp QML khác hoặc nếu bạn vẫn đang sử dụng phương pháp trên? – stackunderflow
Không, theo như tôi có thể nói đây là cách "chính thức" để làm điều đó. – chazomaticus
Có vẻ như một trong những vấn đề mà "ma thuật đen" cố gắng khắc phục là danh sách trẻ em bị ô nhiễm bởi anh chị em của GridView. Tôi nghĩ rằng bạn có thể bọc GridView của bạn trong một hình chữ nhật, đơn giản hóa danh sách con của bạn. Sau đó, chỉ đơn giản là summaryView.contentItem.children [i] dường như hoạt động tốt. – SketchBookGames