diff --git a/README.md b/README.md index 8303d6a..be38b72 100644 --- a/README.md +++ b/README.md @@ -2,80 +2,59 @@ A declarative library for building reactive user interface. Built over [UniMob](https://github.com/codewriter-packages/UniMob). -## Core concepts +## Getting Started -Widgets are the building blocks of a app’s user interface, and each widget is an immutable declaration of part of the user interface. -Widgets form a hierarchy based on composition. +#### 1. Create view -UniMob.UI comes with a suite of powerful basic widgets, of which the following are commonly used: - -> **[Row](./Runtime/Widgets/Row.cs), [Column](./Runtime/Widgets/Column.cs)**
-> These widgets let you create layouts in both the horizontal (Row) and vertical (Column) directions. -> ->**[ZStack](./Runtime/Widgets/ZStack.cs)**
->A Stack widget lets you place widgets on top of each other in paint order. -> ->**[Container](./Runtime/Widgets/Container.cs)**
->The Container widget lets you create a rectangular visual element that has background color and custom size. - -So what does code that uses UniMob.UI look like? +View are regular MonoBehaviour that should be attached to gameObject. ```csharp -using UniMob; using UniMob.UI; -using UniMob.UI.Widgets; -using UnityEngine; -public class CounterApp : UniMobUIApp +public class CounterView : View { - [Atom] private int Counter { get; set; } + public UnityEngine.UI.Text counterText; + public UnityEngine.UI.Button incrementButton; - protected override Widget Build(BuildContext context) + // initial setup + protected override void Awake() { - return new Container { - BackgroundColor = Color.cyan, - Child = new Column { - Children = { - new UniMobText(WidgetSize.Fixed(400, 50)) { - Value = "Tap count: " + Counter, - FontSize = 40, - }, - new UniMobButton { - OnClick = () => Counter += 1, - Child = new UniMobText(WidgetSize.Fixed(400, 50)) { - Value = "Increment", - FontSize = 40, - } - } - } - } - }; - } -} -``` + base.Awake(); -More code samples are located in [UniMob.UI Samples](https://github.com/codewriter-packages/UniMob.UI-Samples) repository. + incrementButton.Click(() => State.Increment); + } -## Custom widgets + // update view with data provided by State + // Render() is called automatically when data changes + // so view always be synchronized with state + protected override void Render() + { + counterText.text = "Conter: " + State.Counter; + } +} -Built-in widgets provide basic functionality, but modern games requires more complex and unique interfaces. You can create your own widgets to implement it. +// describe data required for view +public interface IConterState : IViewState { + Counter { get; set; } +} +``` -#### 1. Create widget +#### 2. Create widget -The widget contains the immutable data that is required for a user interface part. +A widget is an immutable description of an interface element. May contain additional data if necessary. ```csharp using UniMob.UI; -public class RealCounterWidget : StatefulWidget +public class CounterWidget : StatefulWidget { public int IncrementStep { get; set; } - public override State CreateState() => new RealCounterState(); + public override State CreateState() => new CounterState(); } ``` -#### 2. Create state +#### 3. Create state The State provides data for the View and optionally contains mutable state of this interface part. @@ -83,45 +62,94 @@ The State provides data for the View and optionally contains mutable state of th using UniMob; using UniMob.UI; -public class RealCounterState : ViewState +public class CounterState : ViewState, ICounterState { - public override WidgetViewReference View => WidgetViewReference.Resource("Prefabs/Real Counter View"); - + // where to load the view from? + public override WidgetViewReference View { + get => WidgetViewReference.Resource("Prefabs/Counter View"); + } + [Atom] public int Counter { get; private set; } public void Increment() { + // atom modification will automatically update UI Counter += Widget.IncrementStep; } } ``` -#### 3. Create view - -View describes how data provided by State should be rendered on the screen. +#### 3. Run app ```csharp +using UniMob; using UniMob.UI; -public class RealCounterView : View +public class CounterApp : UniMobUIApp { - public UnityEngine.UI.Text counterText; - public UnityEngine.UI.Button incrementButton; - - protected override void Awake() + protected override Widget Build(BuildContext context) { - base.Awake(); - - incrementButton.Click(() => State.Increment); + return new ConterWidget(); } +} +``` - protected override void Render() - { - counterText.text = State.Counter.ToString(); - } +## Widget Composition + +Widgets are the building blocks of a app’s user interface. +Widgets form a hierarchy based on composition. + +UniMob.UI comes with a suite of powerful basic widgets, of which the following are commonly used: + +> **[Row](./Runtime/Widgets/Row.cs), [Column](./Runtime/Widgets/Column.cs)**
+> These widgets let you create layouts in both the horizontal (Row) and vertical (Column) directions. +> +>**[ZStack](./Runtime/Widgets/ZStack.cs)**
+>A Stack widget lets you place widgets on top of each other in paint order. +> +>**[Container](./Runtime/Widgets/Container.cs)**
+>The Container widget lets you create a rectangular visual element that has background color and custom size. +> +>**[Scroll Grid Flow](./Runtime/Widgets/ScrollGridFlow.cs)**
+>The ScrollGridFlow widget lets you create a virtualized scrollable grid of elements. + +Composition of widgets allows you to build complex custom interfaces that will automatically update when needed. + +```csharp +private Widget Build(BuildContext context) { + return new ScrollGridFlow { + CrossAxisAlignment = CrossAxisAlignment.Center, + MaxCrossAxisExtent = 750.0f, + Children = { + this.BuildDailyOffers(), + + this.BuildGemsHeader(), + this.BuildGemsSlots(), + + this.BuildGoldHeader(), + this.BuildGoldSlots(), + } + }; } + +private IEnumerable BuildDailyOffers() { + return this.DailyOffersModel + .GetAllOffers() + .Where(offer => offer.Visible) // subscribe to 'Visible' atom + .Select(offer => this.BuildDailyOffer(offer.Id); +} + +private Widget BuildDailyOffer(string offerId) { + return new DailyOfferWidget(offerId) { + Key = Key.Of($"store_item_{offerId}") + }; +} + +// ... ``` +More code samples are located in [UniMob.UI Samples](https://github.com/codewriter-packages/UniMob.UI-Samples) repository. + ## How to Install Minimal Unity Version is 2019.3.