React.Native

[QML] 레이아웃 잡기 : Grid, Row, Column

De-v-signer 2024. 11. 24. 04:28

마크업에서 가장 많이 사용하는 것 중 하나가 바로 레이아웃 관련된 내용일 것이다. QML에서는 레이아웃에 관련하여 세 가지 기능을 제공하는데, Grid와 Row와 Column이 그들이다. 이들을 잘 몰랐을 때에는 Item에서 살펴봤던 anchors 속성을 사용하거나 x.y 좌표를 사용해 배치를 잡는 경우가 많았는데, 각각 특성이 있어 원하는 목적에 따라 잘 알고 사용해야 하며, 사실 레이아웃을 위해 만들어진 컴포넌트는 이 셋이므로 되도록 이들을 사용하는 것이 안전하다.

1. Row

Row는 말 그대로 행으로 배치되는 요소들을 정의한다. 즉, Row의 자식 요소들은 자동으로 가로로 배치된다.

Row {
	width:parent.width
    height:200
    spacing:5

	Item {
    	id:item1
        width:100
        height:100
        anchors.verticalCenter:parent.verticalCenter //Okay
    }
    
    Item {
    	id:item2
        width:100
        height:100
        //anchors.left:item1.right //Error
    }
    
    Item {
    	id:item3
        width:100
        height:100
        //anchors.horizontalCenter:parent.horizontalCenter //Error
    }
}

예시에서  item1, item2, item3은 5의 여백을 가진 채로 좌우로 길게 배치된다. 주의할 점은 각 아이템의 마지막에 있는 anchors 부분인데, 일단 item1의 anchors.verticalCenter는 높이를 기준으로 가운데 위치시키는 내용으로, Row의 높이가 200인 상태에서 높이가 100인 Item을 verticalCenter로 위치시키는 것이다. 상하 50의 여백이 생기는 채로 가운데에 위치하게 된다.

이처럼 anchors.verticalCenter나 top, bottom과 같이 상/하로 고정하는 속성들은 Row의 배치 규칙과 위배되는 부분이 없으므로 큰 문제가 없다. 그러나 item2와 item3에 쓰인 left, horizontalCenter와 같은 속성들은 문제가 되는데, Row는 정해진 규칙대로 행 배치를 하려고 하는데 이들이 행 배치에 영향을 주는 속성들이기 때문이다. item2에 쓰인 left / right 속성은 Row를 사용하지 않고 좌우 배치를 하고 싶을 때 쓰는 두 컴포넌트의 고정 방법인데, Row의 의도와 위배된다. horizontalCenter의 경우 가로 기준 가운데로 배치하려는 속성이므로 마찬가지로 가로 배치 규칙을 가진 부모와 대치된다. 그렇기 때문에 이 둘을 사용하면 Row는 작동하지 않고 에러를 발생한다.

2. Column

Column은 Row 컴포넌트의 세로 배치 버전으로, 세부적으로도 크게 다르지 않고 동일하다. anchors 속성을 사용할 때에는 반대로 horizontalCenter나 left/right는 위배되지 않지만, top/bottom이나 verticalCenter와 같이 세로 배치를 하는 속성들은 충돌한다.

Column {
	width:200
    height:parent.height
	
    Item {
    	id:item1
    	width:100
        height:100
        anchors.horizontalCenter:parent.horizontalCenter
    }
    
    Item {
    	id:item2
    	width:100
        height:100
        // anchors.top: parent.top // Error
    }
    
    Item {
    	id:item3
    	width:100
        height:100
        // anchors.verticalCenter : parent.verticalCenter // Error
    }
}

3. Grid

Grid는 Row와 Column을 합친 컴포넌트로, 격자형 배치를 할 수 있게 해준다. 그렇기 때문에 위에서 설명한 두 가지 위배규칙도 복합적으로 반영되어, 자식요소에서는 anchors 속성을 사용할 수 없다.

Grid {
	width: 600
    height: 600
    
	columns : 3
    rows : 3
    
    Item {
    	id: item1
        width:100
        height:100
    }
    Item {
    	id: item2
        width:100
        height:100
    }
    Item {
    	id: item3
        width:100
        height:100
    }
    Item {
    	id: item4
        width:100
        height:100
    }
    Item {
    	id: item5
        width:100
        height:100
    }
}

위의 Grid는 item1,2,3이 첫번째 줄, item4,5가 두번째 줄을 만드는 격자형 레이아웃이 생성될 것이다. 그리고 각 아이템들은 200*200의 공간 중 100*100의 공간을 사용하며 좌측상단(0,0의 위치)에 붙은 형태가 된다. 의도한 바라면 좋겠지만, 다른 의도가 있다면, 예를 들어 이들을 가운데에 두고 싶다면 어떻게 하면 될까?

Grid {
	width: 600
    height: 600
    
	columns : 3
    rows : 3
    
    Item {
        width:width/3
        height:height/3
        
        Item {
        	id: item1
        	width:100
            height:100
            anchors.centerIn:parent
        }
    }
    Item {    	
        width:width/3
        height:height/3
        
        Item {
	        id: item2
        	width:100
            height:100
            anchors.centerIn:parent
        }
    }
    Item {
        width:width/3
        height:height/3
        
        Item {
        	id: item3
        	width:100
            height:100
            anchors.centerIn:parent
        }
    }
    Item {
    	id: item4
        width:width/3
        height:height/3
    }
    Item {
    	id: item5
        width:width/3
        height:height/3
    }
}

위와 같이 자식 요소는 각 레이아웃의 칸을 가득 채우고, 손자요소를 만들면 anchors를 다양하게 사용할 수 있다. 이는 Row나 Column에서도 마찬가지로, 이들 레이아웃의 자식요소는 각 부모요소의 레이아웃 규칙에 따라 anchors 등 레이아웃에 영향을 줄 수 있는 규칙에 제재를 받지만, 손자 요소부터는 제약이 없다는 의미이다. 이는 보이는 것 없이 자리만 차지하도록 하는 Item 요소가 꼭 필요한 이유이기도 한데, 레이아웃에 Item이 '있을 것임'을 알려 그 자리를 확보해주기 때문이다.

반응형