UMG ListView

UMG ListView »ç¿ë¹ý¿¡ ´ëÇؼ­ ¾Ë¾Æ º»´Ù.

ListView ¸®¼Ò½º ¸¸µé±â

1. ListItem ¸¸µé±â
2. ListView ¸¸µé±â
3. InventoryItemData ¸¸µé±â

ListView´Â UObject·Î ŸÀÔÀ¸·Î µ¥ÀÌÅ͸¦ Ãß°¡ ÇÑ´Ù. UObject¸¦ »ó¼ÓÇÑ µ¥ÀÌÅÍ Å¬·¡½º¸¦ º°µµ·Î ¸¸µç´Ù.
¿©±â¼­´Â InventoryItemData¸¦ ¸¸µç´Ù.




1. ListItem ¸¸µé±â

À§Á¬ ºí·çÇÁ¸°Æ®¸¦ »ý¼ºÇÑ´Ù.  À̸§Àº "BP_ListItem"ÀÌ´Ù.
È­¸é Å©±â´Â Custom ( 200X50 )À¸·Î ÇÑ´Ù.
À̹ÌÁö¿Í ÅؽºÆ®¸¦ Ãß°¡ ÇÑ´Ù.



2. ListView ¸¸µé±â

Border´Â ¹ÙÅÁ»öÀ» Ä¥Çϱâ À§ÇØ Ãß°¡ÇÑ °ÍÀ¸·Î Àå½Ä¿ëÀÌ´Ù.
ListView¸¦ Ãß°¡ Çϸé "ÀÌ ¸ñ·Ï¿¡ EntryWidgetClass¸¦ ÁöÁ¤ÇÏÁö ¾Ê¾Ò½À´Ï´Ù"¶ó´Â ¹®±¸°¡ ¶á´Ù.
Áö±ÝÀº BP_ListItemÀ» "Entry Widget Class"¿¡ Ãß°¡ ÇÒ¼ö ¾ø´Ù.



3. InventoryItemData ¸¸µé±â

¾ð¸®¾ó ¿¡µðÅÍ > C++ Ŭ·¡½º Ãß°¡ > UObject¸¦ »ó¼ÓÇؼ­ UInventoryItemData¸¦ ¸¸µç´Ù.

µ¥ÀÌÅ͸¸ Á¸ÀçÇϱ⠶§¹®¿¡ Çì´õ ÆÄÀÏ¿¡ »ç¿ëÇÒ µ¥ÀÌÅ͸¸ Ãß°¡ÇÑ´Ù.

µ¥ÀÌÅÍ´Â ´ÙÀ½°ú °°ÀÌ ±¸¼ºÇß´Ù.
ItemIndex : À̹ÌÁö À妽º·Î ListItem¿¡¼­ À̹ÌÁö·Î º¯°æÇÑ´Ù.
ItemText : ListItem¿¡¼­ ¹®ÀÚ¿­·Î º¯°æÇÑ´Ù.

InventoryItemData.h ÆÄÀÏ
#pragma once

#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "InventoryItemData.generated.h"

UCLASS()
class UMGLISTVIEWDEMO_API UInventoryItemData : public UObject
{
    GENERATED_BODY()
   
public:
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Meta = (AllowPrivateAccess = "true"))
    int32 ItemIndex;

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Meta = (AllowPrivateAccess = "true"))
    FString ItemText;
};

4. ¸®½ºÆ® Item Ŭ·¡½º »ý¼º

C++·Î ´ÙÀ½°ú °°ÀÌ ÆÄÀÏÀ» ¸¸µç´Ù.
»ó¼Ó : UserWidget
ÆÄÀÏÀ̸§Àº InventoryItem

ÆÄÀÏÀ» ¸¸µé¸é ´ÙÀ½°ú °°ÀÌ Çì´õ ÆÄÀÏÀÌ »ý¼º µÈ´Ù.
#pragma once

#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "InventoryItem.generated.h"

UCLASS()
class UMGLISTVIEWDEMO_API UInventoryItem : public UUserWidget
{
    GENERATED_BODY()
   
};


ListViewÀÇ ¾ÆÀÌÅÛÀº IUserObjectListEntry¸¦ »ó¼ÓÇØ¾ß ÇÑ´Ù.
IUserObjectListEntry.h Çì´õ ÆÄÀÏÀ» Ãß°¡ÇÏ°í IUserObjectListEntry¸¦ »ó¼ÓÇÑ´Ù.
#pragma once

#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "Blueprint/IUserObjectListEntry.h"
#include "InventoryItem.generated.h"

UCLASS()
class UMGLISTVIEWDEMO_API UInventoryItem : public UUserWidget, public IUserObjectListEntry
{
    GENERATED_BODY()
   
};

5. ¸®½ºÆ® ¾ÆÀÌÅÛÀÇ ºÎ¸ð Ŭ·¡½º¸¦ IUserObjectListEntry¸¦ »ó¼ÓÇÑ C++ Ŭ·¡½º·Î º¯°æÇÑ´Ù.
BP_ListItemÀÇ ºÎ¸ð Ŭ·¡½º¸¦ InventoryItemÀ¸·Î º¯°æÇÑ´Ù.

6. ¸®½ºÆ®ºä¿¡¼­ Entry Widget Class¸¦ ÁöÁ¤ÇÑ´Ù.
BP_ListView¿¡¼­ "Entry Widget Class"¸¦ "BP_ListItem"À¸·Î ÁöÁ¤ÇÑ´Ù.


7. BP_ListView¸¦ BP_UI_MAIN¿¡ ¹èÄ¡ ÇÑ´Ù.


8. ¸®½ºÆ® Item Ŭ·¡½º¿¡  UI ¸®¼Ò½º¿Í µ¥ÀÌÅÍ Ãß°¡

UInventoryItem Ŭ·¡½º¿¡ UI ¸®¼Ò½º¿Í µ¥ÀÌÅ͸¦ Ãß°¡ ÇÑ´Ù.
Visual Data´Â UI¸®¼Ò½º·Î È­¸é¿¡ º¸ÀÌ´Â µ¥ÀÌÅÍÀÌ´Ù.
Real Data´Â È­¸é¿¡ º¸ÀÌÁö ¾ÊÁö¸¸ ¾ÆÀÌÅÛÀÌ °¡Áö°í ÀÖ´Â Á¤º¸·Î InventoryItemDataÀÇ °ªÀ» ÀúÀå ÇصдÙ.

InventoryItem.h ÆÄÀÏÀÇ ÀϺÎ
UCLASS()
class UMGLISTVIEWDEMO_API UInventoryItem : public UUserWidget, public IUserObjectListEntry
{
    GENERATED_BODY()

protected:
    //Visual Data
    UPROPERTY()
    class UTextBlock* TextBlock_ItemText;
    UPROPERTY()
    class UImage* Image_ItemImage;

    //Real Data
    UPROPERTY()
    int Index;
    UPROPERTY()
    FString ItemText;
};

9. ¸®½ºÆ®ºä¿¡¼­ µ¥ÀÌÅÍ Ãß°¡¿Í Ŭ¸¯Çϱâ

¸®½ºÆ®ºä¿¡ µ¥ÀÌÅÍ Ãß°¡´Â UListView::AddItemÀ¸·Î ÇÑ´Ù.
AddItem¿¡ Ãß°¡ÇÏ´Â µ¥ÀÌÅÍ´Â UObject µ¥ÀÌÅ͸¦ »ó¼ÓÇÑ UInventoryItemDataÀÌ´Ù.

Áö±Ý ´Ü°è¿¡¼­´Â µ¥ÀÌÅ͸¦ ÀÌ·¸°Ô Ãß°¡ ÇÒ¼öÀִٴ°͸¸ ¾Ë°í ³Ñ¾î °£´Ù.

¾ÆÀÌÅÛ Å¬¸¯Àº ´ÙÀ½ ÇÔ¼ö·Î ºÒ·ÁÁú ÇÔ¼ö¸¦ ¿¬°áÇÑ´Ù.
UListView::OnItemClicked

MyListView.h ÆÄÀÏ
UCLASS()
class UMGLISTVIEWDEMO_API UMyListView : public UUserWidget
{
    GENERATED_BODY()

protected:
    void InitList();
    virtual bool Initialize() override;

protected:
    UPROPERTY()
    class UListView* ListView_Name;

    UFUNCTION()
    void OnItemClick(UObject* Obj);
};

MyListView.cpp ÆÄÀÏ
bool UMyListView::Initialize()
{
    if (Super::Initialize() == false)
        return false;

    ListView_Name->OnItemClicked().AddUObject(this, &UMyListView::OnItemClick);
    InitList();
    return true;
}

void UMyListView::InitList()
{
    for (int n = 0; n < 20; ++n)
    {
        UInventoryItemData* item = NewObject<UInventoryItemData>(this, UInventoryItemData::StaticClass());
        item->ItemIndex = n + 1;
        item->ItemText = FString::Printf(TEXT("%03d"), n + 1);
        ListView_Name->AddItem(item);
    }
}

void UMyListView::OnItemClick(UObject* Obj)
{
    UInventoryItemData* pData = Cast<UInventoryItemData>(Obj);

    if (IsValid(pData))
    {
        UE_LOG(LogTemp, Log, TEXT("Index=%d, Name=%s"), pData->ItemIndex, *pData->ItemText);
    }
}

10. ¸®½ºÆ® ¾ÆÀÌÅÛ¿¡¼­ NativeOnListItemObjectSet ÇÔ¼ö ó¸®

ListView´Â Ç׸ñÀ» Ãß°¡ÇÏ¸é ¸®½ºÆ® ¾ÆÀÌÅÛÀÇ NativeOnListItemObjectSet ÇÔ¼ö°¡ ºÒ¸°´Ù.
NativeOnListItemObjectSet ÇÔ¼ö¿¡¼­  ItemData·Î InventoryDataÀÇ ºñÁê¾ó ¸®¼Ò½º¸¦ ¼³Á¤ÇÑ´Ù.
SetData·Î ItemData¸¦ ÀúÀå ÇÑ´Ù.


InventoryItem.h ÆÄÀÏ
virtual void NativeOnListItemObjectSet(UObject* ListemItemObject) override;

InventoryItem.cpp ÆÄÀÏ
void UInventoryItem::NativeOnListItemObjectSet(UObject* ListemItemObject)
{
    UInventoryItemData* ItemData = Cast< UInventoryItemData>(ListemItemObject);
    if (IsValid(ItemData))
    {
        TextBlock_ItemText->SetText(FText::FromString(ItemData->ItemText));
        UTexture2D* Texture = LoadObject<UTexture2D>(nullptr, TEXT("/Game/texture/redbox.redbox"));
    }

    SetData(ItemData);
}


InventoryItemÀÇ Àüü ¼Ò½º´Â ´ÙÀ½°ú °°´Ù.

InventoryItem.h ÆÄÀÏ
// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "Blueprint/IUserObjectListEntry.h"
#include "InventoryItem.generated.h"

/**
 *
 */
UCLASS()
class UMGLISTVIEWDEMO_API UInventoryItem : public UUserWidget, public IUserObjectListEntry
{
    GENERATED_BODY()

public:
    void SetData(class UInventoryItemData* Data);

protected:
    virtual void NativeOnListItemObjectSet(UObject* ListemItemObject) override;
    virtual void NativeOnItemSelectionChanged(bool bIsSelected) override;

protected:
    //Visual Data
    UPROPERTY()
    class UTextBlock* TextBlock_ItemText;
    UPROPERTY()
    class UImage* Image_ItemImage;

    //Real Data
    UPROPERTY()
    int Index;
    UPROPERTY()
    FString ItemText;
};


InventoryItem.cpp ÆÄÀÏ
// Fill out your copyright notice in the Description page of Project Settings.

#include "InventoryItem.h"
#include "Components/TextBlock.h"
#include "Components/Image.h"
#include "InventoryItemData.h"

void UInventoryItem::SetData(class UInventoryItemData* Data)
{
    Index = Data->ItemIndex;
    ItemText = Data->ItemText;
}

void UInventoryItem::NativeOnListItemObjectSet(UObject* ListemItemObject)
{
    UInventoryItemData* ItemData = Cast< UInventoryItemData>(ListemItemObject);
    if (IsValid(ItemData))
    {
        TextBlock_ItemText->SetText(FText::FromString(ItemData->ItemText));
        if ((ItemData->ItemIndex % 3) == 0)
        {
            UTexture2D* Texture = LoadObject<UTexture2D>(nullptr, TEXT("/Game/texture/redbox.redbox"));
            if (Texture)
                Image_ItemImage->SetBrushFromTexture(Texture);
        }
        else if ((ItemData->ItemIndex % 3) == 1)
        {
            UTexture2D* Texture = LoadObject<UTexture2D>(nullptr, TEXT("/Game/texture/bluebox.bluebox"));
            if (Texture)
                Image_ItemImage->SetBrushFromTexture(Texture);
        }
        else
        {
            UTexture2D* Texture = LoadObject<UTexture2D>(nullptr, TEXT("/Game/texture/greenbox.greenbox"));
            if (Texture)
                Image_ItemImage->SetBrushFromTexture(Texture);
        }
    }

    SetData(ItemData);
}

void UInventoryItem::NativeOnItemSelectionChanged(bool bIsSelected)
{
    UE_LOG(LogTemp, Warning, TEXT("bIsSelected: %d, 0x%p, NativeOnItemSelectionChanged"), bIsSelected, this);
}


UmgListViewDemo.zip
InventoryItem.h
InventoryItem.cpp
InventoryItemData.h
InventoryItemData.cpp
MyListView.h
MyListView.cpp

PS)
NativeOnItemSelectionChanged ½ÇÇà °á°ú

½ÇÇà °á°ú¸¦ º¸¸é ÇØÁ¦, ¼±ÅÃÀÇ ¼ø¼­°¡ ÀÏÁ¤ÇÏÁö ¾Ê´Ù.