[UE4]ListViewのスクロールバーのデザインを変更する

# はじめに

UMGでリスト表示をする際に[ListViewを使うとScrollBoxよりも負荷が軽いらしいという記事](https://historia.co.jp/archives/10389/)を見つけたので使ってみました。
ところがListViewではスクロールバーのデザインを変更することができないため、Blueprintに公開して変更できるようにしました。

今回はエンジンの改造は行わず、C++でListViewを継承する形で実現しています。

# 環境

- Windows 10
- Unreal Engine 4.27

# できたもの

スクロールバーの形と色を変更、バー上下の線を非表示にしました。

**Before**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/d8465a15-1c37-7202-9f68-0b36dfebd15b.png)

**After**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/4aac66a1-ccee-e09d-7e0b-a35b07c1fa01.png)

# 手順
## C++でのクラス作成

```SListViewCustom.h
#pragma once

#include "CoreMinimal.h"
#include "Widgets/Views/SListView.h"

/**
 * スクロールバーのスタイル情報を持つクラス
 */
template <typename ItemType>
class TEST_API SListViewCustom : public SListView<ItemType>
{
public:
	SListViewCustom(ETableViewMode::Type InListMode = ETableViewMode::List)
		: SListView(InListMode)
	{
	}

	/** Set Scroll Bar Style */
	void SetScrollBarStyle(const FScrollBarStyle* InStyle)
	{
		if (ScrollBar)
		{
			ScrollBar->SetStyle(InStyle);
		}
	}

	/** Set ScrollBarAlwaysVisible attribute */
	void SetScrollBarTrackAlwaysVisible(bool InAlwaysVisible)
	{
		if (ScrollBar)
		{
			ScrollBar->SetScrollBarTrackAlwaysVisible(InAlwaysVisible);
		}
	}
};
```

```CustomizableListView.h
#pragma once

#include "CoreMinimal.h"
#include "Widgets/Views/SListView.h"
#include "Components/ListView.h"
#include "SListViewCustom.h"
#include "CustomizableListView.generated.h"

/**
 * ListViewを継承したクラス
 */
UCLASS()
class TEST_API UCustomizableListView : public UListView
{
	GENERATED_BODY()

public:
	UCustomizableListView(const FObjectInitializer& Initializer) : UListView(Initializer){}

	/** Set Scroll Bar Style */
	UFUNCTION(BlueprintCallable)
		void SetScrollBarStyle(const FScrollBarStyle& InStyle);

	/** Set ScrollBarAlwaysVisible attribute */
	UFUNCTION(BlueprintCallable)
		void SetScrollBarTrackAlwaysVisible(bool InAlwaysVisible);

protected:
	virtual TSharedRef<STableViewBase> RebuildListWidget() override;
};
```

```CustomizableListView.cpp
#include "CustomizableListView.h"

TSharedRef<STableViewBase> UCustomizableListView::RebuildListWidget()
{
	return ConstructListView<SListView>();
}

void UCustomizableListView::SetScrollBarStyle(const FScrollBarStyle& InStyle)
{
	TSharedPtr<SListViewCustom<UObject*>> MyListViewCustom = StaticCastSharedPtr<SListViewCustom<UObject*>>(MyListView);
	MyListViewCustom->SetScrollBarStyle(&InStyle);
}

void UCustomizableListView::SetScrollBarTrackAlwaysVisible(bool InAlwaysVisible)
{
	TSharedPtr<SListViewCustom<UObject*>> MyListViewCustom = StaticCastSharedPtr<SListViewCustom<UObject*>>(MyListView);
	MyListViewCustom->SetScrollBarTrackAlwaysVisible(InAlwaysVisible);
}
```

## Blueprintでデザイン変更

Blueprintに関数を公開できたので、Widget Blueprintから設定します。
Normal Thumb Image,Hovered Thumb Image,Dragged Thumb Imageを変更しました。
マテリアルは[こちらの角丸マテリアル](https://historia.co.jp/archives/19988/)を使用しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/9529a842-ce50-82da-fc07-96874a15c928.png)

# 今回できなかったこと

- スクロールバーにカーソルを合わせるとバー上下の線が表示されてしまう
ここを消すにはさらに深い階層まで手を入れないといけなさそうだったので今回は断念しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/e369f0a0-817c-a83f-d8b7-96a24e4e9578.png)

- スクロールバーの横幅の変更
どこで指定しているのかまでコードを追えていないです。

# 参考サイト

https://docs.unrealengine.com/4.27/ja/ProgrammingAndScripting/ProgrammingWithCPP/CPPTutorials/UMG/

https://historia.co.jp/archives/10389/

https://historia.co.jp/archives/19988/