Mvvmcross: How to "hook into" and do some post processing after a call to BindingInflate?

Created on 4 May 2017  Â·  10Comments  Â·  Source: MvvmCross/MvvmCross

Hi,

I'm trying to replace certain View values (colors, etc), the best place to do this would be after a layout has been inflated. Since I don't control all the calls that inflate layouts I was thinking about "hooking into" BindingInflate/MvxLayoutInflater and do some post processing.

I tried creating my own MvxContextWrapper and MvxLayoutInflater, and instantiate the MvxContextWrapper in .AttachBaseContext, but when debugging I was never able to get any hits in the MvxLayoutInflater.Inflate override method.

I did get hits in the MvxContextWrapper.GetSystemService method (yes I returned "my" MvxLayoutInflater).

Maybe I missed something...

Before I try and attack the problem again, is there a better/easier/recommended way of doing post processing after BindingLayout has been called?

All 10 comments

Don't do that.

What I would do instead is provide your own implementation of IMvxLayoutInflaterHolderFactoryFactory that returns a custom IMvxLayoutInflaterHolderFactory (inherited from MvxBindingLayoutInflaterFactory) from the Create method. Your custom IMvxLayoutInflaterHolderFactory.BindCreatedView can then call the base class to bind the view after which you can do your custom stuff.

https://github.com/MvvmCross/MvvmCross/blob/bcecb75dbce1914a96b82ab5e501acaa08729f11/MvvmCross/Binding/Droid/Views/MvxLayoutInflater.cs#L50 is where the BindCreatedView gets called.

You can register for that IMvxLayoutInflaterHolderFactoryFactory in your app setup by creating a new MvxAndroidBindingBuilder and overriding CreateLayoutInflaterFactoryFactory to return your custom class. Return your special MvxAndroidBindingBuilder from your setup's CreateBindingBuilder()

```csharp
public class Setup : ...
{
protected override MvxBindingBuilder CreateBindingBuilder()
{
return new MyMvxAndroidBindingBuilder();
}

public MyMvxAndroidBindingBuilder : MvxAndroidBindingBuilder
{
    protected virtual IMvxLayoutInflaterHolderFactoryFactory CreateLayoutInflaterFactoryFactory()
    {
        return new MyMvxLayoutInflaterFactoryFactory();
    }
}

public MyMvxLayoutInflaterFactoryFactory : IMvxLayoutInflaterHolderFactoryFactory
{
    public IMvxLayoutInflaterHolderFactory Create(object bindingSource)
    {
        return new MyMvxBindingLayoutInflaterFactory(bindingSource);
    }
}

public MyMvxBindingLayoutInflaterFactory : MvxBindingLayoutInflaterFactory
{
     public override View BindCreatedView(View view, Context context, IAttributeSet attrs)
    {
        base.BindCreatedView(view, context, attrs);
        if (view != null)
       {
       // Do whatever ...
        }
        return view;
    }
}

}

Excellent, thank you! 😄

I'd like to reopen this @kjeremy

It appears that the BindCreatedView is not always called. For example when I'm creating a AlertDialog it doesn't call BindCreatedView, it does however use the MvxLayoutInflater.

I think it would be better to do post-processing by overriding the MvxLayoutInflater.Inflate method.

Where should I do the wrapping of the MvxLayoutInflater. Maybe by overriding the GetSystemService in my BaseActivity or do you have another recommended way of doing this?

Can you elaborate on: it doesn't always get called? What gets missed?

On May 9, 2017 5:54 AM, "Mikael Nensén" notifications@github.com wrote:

I'd like to reopen this @kjeremy https://github.com/kjeremy

It appears that the BindCreatedView is not always called. For example when
I'm creating a AlertDialog it doesn't call BindCreatedView, it does however
use the MvxLayoutInflater.

I think it would be better to do post-processing by overriding the
MvxLayoutInflater.Inflate method.

Where should I do the wrapping of the MvxLayoutInflater. Maybe by
overriding the GetSystemService in my BaseActivity or do you have another
recommended way of doing this?

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/MvvmCross/MvvmCross/issues/1769#issuecomment-300117557,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AEIBRDF6p6JjwQEHphAgOS5WVRMCLZ2Hks5r4DfegaJpZM4NQpY1
.

MyMvxBindingLayoutInflaterFactory.BindCreatedView does not get called when I create and show a dialog with similar code as below:
var dialog = new Android.Support.V7.App.AlertDialog.Builder(this).SetTitle(title).SetPositiveButton(...).Create(); dialog.Show();

I know the AlertDialog.Builder uses the MvxLayoutInflater because I did a check regarding what gets returned from the current Activity's GetSystemService.

Right. In the case of alert dialog builder the UI is built dynamically. In
order for our code to execute you need to pass in a view resource.

On May 9, 2017 6:23 AM, "Mikael Nensén" notifications@github.com wrote:

MyMvxBindingLayoutInflaterFactory.BindCreatedView does not get called
when I create and show a dialog with similar code as below (:
var dialog = new Android.Support.V7.App.AlertDialog.Builder(this).
SetTitle(title).SetPositiveButton(...).Create(); dialog.Show();

I know the AlertDialog.Builder uses the MvxLayoutInflater because I did a
check regarding what gets returned from the current Activity's
GetSystemService.

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/MvvmCross/MvvmCross/issues/1769#issuecomment-300123610,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AEIBREAR-7ERXxWpSG58yvqaiLrcFrVlks5r4D6qgaJpZM4NQpY1
.

OK. My goal is to intercept any view inflation, that's why I'm thinking about wrapping the MvxLayoutInflater and override Inflate.

So going back to my previous question, would overriding GetSytemService in my own BaseActivity suffice, and then return a MyMvxLayoutInflater that inherits from MvxLayoutInflater, or is there a better/safer way?

I think you misunderstood me. In the case of AlertDialog.Builder the framework generates the view in java so you cannot intercept it. Now if you are manually inflating views then what I said above should visit every view.

It is incredibly frustrating that Android does not provide this ability out of the box and that's why MvxLayoutInflater was created.

Was this page helpful?
0 / 5 - 0 ratings