#はじめに
ListView の並びは変えずにアイテムを一番上に表示したいな~ ということでやってみました。
##やり方
ListView
のScrollViewPos
プロパティとGetItemRect
メソッドを使います。
var
itemRect:TRectF;
begin
itemRect := ListView1.GetItemRect(対象アイテムのインデックス);
ListView1.ScrollViewPos := ListView1.ScrollViewPos + itemRect.Top;
end;
GetItemRect
メソッドは、ListViewの現在のスクロール位置からの相対位置を返すので、対象アイテムがリストの上側に隠れている場合は負の値になります。
その為、現在のスクロール位置にアイテム位置を足し算してあげればOKです。
更に、FloatAnimation
を組み合わせれば、スクロールする様子をユーザーに見せることもできます!
なお、ScrollViewPos
の最大値を超えてはスクロールしない為、最後の方のアイテムはリストの先頭には表示できません。
その他、ScrollTo
メソッドもあります。こちらは対象のアイテムが画面内に無い場合に、そのアイテムが表示されるまでスクロールしてくれます。(ここでは詳しく扱いません)
##サンプル
例として、リストアイテムのヘッダーを頭出しするプログラムを作ってみました。
###手順1 コンポーネント配置
- フォームに
TComboBox
、TListView
、TProtoTypeBideSource
を配置します。 -
ComboBox1
はAlign:Top
、ListView1
はAlign:Client
に設定します。 -
ProtoTypeBindSource1
はColorsNames
フィールドを追加します。その際、値のシャッフルと繰り返しはチェックを外します。 -
TFloatAnimation
をListView1
の子になるよう配置します。PropertyName
フィールドに、ScrollViewPos
を設定します。
###手順2 バインディング
- デザイナ上で
ListView1
を右クリック→ビジュアルにバインドを選択します(LiveBindingデザイナが表示されます)。 - LiveBindingデザイナ上で、
ProtoTypeBindSource1
のColorsName1
からListView1
のItem.Text
へドラッグします(矢印が引かれます)。同様に、ColorsName1
からItemHeader.Text
に矢印を引きます。 - オブジェクトインスペクタにて、
LinkFillControlToField1
のFillHeaderCustomFormat
にSubString(%s, 0, 1)
を設定します(選択肢に出てきます)。
また、UseEvalShortCut
をFalse
にします。
###手順3 イベント処理記述
オブジェクトインスペクタにて、LinkFillControlToField1
のイベントOnFilledList
をダブルクリックし、以下のようにコードを記述します。
内容は、ComboBox1
にListView1
内のヘッダーアイテムを登録しています。
procedure TForm1.LinkFillControlToField1FilledList(Sender: TObject);
var
i:integer;
item:TListViewItem;
begin
ComboBox1.Clear;
for I := 0 to ListView1.ItemCount -1 do
begin
item := ListView1.Items[i];
if item.Purpose = TListItemPurpose.Header then
ComboBox1.Items.AddObject(item.Text, item);
end;
end;
次に、ComboBox1
のOnChange
イベントに以下を記述します。
リストのスクロール位置の取得とアニメーションの設定・開始を行っています。
procedure TForm1.ComboBox1Change(Sender: TObject);
var
item:TListViewItem;
itemRect:TRectF;
begin
if ComboBox1.ItemIndex > -1 then
begin
item := ComboBox1.Items.Objects[ComboBox1.ItemIndex] as TListViewItem;
itemRect := ListView1.GetItemRect(item.Index);
FloatAnimation1.StartValue := ListView1.ScrollViewPos;
FloatAnimation1.StopValue := ListView1.ScrollViewPos+itemRect.Top;
FloatAnimation1.Start;
end;
end;
##完成
コンパイルして、動作確認してみましょう!
##応用
こんな感じのインターフェースも簡単に作れます!(操作パネルによってアイテムが隠れないようにスクロールする処理)
###やり方
####フォームデザイン
各コントロールを以下のように設定します(デフォルト値から変えた部分のみ)。
ListView1
Align:Client
FloatAnimation_ListViewScroll
PropertyName:ScrollViewPos
StartFromCurrent:True
Panel1
Align:Bottom
Height:好みの大きさ
FloatAnimation_PanelSlideIn
PropertyName:Height
StartFromCurrent:True
FloatAnimation_PanelSlideOut
Delay:3.0
PropertyName:Height
StartFromCurrent:True
(Button1、Button2は飾りなので適当に)
####ソースコード
Form1 のOnCreate
イベントと、ListView1 の OnItemClick
イベントを作成します。
procedure TForm1.FormCreate(Sender: TObject);
begin
OriginPanelHeight := Panel1.Height;
Panel1.Height := 0;
end;
procedure TForm1.ListView1ItemClick(const Sender: TObject;
const AItem: TListViewItem);
var
itemRect:TRectF;
overlapped:Single;
begin
itemRect := ListView1.GetItemRect(AItem.Index);
overlapped := itemRect.Bottom - (ListView1.Height - OriginPanelHeight);
if overlapped > 0 then
begin
FloatAnimation_ListViewScroll.StopValue := ListView1.ScrollViewPos + overlapped;
FloatAnimation_ListViewScroll.Start;
end;
FloatAnimation_PanelSlideIn.StopValue := OriginPanelHeight;
FloatAnimation_PanelSlideIn.Start;
FloatAnimation_PanelSlideOut.Start;
end;
以上です。
#おわりに
Delphi (*´ω`*) ハヤル!