Xamarin.Forms: rendering Xamarin.Froms Control in native Dialog - wrap_content is ignored

Let's say I want to display a Xamarin.Froms control (for example Xamarin.Forms.Label

) in a native Android view.
The following code works. But it ignores the width and height of the control ( wrap_content

).

// create a Xamarin.Froms.Label
Xamarin.Forms.Label view = new Xamarin.Forms.Label()
{
    Text = "This is a Xamarin.Forms.Label",
    BackgroundColor = Color.Red,
};

// create a Renderer
var renderer = Xamarin.Forms.Platform.Android.Platform.CreateRenderer(view);

// create an AlertDialog
var builder = new AlertDialog.Builder(Xamarin.Forms.Forms.Context);
builder.SetView(renderer.ViewGroup); // Use the ViewGroup of the renderer
builder.SetTitle("Dialog");
// create and show the dialog
builder.Create().Show();

      

Produces the following:

Xamarin.Forms.Label screenshot

Performing the same action with a native label:

var view = new Android.Widget.TextView(Xamarin.Forms.Forms.Context)
{
    Text = "This is a Android.Widget.TextView",
    Background = new Android.Graphics.Drawables.ColorDrawable(Android.Graphics.Color.Red),
};
var builder = new AlertDialog.Builder(Xamarin.Forms.Forms.Context);

builder.SetView(view);
builder.SetTitle("Dialog");
builder.Create().Show();

      

Produces expected output:

Android.Widget.TextView screenshot

I'm looking for any hints or advice regarding measuring width and height in Xamarin.Forms and / or solutions for this kind of problem.


Update

Also note that this is independent of AlertDialog

, using LinearLayout

instead results AlertDialog

for the same behavior.

+3


source to share


2 answers


The following code works. But it ignores the width and height of the control (wrap_content).

Cause:

You have transferred ViewGroup

to AlertDialog

. But internally, AlertDialog

the layout options ViewGroup

won't work at all. Referring to this blog :

Every rule has an exception

...

The problem here is that AlertDialog.Builder supports a custom view, but does not provide a setView () implementation that accepts a layout resource; so you have to inflate the XML manually. However, since the result will go into a dialog that doesn't expose its root view (it doesn't actually exist yet), we don't have access to the final parent of the layout, so we can't use it for inflation. It turns out it doesn't matter because the AlertDialog will erase any LayoutParams on the layout anyway and replace them with match_parent .

So instead of passing ViewGroup

, pass the view AlertDialog

as your second attempt.

Update (some more research):

if try the following codes to set the height ViewGroup

to 400:

// create a Renderer
var renderer = Xamarin.Forms.Platform.Android.Platform.CreateRenderer(view);
// create an AlertDialog
var builder = new AlertDialog.Builder(Xamarin.Forms.Forms.Context);
renderer.ViewGroup.LayoutParameters = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WrapContent, 400);
builder.SetView(renderer.ViewGroup); // Use the ViewGroup of the renderer
builder.SetTitle("Dialog");
// create and show the dialog
builder.Create().Show();

      

It doesn't work, the dialog still almost covers the entire screen:

enter image description here

But if you add rendered ViewGroup

in LinearLayout

like this:

var renderer = Xamarin.Forms.Platform.Android.Platform.CreateRenderer(view);
//The following codes works correctly
renderer.ViewGroup.LayoutParameters = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WrapContent, 400);
LinearLayout linearLayout = new LinearLayout(Xamarin.Forms.Forms.Context);
linearLayout.LayoutParameters = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.WrapContent);
linearLayout.AddView(renderer.ViewGroup);
this.AddContentView(linearLayout,new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.WrapContent));

      



The height is set correctly:

enter image description here

So, at this level, the problem is AlertDialog

, as I mentioned above.

But If the height was set to Wrap_content

like this:

var renderer = Xamarin.Forms.Platform.Android.Platform.CreateRenderer(view);
//set the height again to wrap_content
renderer.ViewGroup.LayoutParameters = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.WrapContent);
LinearLayout linearLayout = new LinearLayout(this);
linearLayout.LayoutParameters = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.WrapContent);
linearLayout.AddView(renderer.ViewGroup);
this.AddContentView(linearLayout,new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.WrapContent));

      

rendererd ViewGroup

will start filling the whole screen again:

enter image description here

On this layer I found that the problem is with the renderingViewGroup

because after changing ViewGroup

to native LinearLayout

everything is fine.

I checked the Xamarin.Forms Source Codes and found the following Inherit hierarchy:

Xamarin.Forms.Platform.AndroidLabelRenderer ->
Xamarin.Forms.Platform.Android.ViewRenderer<TView, TNativeView> ->
Xamarin.Forms.Platform.Android.VisualElementRenderer<TElement> ->
Xamarin.Forms.Platform.Android.FormsViewGroup ->
Android.Views.ViewGroup

      

I found that none of these classes implemented the method ViewGroup.OnMeasure

.
Thus, it Wrap_content

will never work. You can refer to Custom ViewGroup for a detailed example of custom implementation ViewGroup

.

+1


source


I am answering my own question since this is the simplest way to solve the problem:

Since Xamarin.Forms 2.3.5 (as tentatively written) a new property appears View

next to ViewGroup

in IVisualElementRenderer

.



The solution is to use Xamarin.Froms 2.5.3 and properties View

:

Xamarin.Forms.Label view = new Xamarin.Forms.Label()
{
    Text = "This is a Xamarin.Forms.Label",
    BackgroundColor = Color.Red,
};

var renderer = Xamarin.Forms.Platform.Android.Platform.CreateRenderer(view);
var builder = new AlertDialog.Builder(Xamarin.Forms.Forms.Context);
builder.SetView(renderer.View); // Use View instead of ViewGroup
builder.SetTitle("Dialog");
builder.Create().Show();

      

+1


source







All Articles