动态设置Spinner的选择项,不触发OnItemSelectedListener事件。

5
我是一名有用的助手,能够翻译文本。

我有一个活动,其中有许多级联的微调器。在选择第一个微调器后,第二个微调器会初始化并填充数据,然后在从第二个微调器选择项目后,第三个微调器会初始化并填充数据,依此类推。

对于每个微调器,我都像这样创建它们,并且是迭代的:

public ArrayList<MaterialSpinner> spinnerlist = new ArrayList<>();

public void createView(){
 final MaterialSpinner spinner = new MaterialSpinner(context);
        spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener(){//...after select item next spinner creates with calling createView() iteratively}
        loadSpinnerData(); // set adapter and more
        spinnerlist.add(spinner);
}   

当用户选择时,一切都正常,但是当我使用setSelection(positionOfItem)进行动态设置时,不幸的是,spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener()没有被调用。我不知道为什么会发生这种情况。
   for (int i = 0; i < some_value; i++) {

            int positionOfItem = get_proper_position;
            spinnerList.get(i).setSelection(positionOfItem); //this not trigger onItemSelect!
        }

问题出在这里。第一次旋转器大小为1,但在设置选择后,监听器不调用,第二个旋转器也不创建。
我还以为这是因为时间消耗行动,所以尝试使用可运行的和发布一些延迟,但它没有起作用。

我假设您在初始化setOnItemSelectedListner之前进行了setSelection。它应该始终调用setOnItemSelectedListner。请检查该场景并分享您的代码。 - Miral Bhalani
@MiralBhalani 我更新了问题。第一个 spinner 已经被创建、初始化并添加到列表中,但是它的选择操作不起作用。 - Mahdi
请尝试将loadSpinnerData();移动到spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener()之前。 - Miral Bhalani
@MiralBhalani 它没有起作用。 - Mahdi
1
只有在选择与上一个不同的新项目时,onItemSelecteListner才会被调用。 每次选择项目时,即使它相同,OnItemClicklistner也会被调用。因此,请检查一下loadSpinnerData()中是否默认选择了任何项目。 - Miral Bhalani
显示剩余3条评论
2个回答

2

我终于找到了一个可怕的解决方案。问题似乎出在需要一些时间来创建项目和视图的Android系统上。 当我调用第一个下拉菜单的onClickListener时,它应该创建第二个下拉菜单并填充数据,这是一个耗时的操作。所以我不得不为每个项目设置延迟,并使用可变间隔:

for (int i = 0; i < some_value; i++) {
            selectItemOfSpinner(i);
        }


private void selectItemOfSpinner(final int i) {

    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            MaterialSpinner spinner = spinnerList.get(i);
            int positionOfItem = get_proper_position;
            spinner.setSelection(positionOfItem, true);
        }
    }, 50*i);

}

这解决了我的问题,所有的旋转器都被创建并填充得很好。但在一些慢速设备上,延迟时间应该增加,这就是我说的可怕方式。我正在努力解决这个问题,如果我找到更好的方法,我会更新解决方案。

1
不要使用postDelayed,而是使用post。这将推迟运行内部的代码执行,直到布局绘制完成。没有必要设置任意时间来延迟执行。 - Vlad

0

我认为你想要实现的目标可以通过 performItemClick 实现。

for (int i = 0; i < some_value; i++) {

        int positionOfItem = get_proper_position;
        MaterialSpinner spinner = spinnerList.get(i);
        spinner.setSelection(positionOfItem);

        View itemView = (View)spinner.getChildAt(positionOfItem);
        long itemId = your_spinner.getAdapter().getItemId(positionOfItem);

        spinner.performItemClick(itemView, positionOfItem, itemId);
} 

setSelection 方法不会触发 OnItemSelectedListener,但是 performItemClick 方法会。


我会检查并通知您。 - Mahdi
(View)spinner.getChildAt(positionOfItem); 返回null - Mahdi
int positionOfItem = get_proper_position; 这段代码返回的是什么? - fluffyBatman
它是int positionOfItem = spinnerList.get(i).getPositionOfItem(categoryListNames.get(i).getName()); 它正常工作,因为我的第一个下拉框正确填充和选择,但必须执行点击操作 :( - Mahdi
所以,如果我理解正确的话,你的 positionOfItem 和循环计数器 i 在技术上是相同的值,对吗? - fluffyBatman
不要,getPositionOfItem() 去查找我想知道的名称的位置。因此,在 spinner 选择该项之后。i 是计数器,用于计算 spinner 的大小和类别。我认为最好留下这部分因为它可以正常工作,并且我已经在调试模式下进行了双重检查并返回正确的值。 - Mahdi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接