简体   繁体   English

Xamarin Forms Layout创建重叠的视图

[英]Xamarin Forms Layout create overlapping views

I am trying to create an Autocomplete control in Xamarin.Forms , so far I have created a ContentView with following Xaml. 我试图在Xamarin.Forms创建一个自动完成控件,到目前为止,我已经使用以下Xaml创建了ContentView

<ContentView.Content>
        <AbsoluteLayout BackgroundColor="Red" x:Name="absLayout" HeightRequest="30">
            <Entry BackgroundColor="Green" x:Name="entryView" AbsoluteLayout.LayoutBounds="1,1,1,1" AbsoluteLayout.LayoutFlags="All" Focused="Handle_Focused" Unfocused="Handle_Unfocused"/>
            <ListView BackgroundColor="Blue" Margin="0,30,0,0" IsVisible="false" x:Name="listView" HeightRequest="200">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <TextCell Text="{Binding .}" />
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </AbsoluteLayout>
    </ContentView.Content>

This will be used on ContentPage , along with other Entry and Label controls. 这将与其他EntryLabel控件一起用于ContentPage

When someone clicks on Entry then, corresponding ListView must be shown to user just below the Entry , by overlapping other controls, instead of pushing down other controls below it. 当有人单击Entry ,必须通过重叠其他控件,而不是按下其下方的其他控件,向用户显示在Entry下方的相应ListView

I have achieved overlapping of controls, but not correctly. 我已经实现了控件的重叠,但是没有正确完成。 ListView does shows list to user but other controls overlap it. ListView确实向用户显示列表,但其他控件将其重叠。 ListView gets a lower Z-Index and other controls get higher Z-Index. ListView的Z-Index较低,其他控件的Z-Index较高。

Need help to fix this. 需要帮助解决此问题。

Edit 1- 编辑1-

Screens for what I want to achieve. 我想要实现的屏幕。 (This a Spinner control in Android) (这是Android中的Spinner控件) 单击控件之前 单击控件后 I want to do something similar with my control. 我想对我的控件做类似的事情。

PS - follow this SO answer for root cause this behaviour. PS-请遵循 SO答案,以找出造成此问题的根本原因。

I had the exact same problem and I fixed it using a custom renderer. 我遇到了完全相同的问题,并使用自定义渲染器进行了修复。 This lets the user type to filter the list choices and then puts the selected choice in the entry when the user picks one. 这样,用户可以键入内容以过滤列表选项,然后在用户选择一个选项时将所选选项放在条目中。 In your forms project you'll want a new subclass of entry: 在表单项目中,您需要一个新的条目子类:

public class AutofillTextView : Entry
{
    public static BindableProperty ChoicesSourceProperty = BindableProperty.Create(
            nameof(ChoicesSource), typeof(ObservableCollection<string>), typeof(CustomPicker), 
            default(ObservableCollection<string>), propertyChanged: OnChoicesSourceChanged);

    public ObservableCollection<string> ChoicesSource
    {
        get { return (ObservableCollection<string>)GetValue(ChoicesSourceProperty); }
        set { SetValue(ChoicesSourceProperty, value); }
    }
    public AutofillTextView()
    {
        Items = new List<string>();
    }

    private void ChoicesChanged(object sender, NotifyCollectionChangedEventArgs args)
    {
        switch (args.Action)
        {
            case NotifyCollectionChangedAction.Add:
                Items.Add(args.NewItems[0]);
                break;

            default:
                var itemsList = ChoicesSource.ToList();
                Items = itemsList;
                break;
        }
        OnPropertyChanged(nameof(Items));
    }

    private static void OnChoicesSourceChanged(BindableObject bindable, object oldValue, object newValue)
    {
        var textView = (AutofillTextView) bindable;
        textView.ChoicesSource.CollectionChanged -= textView.ChoicesChanged;
        textView.ChoicesSource.CollectionChanged += textView.ChoicesChanged;
        textView.Items = newValue == null ? new List<string>() : ((ObservableCollection<string>)newValue).ToList();
    }
}

You might need to expand on this, but I never remove items from the list so the switch was good enough for me. 您可能需要对此进行扩展,但是我从不从列表中删除任何项目,因此切换对我来说已经足够好了。 I needed to use observable collection as well, so you can simplify by switching to list. 我还需要使用可观察的集合,因此您可以通过切换到列表来简化操作。 Anyway, next you need your custom renderer in droid: 无论如何,接下来您需要在droid中使用自定义渲染器:

[assembly: ExportRenderer(typeof(AutofillTextView), typeof(AutofillTextViewRenderer))]

namespace Default
{
    public class AutofillTextViewRenderer : ViewRenderer<AutofillTextView, InstantAutoCompleteTextView>
    {
        protected override void OnElementChanged(ElementChangedEventArgs<AutofillTextView> e)
        {
            base.OnElementChanged(e);

            if (Control == null)
            {
                var control = new InstantAutoCompleteTextView(Forms.Context);

                control.InputType = Android.Text.InputTypes.ClassText | Android.Text.InputTypes.TextFlagNoSuggestions;
                control.Text = Element.Text;
                SetNativeControl(control);
            }

            if (e.OldElement != null)
            {

            }

            if (e.NewElement != null)
            {
                var adapter = new ArrayAdapter<string>(Forms.Context as Android.App.Activity, Resource.Layout.AutofillTextViewItem, e.NewElement.Items.ToArray<string>());
                Control.Adapter = adapter;
                Control.Threshold = 0;
                Control.TextChanged += Control_TextChanged;
                adapter.NotifyDataSetChanged();
            }
        }

        void Control_TextChanged(object sender, Android.Text.TextChangedEventArgs e)
        {
            if (Element.Text != Control.Text)
            {
                Element.Text = Control.Text;
            }
        }

        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);
            if (e.PropertyName == AutofillTextView.ItemsProperty.PropertyName)
            {
                var adapter = new ArrayAdapter<string>(Forms.Context as Android.App.Activity, Resource.Layout.AutofillTextViewItem, Element.Items.ToArray<string>());
                Control.Adapter = adapter;
                adapter.NotifyDataSetChanged();
            } 
            else if(e.PropertyName == AutofillTextView.TextProperty.PropertyName)
            {
                if(Control.Text != Element.Text)
                {
                    Control.Text = Element.Text;
                }
            } else if(e.PropertyName == AutofillTextView.IsFocusedProperty.PropertyName) {
                if(Element.IsFocused)
                    Control.PerformFiltering();
            }
        }


    }
}

This will connect your custom class (AutofillTextView) to an android class (InstantAutoCompleteTextView) to replace the default entry renderer. 这会将您的自定义类(AutofillTextView)连接到android类(InstantAutoCompleteTextView),以替换默认条目渲染器。 The reason I don't use the built in AutoCompleteTextView is because it won't show the dropdown until you type at least one character. 我不使用内置的AutoCompleteTextView的原因是,在您键入至少一个字符之前,它不会显示下拉菜单。 I'd prefer it shown on focus. 我希望重点显示。 If you don't care you can skip that. 如果您不在乎,则可以跳过。 Here's that view: 这是视图:

public class InstantAutoCompleteTextView : AutoCompleteTextView 
{

    public InstantAutoCompleteTextView(Context context) : base(context) {}

    public InstantAutoCompleteTextView(Context arg0, IAttributeSet arg1) : base(arg0, arg1){}

    public InstantAutoCompleteTextView(Context arg0, IAttributeSet arg1, int arg2) : base(arg0, arg1, arg2){}

    public override bool EnoughToFilter() {
        return true;
    }

    public void PerformFiltering()
    {
        PerformFiltering(Text, 0);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM