[ UI 오버레이 ]
[ Bottom Sheet ]
버튼을 눌러 화면 하단에서 UI가 올라오는 것을 Bottom Sheet / Action Sheet이라고 한다 .
특징은 기존 UI를 건들지 않고 오버레이 함이 특징이다 .
[ 부모 추가 ]
기존 UI의 부모가 될 Visual Element를 추가한다 .
문제는 Size를 100%로 함에도 화면을 덮지 못하고 기존 UI를 밀어올린다 .
[ 포지션 : Relative / Absolute ]
[ 상황 재현 ]
다음과 같은 상황에서 파란 UI는 중앙에 그려져야 한다 . 이렇게 배치됨은 flex의 설정 때문이다 ..
UGUI의 LayoutGroup에 추가된것과 같은 상황인데 , 이떄 Layout Element의 Ignore Layout과 같은 설정이 필요하다 .
Postion , Absolute(레이아웃의 영향 받지 않음 )를 선택하면 같은 효과를 받을 수 있다.
이를 사용하면 Layout의 영향을 받지 않는다 . cf ) Relative(레이아웃의 영향을 받음)
[ Flex : Shrink / Grow ]
[ Shrink 상황 재현 ]
해당 상황에서 레이아웃이 올라가고 , 파란 레이아웃 역시 원래 설정한 500/500사이즈와 다르게 적용 되어 있다 .
이는 Flex - Shrink값 때문이다 . ( 1이 기본으로 들어 있기 때문)
레이아웃에 영향을 미치는 다른 Visual Element들이 Shrink값 총합에서 차지하는 크기만큼 더 많이 줄어든다 .
[ Grow ]
grow 역시 같다 . 빈 공간을 매울지 결정한다 .
이는 웹의 반응형 레이아웃에 알맞다 .
[ 바텀 시트 ]
[ 부모 조작 ]
다시 돌아와 부모의 position을 Absolute로 한다 . 이 상황에서 Flex -Grow는 사용이 불가하다 .
[ 가림막 생성 ]
부모가 Absolute를 사용해 자식은 Relative사용이 가능하다 . Grow를 1로 만든다 .
불투명한 검정으로 만든다 .
[ Bottom Sheet 생성 ]
가림막을 형제로 가지는 바텀 시트를 만든다 . Position은 Absolute로 정한다 .
버튼 / 두개의 라벨 / 사진이 필요하다 .
[ Lanbel 조작 ]
해당 라벨은 스타일 시트로 만들어 보자 .
Inlined styles는 UXML의 재사용성과 성능상의 이유로 Style sheet의 사용을 권장한다 . 각 레이블에 적용한다 .
[ 버튼 생성 ]
부모의 우측에 설정 . Absolute로 우측 상단에 넣어준다 .
스크립트를 통해 버튼을 누르면 애니메이션이 재생되며 바텀 시트가 올라온다 .
지금은 특정 UI 내부에 바텀시트가 들어있지만 재사용성 / 관리 / 성능 을 위해 별도의 UXML파일을 불러온다 .
[ 디스플레이 : Flex , Node ]
[ Opacity 동작 ]
버튼을 누르면 바텀 그룹이 사라지고 나타난다 .
사라짐은 Display의 Opacity를 조작한다 (UGUI 의 Canvas Group의 알파값 동작과 같음)
Opacity 값은 자식에게 상속된다 .
[ 문제 ]
사실 보이지만 않을 뿐 , 아래의 다른 UI와의 상호작용 (hover)등을 막고 있다 .
지금 필요한건 보이지 않고 ,입력도 막지 않는 상태가 필요하다 .
[ Display ]
이를 위해 Display 속성을 활용하자 . 눈 모양 아이콘을 비활성화 하면 보이지 않고 입력도 잘 처리한다 .
디스플레이를 끄면 레이아웃 그룹도 변함을 볼 수 있다 .
[ 스크립트 준비 ]
[ 스크립트 생성 ]
C#스크립트를 생성 , UI Controller로 생성하고 UI Document 가 붙은 오브젝트에 연결한다 .
특정 UI를 찾기 위해서 사용하는 UQuery 는 UI 계층구조 최상위 노드가 필요하다 .
UI Builder 의 Hirearchy는 Visual Tree라고도 칭한다.
Hirearchy에는 보이지 않는 Root Visual Element가 존재한다 .
각 요소를 스크립트에서 찾는것까지의 과정은 다음과 같다 .
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//선언으로 UI ToolKit의 기능 사용
using UnityEngine.UIElements;
public class UIController : MonoBehaviour
{
//바텀시트 그룹 전체를 담는다
private VisualElement _bottomController;
//열기 버튼
private Button _openButton;
//닫기 버튼
private Button _closeButton;
// Start is called before the first frame update
void Start()
{
//UI상 특정 Elements를 찾을떄 사용하는 UQuery . 이를 위해 UI 계층구조 최상위 루트 노드가 필요하다 .
var root = GetComponent<UIDocument>().rootVisualElement;
//UQuery는 루트.Q<타입>("이름");
//바텀 컨트롤러
_bottomController = root.Q<VisualElement>("Container_Botton");
//버튼들
_openButton = root.Q<Button>("Button_Open");
_closeButton = root.Q<Button>("Button_Close");
//시작시 바텀그룹을 감춘다 - 그룹의 display에 접근하여 꺼준다.
_bottomController.style.display = DisplayStyle.None;
}
// Update is called once per frame
void Update()
{
}
}
[ 스크립트 : 버튼 ]
[ 버튼 콜백 등록 ]
에디터상 버튼의 콜백함수는 버튼의 OnClick에 추가 가능했다 . UI ToolKit에서는 스크립트로만 가능하다 .
//버튼 . RegisterCallback<이벤트 타입>(할일) 의 방식으로 등록
_openButton.RegisterCallback<ClickEvent>(OnOpenButtonClicked);
_closeButton.RegisterCallback<ClickEvent>(OnCloseButtonClicked);
private void OnOpenButtonClicked(ClickEvent evt)
{
//바텀 시트 그룹을 보여준다
_bottomController.style.display = DisplayStyle.Flex;
}
private void OnCloseButtonClicked(ClickEvent evt)
{
//바텀 시트 그룹을 보여준다
_bottomController.style.display = DisplayStyle.None;
}
[ USS 트랜지션 애니메이션 ]
버튼을 눌러 바텀 시트가 위로 올라오고 가림막이 서서히 어두워지는 효과를 만든다 .
[ 바텀 시트 위치 조정 ]
Position의 Bottom 값을 바꿀 수 도 있지만 Transform 의 Translate의 값의 변경 할 수 있다 .
Position의 상하좌우와 Transform의 상하좌우는 뭐가 다를까?
유니티는 정적 레이아웃은 Position의 상하좌우를 사용하고 ,
애니메이션의 동적 값은 Layout재계산에 포함되지 않는 Transform을 권장한다 .
Transform - Translate - y에 100%를 넣어준다 . (자신의 높이만큼 이동)
[ 바텀 시트 이동 애니메이션 생성 ]
그전 버튼의 상태별 Transition 애니메이션은 Pseudo로 버튼의 스타일이 바뀔때 변화 전, 후를 애니메이션을 부드럽게
연결하였다 . 버튼은 Pseudo로 변화가 가능하지만 일반 Visual Element는 스크립트 제어가 필요하다 .
화면 안 / 밖 상태의 스타일 클래스를 만들어 주자 .
먼저 기본 상태에 애니메이션을 설정해준다 .
위로 올라온 시트 / 내려온 시트 두가지의 스타일 클래스를 만들어 준다 .
Botto, Sheet Up을 지우자 따로 씬의 실행 없이 스타일에 변화에 따른 transitoin 애니메이션을 볼 수 있다 .(추가 역시 같음)
이를 스크립트로 구현해보자 .
[ 가림막 투명도 조절 ]
가림막의 Opacity를 0,1 상태의 스타일을 추출해서 만들어주자 .
[ 스크립트 - 스타일 ]
[ 적용 ]
private void OnCloseButtonClicked(ClickEvent evt)
{
//바텀 시트 그룹을 보여준다
_bottomController.style.display = DisplayStyle.None;
//셀렉터를 끌어 비주얼 엘리먼트에 떨구는 것과 같다 .
_bottomSheet.AddToClassList("bottomsheet--up");
_scrim.AddToClassList("scrim--fadein");
}
private void OnOpenButtonClicked(ClickEvent evt)
{
//바텀 시트 그룹을 보여준다
_bottomController.style.display = DisplayStyle.Flex;
//이미 스타일이 있다면 변화 애니메이션이 안나오기에 초기화 필요 클래스 리스트에서 제거한다 .
_bottomSheet.RemoveFromClassList("bottomsheet--up");
_scrim.RemoveFromClassList("scrim--fadein");
}
[ 스크린 값 변경을 CSS에서 수행 ]
css 파일 해당 스타일에서 값을 수정하자 . 다만 , 다음의 주의점이 존재한다 .
[ 아쉬운점 ]
창을 닫을때 바텀 시트 그룹 감춤이 우선되어 사라지는 애니메이션 적용이 이루어 지지 않는다 .
이는 다음 장에서 해결해보자 .
'유니티' 카테고리의 다른 글
[유니티] Some objects were not cleaned up when closing the scene. (Did you spawn new GameObjects from OnDestroy?) 오류 (0) | 2023.02.20 |
---|---|
[유니티] 캔버스를 부모로 설정시 Transform이 바뀌는 문제 해결 (0) | 2023.02.16 |
[UI Tool Kit] 03 . 레이아웃과 버튼 애니메이션 (0) | 2023.02.13 |
[유니티] UI Tool Kit 01 . UI Tool Kit에 관하여 (0) | 2023.02.13 |
[ 유니티 ] UI Tool Kit 02 . 첫 런타임 UI 만들기 (0) | 2023.02.10 |