Xamarin.Android 在 C# Visual Studio 中:多个微调器使用同一个适配器?

Xamarin.Android in C# Visual Studio: Multiple Spinners using the very same adapter?

我有一个布局,我想多次膨胀到 Alertdialog。我有一个列表来保存膨胀的视图,我从 Resources/values/Strings.xml 中定义的资源创建了一个 Adapter。 这是Strings.xml的相关部分:

<string name="day_prompt">Choose a day</string>
<string-array name="days_array">
  <item>Monday</item>
  <item>Tuesday</item>
  <item>Wednesday</item>
  <item>Thursday</item>
  <item>Friday</item>
  <item>Saturday</item>
  <item>Sunday</item>
</string-array>

下面是用于创建适配器和列表的代码:

//create a list to hold Views
List<View> chooseElements = new List<View>();
//create a new adapter to be fed with data defined in vals/Strings
var adapter = ArrayAdapter.CreateFromResource(this, Resource.Array.days_array, Android.Resource.Layout.SimpleSpinnerItem);
//set its source to prev mentioned 
                adapter.SetDropDownViewResource(Android.Resource.Layout.SimpleSpinnerDropDownItem);
for (int i = 0; i < numberOfDays; i++)
    {
         //creating a custom number of elements
         SetUpItems(Resource.Id.dayPicker, Resource.Layout.ChoosingDay, alertHolder, adapter, chooseElements);  
    }

我想在列表中的实际(最新)ViewGroup 元素中找到 Spinner 元素的 ID,我设法做到了。但是,我的问题是,我只能设置首先创建的 Spinner 的适配器,所有其他元素似乎都没有附加适配器,好像 一个适配器 可以仅用于 一个 元素。 这是相关代码:

void SetUpItems(int idOfSpinner, int idOfElement, View alertDialogHolder, ArrayAdapter ad, List<View> list)
    {
        list.Add(LayoutInflater.Inflate(idOfElement, alertDialogHolder.FindViewById<LinearLayout>(Resource.Id.mainHolder)));
        #region Spinner
        Spinner spinner = new Spinner(this);
        //spinner  = alertDialogHolder.FindViewById<Spinner>(idOfSpinner);
        spinner = list[list.Count - 1].FindViewById<Spinner>(idOfSpinner);
        spinner.ItemSelected += new EventHandler<AdapterView.ItemSelectedEventArgs>(Spinner_ItemSelected);
        //var adapter = ArrayAdapter.CreateFromResource(this, Resource.Array.days_array, Android.Resource.Layout.SimpleSpinnerItem);
        //adapter.SetDropDownViewResource(Android.Resource.Layout.SimpleSpinnerDropDownItem);
        spinner.Adapter = ad;
        #endregion
    }

我是 Xamarin 的新手,所以我真的不知道如何使用同一个适配器处理多个 Spinners(或者如果它真的可能的话)。我尝试了很多解决方案都无济于事,而且我找不到任何有关使用同一适配器处理多个 Spinner 的资源。有人可以给我一些建议吗?

以防以后有人遇到同样的问题,我找到了解决办法。它不是很干净,但是可以用。抱歉,我不是一个非常有经验的开发人员。

主要问题似乎出在以下代码上:

 spinner = list[list.Count - 1].FindViewById<Spinner>(idOfSpinner);

这本身没有问题,但如果您还想将 FindViewById 找到的视图分配给其他元素,您将面临问题,因为 所有生成的元素都将具有相同的 ID。出于某种原因,这不算是错误(甚至不是警告),因此您的程序将通过始终返回列表中具有请求 ID 的第一个元素来编译和解决问题。实际上,这意味着在像我这样的程序中,相同的第一个元素将被一遍又一遍地重新定义,而其他元素将被忽略。

如果您以编程方式为您的元素分配一个新 ID,则可以解决该问题。在我的代码中,我使用了列表,以便我可以访问每个元素以便将来将数据传输到另一个 activity,但我想这样做是可能的 w/o 它,这是分配新的唯一元素的关键元素编号.

list.Add(LayoutInflater.Inflate(idOfElement, alertDialogHolder.FindViewById<LinearLayout>(Resource.Id.mainHolder)));

//creating a temp list for spinners
List<Spinner> spinners = new List<Spinner>();

//adding a new element
spinners.Add(new Spinner(this));

//capturing the current element, this way, I dont have to re-call it every time
int currentElement = spinners.Count - 1;

//assign a new lineear layout from another list
spinners[currentElement] = list[list.Count - 1].FindViewById<Spinner>(idOfSpinner);

//IMPORTANT: generate a new UNIQUE id 
spinners[currentElement].Id = View.GenerateViewId();

//subscribe to the event
spinners[currentElement].ItemSelected += new EventHandler<AdapterView.ItemSelectedEventArgs>(Spinner_ItemSelected);

//set the adapter
spinners[currentElement].Adapter = ad;

你为什么不使用 ActionSheet?按照此操作link,您将找到所需的解决方案。

看看代码示例

using Android.Widget;
using Android.OS;
using Xamarin.ActionSheet;
using Android.Support.V4.App;
using System.Collections.Generic;
using Android.App;

namespace ActionSheetTest
{
    [Activity (Label = "ActionSheetTest", MainLauncher = true, Icon = "@mipmap/icon")]
    public class MainActivity : FragmentActivity,ActionSheet.IActionSheetListener
    {
    protected override void OnCreate (Bundle savedInstanceState)
    {
        base.OnCreate (savedInstanceState);

        // Set our view from the "main" layout resource
        SetContentView (Resource.Layout.Main);

        // Get our button from the layout resource,
        // and attach an event to it
        Button button = FindViewById<Button> (Resource.Id.myButton);

        button.Click += delegate {
            var actionSheet = new ActionSheet ();
            actionSheet.Other_Button_Title = new List<string> (){ "Option1", "Option2" };
            actionSheet.SetActionSheetListener (this);
            actionSheet.Show (SupportFragmentManager);
        };
    }

    public void onDismiss (ActionSheet actionSheet, bool isCancel)
    {
        System.Console.WriteLine ("onDismiss");
    }

    public void onOtherButtonClick (ActionSheet actionSheet, int index)
    {
        System.Console.WriteLine (index);
    }
}
}