Skip to content
This repository has been archived by the owner on Dec 28, 2023. It is now read-only.

Add ContentPopup #276

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open

Add ContentPopup #276

wants to merge 5 commits into from

Conversation

sung-su
Copy link
Collaborator

@sung-su sung-su commented Apr 21, 2020

Description of Change

Add ContentPopup.
It is a popup with only one view, and has less interface restrictions than other popups. (TwoButtonPopup, InformationPopup)

API Changes

Added:

public class ContentPopup
{
    public ContentPopup();
    public event EventHandler Dismissed;
    public View Content { get; set; }
    public bool IsOpen { get; set; }
    public void Dismiss();
    protected virtual bool OnBackButtonPressed();
}

public class ContentPopupManager
{
    public static async Task ShowPopup(this INavigation navigation, ContentPopup popup);
    public static async Task ShowPopup(ContentPopup popup);
}

Usage:

ContentPopup popup = new ContentPopup();
await Navigation.ShowPopup(popup);
popup.Dismiss();

Screenshot:
cp

/// BindableProperty. Identifies the content bindable property.
/// </summary>
/// <since_tizen> 4 </since_tizen>
public static readonly BindableProperty ContentProperty = BindableProperty.Create(nameof(Content), typeof(View), typeof(TwoButtonPopup), null);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public static readonly BindableProperty ContentProperty = BindableProperty.Create(nameof(Content), typeof(View), typeof(TwoButtonPopup), null);
public static readonly BindableProperty ContentProperty = BindableProperty.Create(nameof(Content), typeof(View), typeof(ContentPopup), null);

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.

@sung-su
Copy link
Collaborator Author

sung-su commented Apr 21, 2020

Currently, I am considering changing to a renderer structure.

}
}

public void Dispose()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use Dispose pattern

        public void Dispose()
        {
            Dispose(true);
        }

        protected virtual void Dispose(bool disposing)
        {
                if (disposing && _renderer != null)
                {
                        _renderer.Dispose();
                        _renderer = null;
                }
        }

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.

/// <summary>
/// Shows the popup.
/// </summary>
void Show();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No more need

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.

public void Dismiss()
{
_popup?.Hide();
_popup?.Dismiss();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should not use Dismiss, because it destroy popup

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.

/// BindableProperty. Identifies the Content bindable property.
/// </summary>
/// <since_tizen> 4 </since_tizen>
public static readonly BindableProperty ContentProperty = BindableProperty.Create(nameof(Content), typeof(View), typeof(ContentPopup), null);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to update parent

void UpdateContent() 
{
    OnChildAdded(Content);
}
               // it is method of Element
		protected virtual void OnChildAdded(Element child)
		{
			child.Parent = this;

			child.ApplyBindings(skipBindingContext: false, fromBindingContextChanged: true);

			ChildAdded?.Invoke(this, new ElementEventArgs(child));

			OnDescendantAdded(child);
			foreach (Element element in child.Descendants())
				OnDescendantAdded(element);
		}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.


public void SetElement(Element element)
{
element.Parent = Application.Current.Parent;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Set only if no parent

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.

var renderer = Platform.GetOrCreateRenderer(_element.Content);
(renderer as LayoutRenderer)?.RegisterOnLayoutUpdated();
var native = renderer.NativeView;
var sizeRequest = _element.Content.Measure(XForms.NativeParent.Geometry.Width, XForms.NativeParent.Geometry.Height).Request.ToPixel();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need it

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.

(renderer as LayoutRenderer)?.RegisterOnLayoutUpdated();
var native = renderer.NativeView;
var sizeRequest = _element.Content.Measure(XForms.NativeParent.Geometry.Width, XForms.NativeParent.Geometry.Height).Request.ToPixel();
native.MinimumHeight = sizeRequest.Height;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Content should be always fullscreen size

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.

@myroot
Copy link
Collaborator

myroot commented Apr 22, 2020

Please test BindingContext chaining is working on ContentPopup.

ContentPopup should use parent's BindingContext, if not set a BindingContext
and Content of ContentPopup also use BindingContext of ContentPage, if not set a BindingContext on Content

@@ -48,6 +48,7 @@ public static void Init()
{
if (IsInitialized) return;
IsInitialized = true;
ContentPopup.RendererFunc = () => new ContentPopupRenderer();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where this technique come from?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

come from me 😉

ElmSharp.Popup _popup;
ContentPopup _element;

public void SetElement(Element element)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public void SetElement(Element element)
public void SetElement(ContentPopup element)

Because it is ContentPopupRenderer

void OnDismissed(object sender, EventArgs e)
{
_element.SendDismissed();
Dispose();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you dispose it?

var renderer = Platform.GetOrCreateRenderer(_element.Content);
(renderer as LayoutRenderer)?.RegisterOnLayoutUpdated();
var native = renderer.NativeView;
native.MinimumHeight = 360;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not use static value 360
How about use align and weight?

native.AlignmentX= -1;
native.AlignmentY= -1;
native.WeightX = 1;
native.WeightY = 1;

@@ -48,6 +48,7 @@ public static void Init()
{
if (IsInitialized) return;
IsInitialized = true;
ContentPopup.RendererFunc = () => new ContentPopupRenderer();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ContentPopup.RendererFunc = () => new ContentPopupRenderer();
ContentPopup.CreateRenderer = () => new ContentPopupRenderer();


private void OnContentPopupDismissButtonClicked(object sender, EventArgs e)
{
ContentPopup _popup = new ContentPopup();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

            using (ContentPopup _popup = new ContentPopup())
            {
                var dismiss = new Button
                {
                    Text = "Dismiss",
                };
                dismiss.Clicked += (s, ee) =>
                {
                    _popup?.Dismiss();
                    label1.Text = "Test2 Dismissed";
                };

                var label = new Label
                {
                    Text = "This ContentPopup is dismissed as a below dismiss button.",
                    HorizontalTextAlignment = TextAlignment.Center,
                };

                var grid = new Grid();
                grid.HeightRequest = 360;
                grid.WidthRequest = 360;
                grid.RowDefinitions.Add(new RowDefinition());
                grid.RowDefinitions.Add(new RowDefinition());
                grid.RowDefinitions.Add(new RowDefinition());
                grid.RowDefinitions.Add(new RowDefinition());
                grid.RowDefinitions.Add(new RowDefinition());
                grid.Children.Add(label, 0, 1, 1, 3);
                grid.Children.Add(dismiss, 0, 1, 3, 4);

                _popup.Content = grid;
                _popup.Show();

                TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();
                _popup.Dismissed += (s, evt) => tcs.SetResult(true);
                _ = await tcs.Task;
            }


private void OnContentPopupDismissBackKeyClicked(object sender, EventArgs e)
{
ContentPopup _popup = new ContentPopup();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

            using (ContentPopup _popup = new ContentPopup())
            {                
                _popup.BackButtonPressed += (s, ee) =>
                {
                    _popup?.Dismiss();
                    label1.Text = "Test1 Dismissed";
                };

                string _longText = "This ContentPopup is dismissed as a back key.";
                var content = new Label { Text = _longText, HorizontalTextAlignment = TextAlignment.Center };

                _popup.Content = content;
                _popup.Show();

                TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();
                _popup.Dismissed += (s, evt) => tcs.SetResult(true);
                _ = await tcs.Task;
            }

/// Shows the popup.
/// </summary>
/// <since_tizen> 4 </since_tizen>
public void Show()
Copy link
Collaborator

@myroot myroot Apr 26, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about rename to Open?
and How about return Task that indicate closing timing

        TaskCompletionSource<bool> _tcsForDismiss;
        public Task Open()
        {
            IsShow = true;
            _tcsForDismiss = new TaskCompletionSource<bool>();
            return _tcsForDismiss.Task;
        }

        public void SendDismissed()
        {
            Dismissed?.Invoke(this, EventArgs.Empty);
            _tcsForDismiss?.TrySetResult(true);
        }

If you provide Task we can easily use

  using (var popup = new ContentPopup()) {
     poup.Content = new StackLayout { ... };
     _ = await popup.Open();
  }

@sung-su
Copy link
Collaborator Author

sung-su commented Apr 28, 2020

Fixed with reference to the above comments.

var renderer = Platform.GetOrCreateRenderer(_element.Content);
(renderer as LayoutRenderer)?.RegisterOnLayoutUpdated();
var native = renderer.NativeView;
native.MinimumHeight = XForms.NativeParent.Geometry.Height;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about use AligementX/Y and WeightX/Y?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will set MinimunHeight and MinimumWidth instead of Alignment and Weight.

/// BindableProperty. Identifies the IsShow bindable property.
/// </summary>
/// <since_tizen> 4 </since_tizen>
public static readonly BindableProperty IsOpenProperty = BindableProperty.Create(nameof(IsOpen), typeof(bool), typeof(ContentPopup), false);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TwoWay binding is more proper
defaultBindingMode : BindingMode.TwoWay

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

public static async Task ShowPopup(ContentPopup popup)
{
if (popup == null)
await Task.FromResult(false);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
await Task.FromResult(false);
return Task.FromResult(false);

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change to return

using (var renderer = DependencyService.Get<IContentPopupRenderer>(DependencyFetchTarget.NewInstance))
{
if (renderer == null)
await Task.FromResult(false);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
await Task.FromResult(false);
return Task.FromResult(false);

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change to return


popup.Content = label;

await ContentPopupManager.ShowPopup(popup);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
await ContentPopupManager.ShowPopup(popup);
await Navigation.ShowPopup(popup);

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

public Task Open()
{
_popup.Show();
_element.IsOpen = true;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
_element.IsOpen = true;
_element.SetValueFromRenderer(ContentPopup.IsOpenProperty, true);

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

Copy link
Contributor

@rookiejava rookiejava left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We decided to think again about providing ContentPopup on Galaxy Watch, which has a smaller screen size than mobile or TV.

The two main parts we are concerned with are:

  • Since the screen is small, the popup always occupies the entire screen, so there is no difference from using the page.
  • The complexity of managing the bezel interaction between the content of pop-ups created in a new window and the content of the existing page can be increased.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants