首页 文章

Xamarin表单布局创建重叠视图

提问于
浏览
1

我试图在 Xamarin.Forms 中创建一个 Autocomplete 控件,到目前为止,我已经创建了一个跟随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>

这将在 ContentPage 上与其他 EntryLabel 控件一起使用 .

当有人点击 Entry 时,相应的 ListView 必须通过重叠其他控件而显示在 Entry 正下方的用户,而不是按下它下面的其他控件 .

我已实现控件的重叠,但不正确 . ListView确实向用户显示列表,但其他控件重叠它 . ListView获得较低的Z-Index,其他控件获得更高的Z-Index .

需要帮助来解决这个问题 .

Edit 1-

筛选我想要实现的目标 . (这是Android中的Spinner控件)
Before clicking control

After clicking control
我想用我的控件做类似的事情 .

PS - 关注this SO回答根本导致此行为 .

1 回答

  • 0

    我有完全相同的问题,我使用自定义渲染器修复它 . 这允许用户键入以过滤列表选项,然后在用户选择一个时将所选选项放入条目中 . 在您的表单项目中,您将需要一个新的条目子类:

    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();
        }
    }
    

    您可能需要对此进行扩展,但我从不从列表中删除项目,因此切换对我来说已经足够了 . 我也需要使用可观察的集合,因此您可以通过切换到列表来简化 . 无论如何,接下来你需要在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();
                }
            }
    
    
        }
    }
    

    这会将您的自定义类(AutofillTextView)连接到Android类(InstantAutoCompleteTextView)以替换默认的条目渲染器 . 我不使用内置AutoCompleteTextView的原因是因为在您键入至少一个字符之前它不会显示下拉列表 . 我更喜欢它在焦点上显示 . 如果你不在乎你可以跳过它 . 这是该观点:

    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);
        }
    }
    

相关问题