226 lines
7.3 KiB
Markdown
226 lines
7.3 KiB
Markdown
Haklısın: Grid’de yatay/dikey akışı sadece **Constraint** değil, **Start Axis** belirler.
|
||
Aşağıya “dikey liste”, “yatay tek sıra” ve “çok sütunlu grid” için **tam parametre setlerini** koyuyorum; hepsi tek bir **dikey ScrollView** içinde problemsiz çalışır.
|
||
|
||
---
|
||
|
||
## 0) Temel kurgu (bir kez)
|
||
|
||
```
|
||
Canvas
|
||
└─ ScrollView (dikey)
|
||
└─ Viewport
|
||
└─ Content ← (VerticalLayoutGroup + ContentSizeFitter[Vertical=PreferredSize])
|
||
```
|
||
|
||
* `Content / VerticalLayoutGroup`
|
||
|
||
* Child Alignment: Upper Center
|
||
* Spacing: 32 (örnek)
|
||
* Child Control Width/Height: **true**
|
||
* Child Force Expand Width: **true**, Height: **false**
|
||
* **Önemli:** İç içe `LayoutGroup` olan yerlerde **ContentSizeFitter kullanma**. Sadece **ScrollView/Content**’te dursun. Aksi halde “layout loop” uyarısı çıkar.
|
||
|
||
Her kategori bir **Section** prefab:
|
||
|
||
```
|
||
Section
|
||
├─ Header (başlık)
|
||
└─ ItemsParent ← (buradaki LayoutGroup tipi, dizilim tipini belirler)
|
||
```
|
||
|
||
Section kökünde `VerticalLayoutGroup` olsun. `ItemsParent`’ın **kendi başına ContentSizeFitter’ı yok**.
|
||
|
||
---
|
||
|
||
## 1) Dikey liste (alt alta kartlar)
|
||
|
||
`ItemsParent` → **VerticalLayoutGroup**
|
||
|
||
* VerticalLayoutGroup
|
||
|
||
* Child Alignment: Upper Center
|
||
* Spacing: 20
|
||
* Child Control Width/Height: **true**
|
||
* Child Force Expand Width: **true**, Height: **false**
|
||
* Item prefablarında **LayoutElement**
|
||
|
||
* Preferred Height: örn. `220`
|
||
* Flexible Height: `0`
|
||
|
||
Bu kurulumda genişlik parent’tan gelir, yükseklik `LayoutElement` ile tutarlı olur.
|
||
|
||
---
|
||
|
||
## 2) Yatay **tek sıra** (sağa doğru uzayan sıra — istersen yatay scroll yaparsın)
|
||
|
||
Bunu iki şekilde kurarsın:
|
||
|
||
### 2A) Grid ile tek satır
|
||
|
||
`ItemsParent` → **GridLayoutGroup**
|
||
|
||
* **Start Corner:** Upper Left
|
||
* **Start Axis:** **Vertical** ⬅️ *(tek satır için kritik)*
|
||
* **Constraint:** **Fixed Row Count**
|
||
* **Constraint Count:** **1**
|
||
* **Cell Size:** (kart boyutu, örn. 420×280)
|
||
* **Spacing:** X=24, Y=24
|
||
* **Child Alignment:** Upper Left
|
||
|
||
> “Start Axis = Vertical” + “Fixed Row Count = 1” ⇒ önce **satırı doldurur**, sonra **yeni kolona** geçer. Yani tek bir sıra halinde sağa doğru uzar. Yatay ScrollView kullanacaksan bu kalıp idealdir.
|
||
|
||
### 2B) HorizontalLayoutGroup ile tek satır
|
||
|
||
`ItemsParent` → **HorizontalLayoutGroup**
|
||
|
||
* Spacing: 24
|
||
* Child Control Height: true
|
||
* Child Control Width: false (genişliği kart belirlesin)
|
||
* Child Force Expand: false/false
|
||
|
||
> Basit yatay sıra istiyorsan bu daha hafif. Yatay ScrollView ile iyi çalışır. Grid gerekmiyorsa tercih edilir.
|
||
|
||
---
|
||
|
||
## 3) Çok sütunlu **grid** (ör. 2 sütun, alta doğru yeni satırlar)
|
||
|
||
`ItemsParent` → **GridLayoutGroup**
|
||
|
||
* **Start Corner:** Upper Left
|
||
* **Start Axis:** **Horizontal** ⬅️ *(satırı soldan sağa doldurur)*
|
||
* **Constraint:** **Fixed Column Count**
|
||
* **Constraint Count:** **2** *(2 sütun/row)*
|
||
* **Cell Size:** (kart boyutu, örn. 480×320)
|
||
* **Spacing:** X=24, Y=24
|
||
* **Child Alignment:** Upper Center
|
||
|
||
> “Start Axis = Horizontal” + “Fixed Column Count = 2” ⇒ **satır** önce 2 kolonla dolar, sonra **alt satıra** geçer. Mağaza ekranlarındaki “chest/gem/ticket packs” dizilimleri için tipik ve temiz çözüm.
|
||
|
||
---
|
||
|
||
## 4) Ekran genişliğine göre hücreyi otomatik hesaplat (profesyonel dokunuş)
|
||
|
||
Grid’i her çözünürlükte “tam **N sütun**” yapacak ufak bir yardımcı:
|
||
|
||
```csharp
|
||
using UnityEngine;
|
||
using UnityEngine.UI;
|
||
|
||
[RequireComponent(typeof(GridLayoutGroup), typeof(RectTransform))]
|
||
public class GridAutoSizer : MonoBehaviour
|
||
{
|
||
[Min(1)] public int columns = 2; // satır başına kaç sütun
|
||
public float aspect = 0.66f; // hücre yüksekliği = width * aspect (örn. 0.66 => 3:2)
|
||
public Vector2 spacing = new Vector2(24, 24);
|
||
public RectOffset padding = new RectOffset(24, 24, 24, 24);
|
||
|
||
GridLayoutGroup grid;
|
||
RectTransform rt;
|
||
|
||
void Awake() { grid = GetComponent<GridLayoutGroup>(); rt = GetComponent<RectTransform>(); Apply(); }
|
||
void OnRectTransformDimensionsChange() { if (isActiveAndEnabled) Apply(); }
|
||
|
||
void Apply()
|
||
{
|
||
var totalW = rt.rect.width - padding.left - padding.right - spacing.x * (columns - 1);
|
||
var cellW = Mathf.Floor(totalW / columns);
|
||
var cellH = Mathf.Round(cellW * aspect);
|
||
|
||
grid.cellSize = new Vector2(cellW, cellH);
|
||
grid.spacing = spacing;
|
||
grid.padding = padding;
|
||
|
||
grid.startCorner = GridLayoutGroup.Corner.UpperLeft;
|
||
grid.startAxis = GridLayoutGroup.Axis.Horizontal; // çok sütunlu grid için
|
||
grid.constraint = GridLayoutGroup.Constraint.FixedColumnCount;
|
||
grid.constraintCount = columns;
|
||
|
||
grid.childAlignment = TextAnchor.UpperCenter;
|
||
}
|
||
}
|
||
```
|
||
|
||
* Bunu **çok sütunlu** `ItemsParent`’larına ekle.
|
||
* Sadece **tek satırlık yatay sıra** istiyorsan (bölüm 2A), gridi o profile göre kur (StartAxis=Vertical, FixedRowCount=1) ve hücre genişliğini manuel ver veya yine yukarıdaki kodu “columns = çok büyük bir sayı” yerine “FixedRowCount=1” düzeni için uyarlayabilirsin.
|
||
|
||
---
|
||
|
||
## 5) İnce ayar ve sık düşülen tuzaklar
|
||
|
||
* **ContentSizeFitter’ı** yalnızca **ScrollView/Content**’te kullan. Grid/Vertical/Horizontal Layout olan ara düğümlerde kullanırsan **layout loop** uyarısı alırsın.
|
||
* **Item prefablarında** `LayoutElement` kullan; dikey listede `Preferred Height` anlamlıdır. **Grid’de hücre boyutunu Grid belirler**, `LayoutElement.Width` dikkate alınmaz.
|
||
* **Canvas Scaler**: `Scale With Screen Size (Ref: 1080×1920, Match=0.5)` → her cihazda tutarlı görünür.
|
||
* Çok sayıda item Instantiate ediyorsan, sonunda:
|
||
|
||
```csharp
|
||
Canvas.ForceUpdateCanvases();
|
||
LayoutRebuilder.ForceRebuildLayoutImmediate(contentRectTransform);
|
||
```
|
||
|
||
çağırmak layout’u anında toparlar.
|
||
|
||
---
|
||
|
||
### Hangi kombinasyonu ne zaman?
|
||
|
||
* “Alt alta büyük kartlar” → **VerticalLayoutGroup** (Bölüm 1)
|
||
* “Sağa doğru giden tek sıra” → **Grid (StartAxis=Vertical, FixedRowCount=1)** ya da **HorizontalLayoutGroup** (Bölüm 2)
|
||
* “2–3 sütunlu, alta doğru akan vitrin” → **Grid (StartAxis=Horizontal, FixedColumnCount=N)** + isteğe göre **GridAutoSizer** (Bölüm 3–4)
|
||
|
||
Sonraki adım olarak, chest/gem/ticket bölümlerinde kaç sütun istediğini belirleyip `GridAutoSizer`’ı ilgili `ItemsParent`’lara ekleyerek her çözünürlükte milimetrik hizayı koruyan bir mağaza elde edebilirsin.
|
||
|
||
|
||
Final hali
|
||
ItemsParent (ürünlerin olduğu kısım)
|
||
|
||
Dikey liste (kartlar alt alta):
|
||
|
||
VerticalLayoutGroup
|
||
|
||
Spacing: 20
|
||
|
||
Child Control Size: Width=ON, Height=ON
|
||
|
||
Child Force Expand: Width=ON, Height=OFF
|
||
|
||
Yatay tek sıra (sağa doğru uzayan):
|
||
|
||
GridLayoutGroup
|
||
|
||
Start Corner: Upper Left
|
||
|
||
Start Axis: Vertical
|
||
|
||
Constraint: Fixed Row Count
|
||
|
||
Constraint Count: 1 → tek satır
|
||
|
||
Cell Size: (kart boyutu)
|
||
|
||
Spacing: (örn. 24, 24)
|
||
|
||
Çok sütunlu grid (ör. 2–3 sütun, alta doğru):
|
||
|
||
GridLayoutGroup
|
||
|
||
Start Corner: Upper Left
|
||
|
||
Start Axis: Horizontal
|
||
|
||
Constraint: Fixed Column Count
|
||
|
||
Constraint Count: 2 veya 3
|
||
|
||
Cell Size: (kart boyutu)
|
||
|
||
Spacing: (örn. 24, 24)
|
||
|
||
ContentSizeFitter ekleme (ItemsParent’a genelde gerek yok). Grid/Vertical LG zaten Section’ın Preferred Height’ını hesaplar.
|
||
|
||
Item prefab (UIStoreItem_*)
|
||
|
||
LayoutElement
|
||
|
||
Dikey listede: Preferred Height = (örn. 220)
|
||
|
||
Grid’de: Cell Size’ı Grid belirler; Width/Height’i prefabla zorlamana gerek yok.
|