「QML(Qt)のListViewにスクロールバーを追加してみる」で、作ったものを拡張した感じです。
/// ポイント ///
・キーボード操作で一番上や下とかページ送り
・バーが表示されるエリアをクリックすると一気に移動する。
キーボードなしでも一気に一番上や下にいけるように。
・currentItemIndexを変更するとバーが表示される。
元の作りだとマウスのスクロール機能使ってる時か慣性スクロールしてる時しかでない。
GooleCodeにコード置いてあります。
「ListViewBaseエレメント」のコード
/// ポイント ///
・キーボード操作で一番上や下とかページ送り
・バーが表示されるエリアをクリックすると一気に移動する。
キーボードなしでも一気に一番上や下にいけるように。
・currentItemIndexを変更するとバーが表示される。
元の作りだとマウスのスクロール機能使ってる時か慣性スクロールしてる時しかでない。
GooleCodeにコード置いてあります。
「ListViewBaseエレメント」のコード
import QtQuick 1.0
ListView {
id: _root
x: 0
y: 0
width: parent.width
height: parent.height
clip: true
property bool loading: (count < 1)
property bool alwaysViewing: false // スクロールバーを常に表示するか
property alias scrollBarVisible: _scrollBarBase.visible // 表示するか
property alias scrollBarBaseColor: _scrollBarBase.color // ベース色
property alias scrollBarColor: _scrollBar.color // 色
property real scrollBarOpacity: 0.8 // 透過率
property real density: 1.0
Rectangle {
id: _scrollBarBase
width: 25 * _root.density
anchors.top: parent.top
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.margins: 2
color: "#22ffffff"
radius: 2 * _root.density
opacity: 0.01
visible: (visibleArea.heightRatio < 1.0) | alwaysViewing
Rectangle {
id: _scrollBar
anchors.horizontalCenter: parent.horizontalCenter
y: parent.height * visibleArea.yPosition
width: parent.width * 0.1
radius: width * 0.5
height: parent.height * visibleArea.heightRatio
color: "#ffffff"
}
MouseArea{
anchors.fill: parent
onClicked: {
var per = mouse.y / height;
var index = 0;
if(per < 0.1){
// 一番上へ
index = 0;
}else if(per > 0.9){
// 一番下へ
index = count - 1;
}else{
// 中間
var h = height * 0.1;
index = Math.floor((count) * ((mouse.y - h) / (height - 2 * h)));
}
positionViewAt(index, ListView.Beginning);
}
}
}
// 選択を変更した時にスクロールバーを表示する。
onCurrentIndexChanged: {
if(!movingVertically && !alwaysViewing){
if(state !== "Visible"){
state = "Visible";
_scrollBarVisibleTimer.start();
}else if(state === "Visible"){
_scrollBarVisibleTimer.restart();
}
}
}
// 選択を変更したときのスクロールバーを消すためのタイマー
Timer{
id: _scrollBarVisibleTimer
interval: 500
repeat: false
triggeredOnStart: false
onTriggered:{
state = "";
}
}
// キー操作
Keys.onPressed: {
switch(event.key){
case Qt.Key_Home:
// 一番上へ
positionViewAtBeginEnd(true);
break;
case Qt.Key_End:
// 一番下へ
positionViewAtBeginEnd(false);
break;
case Qt.Key_PageUp:
// 上へ飛ぶ
positionViewAtPageUpDown(false);
break;
case Qt.Key_PageDown:
// 下へ飛ぶ
positionViewAtPageUpDown(true);
break;
}
}
/////////////////////////////////////////////
// 表示位置をコントロールする
// 表示位置を最初と最後
function positionViewAtBeginEnd(is_begin){
if(is_begin){
positionViewAtIndex(0, ListView.Beginning);
currentIndex = 0;
}else{
positionViewAtIndex(count - 1, ListView.Beginning);
currentIndex = count - 1;
}
}
// 表示位置をページ移動
function positionViewAtPageUpDown(is_down){
// ヘッダとフッタの高さを考慮する
var top = indexAt(1, contentY);
var bottom = indexAt(1, contentY + height);
if(top < 0){
top = 0;
}
if(bottom <= top){
bottom = count - 1;
}
if(is_down){
// 下へ
positionViewAt(currentIndex + (bottom - top), ListView.End);
}else{
// 上へ
positionViewAt(currentIndex - (bottom - top), ListView.Beginning);
}
}
// 表示位置を任意の位置へ移動
function positionViewAt(index, mode){
if(index < 0){
index = 0;
}else if(index >= count){
index = count - 1;
}
positionViewAtIndex(index, mode);
currentIndex = index;
}
// ステータス管理
states: [
State {
name: "Visible"
when: movingVertically | alwaysViewing
PropertyChanges {
target: _scrollBarBase
opacity: scrollBarOpacity
}
}
]
//アニメーション
transitions:
Transition {
PropertyAnimation {
easing.type: Easing.OutCubic
target: _scrollBarBase
properties: "opacity"
duration: 300
}
}
}

