Unity: динамически обновлять выпадающий список при открытии, не теряя фокус на InputField - PullRequest
1 голос
/ 04 апреля 2019

Я создаю Dropdown с панелью поиска вверху. По сути, я положил Inputfield поверх Dropdown.

Когда вы нажимаете Inputfield, открывается Dropdown, а когда вы что-то вводите в него, Dropdown должен динамически обновлять свой список.

Вот проблема, с которой я столкнулся, в инспекторе изменяется опция Dropdown, однако список сцены не обновляется.

Когда я делаю Dropdown.Hide(), а затем Dropdown.Show(), он обновляется, но затем я теряю фокус на Inputfield. Я всегда могу просто сделать Inputfield.Select(), но тогда весь Inputfield будет выделен, и вам нужно щелкнуть позицию, в которой вы находились, чтобы иметь возможность редактировать с того места, где вы были.

Есть предложения?

Редактировать Вот код ниже. Я вынул все неважные вещи, чтобы сделать его максимально тонким, чтобы показать здесь

public class SearchbarInput : InputField
    {
        private GameObject[] m_Ordnance;
        private Dropdown m_Dropdown;
        private SearchbarInput m_InputField;

        // Needed for basic inputfield functionality
        private List<string> m_OrdnanceNames = new List<string>(); // Used to display our data

        protected override void Start()
        {
            m_Ordnance = GetComponent<OrdnanceSelector>().m_Ordnance;

            // Get necessary components
            m_Dropdown = GetComponentInParent<Dropdown>();
            m_InputField = GetComponent<SearchbarInput>();
            m_InputField.gameObject.GetComponentInChildren<Text>().text = "Click here to select Ordnance";

            // Set InputField onValueChange listener
            m_InputField.onValueChanged.AddListener(OnInputValueChanged);

            // Add each ordnance name to our string list
            foreach (GameObject ordnance in m_Ordnance)
            {
                if (ordnance != null) m_OrdnanceNames.Add(ordnance.name);
            }
            if (m_OrdnanceNames.Count == 0) DisplayError("Ordnance were not added");
            else
            {
                ChangeDropdownOptions(m_OrdnanceNames);
                m_Dropdown.onValueChanged.AddListener((index) => OnDropdownItemClicked(index));
            }

            base.Start();
        }

        // When the InputField is selected
        public override void OnSelect(BaseEventData eventData)
        {
            base.OnSelect(eventData);
            Debug.Log("SearchbarInput selected");

            Dropdown parentDropdown = GetComponentInParent<Dropdown>();
            parentDropdown.Show();
        }

        // When the InputField is deselected
        public override void OnDeselect(BaseEventData eventData)
        {
            base.OnDeselect(eventData);
            Debug.Log("SearchbarInput deselected");
        }

        /// Displays items in list that are similar to what the user typed in the Input Field
        private void OnInputValueChanged(string typedText)
        {
            List<string> results = GetResults(typedText);
            ChangeDropdownOptions(results);
        }

        /// Get list of items that contains characters similar to input
        private List<string> GetResults(string input)
        {
            return m_OrdnanceNames.FindAll((str) => str.IndexOf(input) >= 0);
        }

        ///============================== Dropdown Methods===================================
        /// Called when the dropdown menu is clicked. Is set inside of scripts Start function
        public void OnDropdownItemClicked(int index)
        {
            // Get selected ordnance name
            string ordnanceName = m_Dropdown.options[index].text;
            m_InputField.text = ordnanceName;

            // Change AndyGenerator Prefab
            int indexOfOrdnance = m_OrdnanceNames.IndexOf(ordnanceName);
            //m_AndyScript.AndyPrefab = m_Ordnance[indexOfOrdnance]; <- Took out for StackOverflow to make as short as possible
        }

        /// Clears the dropdown options and add's options set inside of the list
        private void ChangeDropdownOptions(List<string> options)
        {
            m_Dropdown.ClearOptions();
            m_Dropdown.AddOptions(options);
        }

        ///============================== Error Method===================================
        /// Displays error inside of our InputField.
        private void DisplayError(string errorText)
        {
            Debug.Log("Searchbar.cs: " + errorText);
            // Decided to make it more obvious since this is absolutely needed and
            // it saves the headache of looking for an error
            m_InputField.text = "Error: " + errorText;
        }
    }
...