【问题标题】:Xamarin Forms Layout create overlapping viewsXamarin 表单布局创建重叠视图
【发布时间】:2017-12-09 05:40:54
【问题描述】:

我正在尝试在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>

这将用于ContentPage,以及其他EntryLabel 控件。

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

我已经实现了控件的重叠,但不正确。 ListView 确实向用户显示列表,但其他控件与其重叠。 ListView 的 Z-Index 较低,而其他控件的 Z-Index 较高。

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

编辑 1-

筛选我想要实现的目标。 (这是 Android 中的 Spinner 控件) 我想用我的控件做类似的事情。

PS - 关注this SO 答案,找出这种行为的根本原因。

【问题讨论】:

  • 您能否添加您想要实现的结果的图像并解释必须重叠哪些其他控件?
  • @ganchito55 更新了我的问题以包含一些屏幕

标签: c# xamarin xamarin.forms absolutelayout


【解决方案1】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多