Search code examples
android-recyclerviewxamarin.androidandroid-alertdialog

displaying alert dialog in the correct location within a recyclerview


I'm making a custom button that when you long press on it a dialog will appear with a list of options to choose from.

The custom button works as it should, however, I'm having some trouble wrangling the dialog to show up exactly where I want it to.

this is the code that displays the dialog.

private void ShowReactionsDialog()
{
    var context = Context;
    var inflater = (LayoutInflater) context.GetSystemService(Context.LayoutInflaterService);
    var dialogView = inflater.Inflate(Resource.Layout.react_dialog_layout, null);
    var linearLayoutManager = new LinearLayoutManager(context)
    {
        Orientation = LinearLayoutManager.Horizontal
    };
    var adapter = new ReactionAdapter(_reactionList);

    adapter.OnItemClicked += (sender, currentReaction) =>
    {
        UpdateReactButtonByReaction(currentReaction);

        _reactAlertDialog.Cancel();
    };

    var rvReactions = dialogView.FindViewById<RecyclerView>(Resource.Id.reaction_rvReactions);

    rvReactions.HasFixedSize = true;
    rvReactions.SetLayoutManager(linearLayoutManager);
    rvReactions.SetItemAnimator(new DefaultItemAnimator());
    rvReactions.SetAdapter(adapter);

    var dialogBuilder = new AlertDialog.Builder(context);
    dialogBuilder.SetView(dialogView);

    _reactAlertDialog = dialogBuilder.Create();
    _reactAlertDialog.RequestWindowFeature((int)WindowFeatures.NoTitle);

    var window = _reactAlertDialog.Window;
    window.SetBackgroundDrawableResource(Resource.Drawable.react_dialog_shape);
    window.SetDimAmount(0);

    // Setup dialog gravity and dynamic position
    var windowManagerAttributes = window.Attributes;
    windowManagerAttributes.Gravity = GravityFlags.AxisSpecified;
    windowManagerAttributes.X = (int) GetX() + (Width / 2);
    windowManagerAttributes.Y = (int) GetY() + (Height / 2);

    _reactAlertDialog.Show();

    var dialogWidth = GetIconSize() * _reactionList.Count;

    if (dialogWidth > GetScreenMaxWidth())
    {
        dialogWidth = GetScreenMaxWidth();
    }

    window.SetLayout(dialogWidth, ViewGroup.LayoutParams.WrapContent);
}

I've tried messing with the gravity and the X & Y coordinates but it just wants to either go too high up or too low down, there's no consistent location it's sticking to. I want it to be above the button that's getting long tapped.


Solution

  • You can use the following code to make the AlertDialog show above the button.

    int[] location = new int[2];
    AndroidX.AppCompat.App.AlertDialog alertDialog = builder.Create();
    Window window = alertDialog.Window;
    WindowManagerLayoutParams attributes = window.Attributes;
    //Get the location of the button and location[0] is X and location[1] is Y
    button.GetLocationInWindow(location);
    //Set the height of the AlertDialog
    int height = 400;
    int a = button.Height / 2;
    int c = location[1];
    //Get the distance of top
    attributes.Y = c - a - height;
    window.Attributes = attributes;
    //Set the AlertDialog location according to the distance of top
    window.SetGravity(GravityFlags.Top);
    alertDialog.Show();
    //Set the Width and Hight of the AlertDialog
    alertDialog.Window.SetLayout(800, height);