Determining a Views Pre-Render Dimensions in Xamarin Android

In this post, I discuss a method for getting a views width and height before it ever gets rendered to the screen in Xamarin Android.

Advertisements

Two (of many) things about Android that always sort of drives me nuts is the fact that Android can make it very difficult to determine how big something should be, and that linear layouts don’t support line breaks when their orientation is horizontal. We had a scenario recently where we had tags, or little text views, for each row in a list view. The tags came in at variable sizes, and needed to fill the entire line and break. This obviously meant that a relative layout was needed, but the problem is to position things on the next line, you must use layout_below. This made our situation complicated, because it meant that I had to determine how big each text view was, check if the next text view would overflow the line, and position it under the first text view of each line (which required a whole system of tracking text view id’s relative to line breaks consequently).

So why do I say all of this? Well, because part of the problem I needed to solve was determining the size of a view that was generated programmatically before it ever got rendered. Normally in Android, a view gets it’s onMeasure method called, which gets a height and width passed in to it to determine what the width or height should be, this has to happen because lots of views in Android are relative, meaning their size is dependent on another views size, which itself may be dependent on another views size, and so on and so forth. It turns out there is a way of determining the pre-render width of a view, and that will be the topic for today’s post.

Display Metrics

For anything you may need to know relating to the general display properties of a device, Android has a built in class called “DisplayMetrics”, which will tell you everything from width and height of the screen in pixels, to the pixel density, and anything else you would need to know to layout views programmatically, do I recommend programatic laying out of views? Not often, I’ve done it before, and it’s a bit of hell to say the least. Do I recommend it for some stuff? Absolutely, but that’s not the point, the point is DisplayMetrics gives you lots of valuable data. The first bit of code I’ll share with you is how to actually get the display metrics. First, I alias the namespace that DisplayMetrics resides in (I do this also because lots of other useful stuff exists in this namespace so it’s nice to have it shortened):

using AndroidResources = global::Android.Content.Res;

// Somewhere else in the file...
public static global::Android.Util.DisplayMetrics GetDisplayMetrics()
{
    return AndroidResources.Resources.System.DisplayMetrics;
}

You can see I also create essentially a getter for getting the display metrics, because having to type all that crap out every time I need to use display metrics is really, really cumbersome.

Determining pre-rendered width

The next bit of code is what I use to actually get the pre-rendered width of a view:

public static int GetPreRederedWidth(View view, Context context)
{
    var metrics = GetDisplayMetrics();
    var deviceWidth = metrics.WidthPixels;
    var deviceHeight = metrics.HeightPixels;
    int widthMeasureSpec = View.MeasureSpec.MakeMeasureSpec(deviceWidth, MeasureSpecMode.AtMost);
    int heightMeasureSpec = View.MeasureSpec.MakeMeasureSpec(deviceHeight, MeasureSpecMode.AtMost);
    view.Measure(widthMeasureSpec, heightMeasureSpec);
    return view.MeasuredWidth;
}

Here, we pass the view we want to render, and the context of the view, in all cases I’ve used this, this would be the activity context. Once inside the block, we call GetDisplayMetrics(), which is the method I shared previously, and we get the device width and height. From there, we call the views MakeMeasureSpec to get the width and height measure spec, and we specify MeasureSpecMode.AtMost to identify that we are allowing the view to be as large as it wants to be, up to the specified width, in this case, the device width. We do the same for the height and pass the measure specs to the views measure method. From there, we get a MeasuredWidth that we can use.

Determining the pre-rendered height

The code to get the height, not surprisingly, is almost identical:

public static int GetPreRederedHeight(View view, Context context)
{
    var metrics = GetDisplayMetrics();
    var deviceWidth = metrics.WidthPixels;
    var deviceHeight = metrics.HeightPixels;
    int widthMeasureSpec = View.MeasureSpec.MakeMeasureSpec(deviceWidth, MeasureSpecMode.AtMost);
    int heightMeasureSpec = View.MeasureSpec.MakeMeasureSpec(deviceHeight, MeasureSpecMode.AtMost);
    view.Measure(widthMeasureSpec, heightMeasureSpec);
    return view.MeasuredHeight;
}

So the only difference here, is we return the views MeasureHeight property.

Conclusion

And there you have it, that’s how you get pre-rendered dimensions for views in Xamarin Android. Hopefully you found this helpful, let me know any thoughts, criticisms, etc. Thanks for reading, until next time.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s

Advertisements
Advertisements
%d bloggers like this: