【问题标题】:Android Gridview and getChildAt with NullPointerException带有 NullPointerException 的 Android Gridview 和 getChildAt
【发布时间】:2011-11-07 23:33:38
【问题描述】:

我有一个 UI,其中包含一个加载了自定义适配器的 Gridview。 ButtonAdapter,在这种情况下。所以网格加载正常,按钮点击功能就像我想要的那样,但现在我必须在按钮上指出它是“活动”选择。

我想我会通过跟踪和更改背景来做到这一点。事实证明,根据 SO 上的几篇文章,按钮在屏幕外时实际上并不存在……甚至在滚动之后也是如此。在滚动后尝试更改按钮背景时,我经常会收到 NullPointerException。

我尝试将适配器中的视图更改为 RadioButtons 和 ToggleButtons,但它们都提供了类似的限制。

问题似乎主要与我在网格上使用 getChildAt() 来“取消选择”一个按钮或其他按钮有关,当另一个按钮被选中时。

是否有解决此问题的方法,或者可能有其他类似功能的建议。一种可垂直滚动的、类似网格的格式等...

感谢您的帮助。

编辑: 谢谢 Craigy...我确实忘记在上面放一个平台 o.0...我会添加 android。

【问题讨论】:

  • 你的按钮点击功能在哪里?在适配器的getView中还是在GridView的onItemClickListener中?

标签: android gridview button nullpointerexception adapter


【解决方案1】:

您是否考虑过使用Selector?在不知道 buttonAdapter 的工作原理或从中拉取它的情况下,您可以使用选择器将任何 View 的背景可绘制对象设置为根据其状态进行更改。

如果您的选择器是这样定义的(当然,假设存在适当的可绘制对象):

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
    <item android:state_focused="true"
          android:drawable="@drawable/list_item_pressed" />
    <item android:state_pressed="true"
          android:drawable="@drawable/list_item_pressed" />
    <item android:state_selected="true"
          android:state_activated="true"
          android:drawable="@drawable/list_item_selected" />
    <item android:state_activated="true"
          android:drawable="@drawable/list_item_selected" />
    <item android:state_selected="true"
          android:drawable="@android:color/black" />
    <item android:drawable="@android:color/transparent" />
</selector>

然后将你的 GridView 的选择模式设置为单选:

<GridView
   ...
   android:choiceMode="singleChoice" />

这让操作系统为您处理所有事情,例如记住在列表中选择了哪个位置,然后在您单击另一个位置时为您清除它

【讨论】:

  • 我正在为按钮使用状态列表。没想到这个已激活的业务。但是在尝试它时,它似乎不像 mGridView.setActivated(false);做任何事。什么都没有清除。
  • 是的,该应用程序支持低于 11 的 API。我实际上虽然我们在那里有一些东西。还是谢谢。
  • 好吧,如果你再次在蜂窝+附近,清除它的实际方法调用是 dispatchSetActivated()。不过,您可能仍然可以使用 setSelected() 调用执行我上面描述的操作,所以我还不会放弃。
  • 该应用支持 API 9 及更高版本。这个想法似乎最有潜力,但我无法让它“清除”一切。谢谢。
  • 您可以使用 setSelected,就像我说的那样...不过,我还没有亲自尝试过,所以可能有一些我不知道的怪癖。但是是的 dispatchSetSelected(false) 应该在所有视图的孩子上调用 setSelected(false)
【解决方案2】:

在适配器在 getView() 中创建的每个视图上设置一个标签。稍后通过 gridView.findViewByTag() 搜索带有该标签的视图或通过 view.getTag() 获取视图的标签。

【讨论】:

  • 不,这有同样的问题,因为在将当前按钮更改为“单击”颜色之前,我必须找到上一个单击的按钮以将其更改回“未单击”颜色。而且我仍然会得到 NullPointers 有时会与上一个按钮交互。不过还是谢谢。
  • 一个previous可以返回null,如果它被滚动屏幕并且已经被回收。所以只要我检查空值,这对我来说就是一个很好的解决方案。
【解决方案3】:

好吧,这可能无法完美回答您的问题,但我已经做了类似的事情。基本上,我将项目添加到表中,并且需要有一个与项目关联的删除按钮。单击删除按钮时,它只需要从表中删除该项目。这可以根据您的需要进行调整,而不是删除单击的项目,它会找到上一个项目,取消单击它,然后突出显示然后新单击的项目。

所以我所做的是给按钮本身一个标签(显然它们需要是唯一的)。单击按钮时,将其标记保存在 sharedPreference 之类的内容中以供以后参考。然后,当单击新按钮时,只需找到具有先前单击标记的按钮并取消标记它所在的行,然后为新单击的按钮标记该行。这是我使用的代码(对不起,变量名很糟糕,我实际上在一个从未发布过的测试应用程序中工作过,所以我没有费心给他们更好的名字):

        //Previous button clicked
        String id = <get this from wherever you choose to store it>
        // create a new TableRow
        TableRow row = new TableRow(getApplicationContext());

        TextView t = new TextView(getApplicationContext());
        t.setTextColor(Color.BLACK);
        t.setText(unique);

        Button b = new Button(getApplicationContext());
        b.setOnClickListener(new Button.OnClickListener() {

            public void onClick(View v) 
            { 
                for(int i = 0; i < table.getChildCount(); i++)
                {          
                    TableRow row = (TableRow) table.getChildAt(i);                        
                    Button bt = (Button) row.getChildAt(1);
                    TextView view  = (TextView)row.getChildAt(0);

                    if( id.equals(v.getTag())) //they match, so this is the button that was previously clicked
                    {
                        //Put your code here to unclick the previous button and mark the new one as clicked.                            

                    }
                }  
            }
        });   

        b.setText(R.string.removeButtonText);
        b.setTag(t.getText().toString());

        /***BE SURE TO SAVE THE NEW BUTTON TAG (t.getText().toString()) SOMEWHERE LIKE A SHARED PREFERENCE****/
        //saving the tag

        //add the row to the table                
        row.addView(t);
        row.addView(b);        
        // add the TableRow to the TableLayout
        table.addView(row,new TableLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));

同样,我不怀疑这是您正在寻找的确切答案,但也许它会给您一个尝试的想法。希望这是有道理的,如果没有,请随时要求澄清。对不起,如果它也离基地很远。

【讨论】:

  • 其实这个很像下面的第一个回复。我已经尝试了这些标签,但有时视图仍然存在 NullPointer 问题。就像要“取消选择”的那个不在屏幕上或通过各种按钮单击太快等。不过,谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-04
  • 2018-06-21
相关资源
最近更新 更多