2012-05-18 34 views
4

我有一个自定义ListView点击一个项目触发一个新的ActivityListView的每一行都有一个CheckBox和一个TextView可以调用onCheckedChanged方法而不进行交互吗?

这是getView方法从我的自定义ListView

public View getView(int position, View convertView, ViewGroup parent) { 
     View v = convertView; 
     if (v == null) { 
      LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
      v = vi.inflate(R.layout.puzzles_row, null); 
     } 
     ListedPuzzle lp = items.get(position); 
     if (lp != null) { 
      TextView title = (TextView) v.findViewById(R.id.listTitles); 
      title.setText(lp.getTitle()); 
      CheckBox star = (CheckBox) v.findViewById(R.id.star_listed); 
      star.setChecked(lp.isStarred()); 
      star.setTag(new Integer(position)); 

      star.setOnCheckedChangeListener(new OnCheckedChangeListener() { 

       public void onCheckedChanged(CompoundButton buttonView, 
         boolean isChecked) { 
        Integer realPosition = (Integer) buttonView.getTag(); 
        ListedPuzzle obj = items.get(realPosition); 
        starListedPuzzle(obj.getId(), isChecked); 
       } 
      }); 

     } 
     return v; 

    } 

onCheckedChanged到来时从另一个Activty回来,没有可能的用户交互来实际检查任何被调用。

问题是过去工作正常,没有真正改变任何事情。我有read这是一个错误,但不能真正相信它。

它始终调用ListView的相同两项中的方法。莫名其妙地设置为checkedChange=true

回答

9

我有一种感觉,它发生在onRestoreInstanceState方法。当Android暂停和恢复时,Android会自动处理恢复活动中大多数View的状态。恢复时,它听起来像是恢复您的CheckBox对象的检查状态,这触发了onCheckedChanged。尝试在Activity这样做,让我知道,如果这能解决你的问题:

private boolean mRestoringInstanceState; 

@Override 
protected void onRestoreInstanceState(Bundle savedInstanceState) { 

    mRestoringInstanceState = true; 
    super.onRestoreInstanceState(savedInstanceState); 
    mRestoringInstanceState = false; 
} 

然后改变你的onCheckChanged方法,像这样:

public void onCheckedChanged(CompoundButton buttonView, 
     boolean isChecked) { 

    if(!mRestoringInstanceState) { 
     Integer realPosition = (Integer) buttonView.getTag(); 
     ListedPuzzle obj = items.get(realPosition); 
     starListedPuzzle(obj.getId(), isChecked); 
    } 
} 

编辑:可能是一个更好/更容易的解决办法是分配onResume方法中的侦听器,因为它在onRestoreInstanceState之后被调用。请注意,你不会,如果使用此解决方案实现上述任何一项:

@Override 
protected void onResume() { 

    super.onResume(); 
    CheckBox star = (CheckBox) v.findViewById(R.id.star_listed); 
    star.setOnCheckedChangeListener(new OnCheckedChangeListener() { 

     public void onCheckedChanged(CompoundButton buttonView, 
       boolean isChecked) { 
      // onCheckedChanged implementation 
     } 
    }); 
} 

EDIT2:刚刚意识到你在Adapter这样做。这可能与onRestoreInstanceState没有关系,但我认为我看到了问题。您在Adapter中重复使用View,这很好,但您在设置侦听器之前将star设置为检查。问题是star已经有一个从上次通过getView方法来的侦听器。在致电star.setChecked()之前,请致电star.setOnCheckedChangedListener(null),看看是否可以解决您的问题。

+0

你是绝对正确的!但是,现在,点击我的CheckBox并没有做任何事情。 – eskalera

+0

它应该在'super.onRestoreInstanceState'完成执行后将'mRestoringInstanceState'设置回'false'。 –

+0

此外,您还可以将'star.setOnCheckedChangeListener ...'行移至'onResume'方法,因为这会在'onRestoreInstanceState'后调用。在这种情况下,你不需要实现'onRestoreInstanceState'。我将编辑我的答案以显示此选项。 –

6

我遇到了这个问题以及使用自定义适配器。

我发现检查,如果该按钮被示解决了这个问题:

OnCheckedChangeListener ccl = new OnCheckedChangeListener() 
{ 
    @Override 
    public void onCheckedChanged(CompoundButton buttonView, 
      boolean isChecked) { 

     if(buttonView.isShown()) 
     { 

     } 
    } 
}; 
+0

工程,但不是更正确。 – delive

+0

我认为这是一个很好的解决方案,因为系统在自身恢复状态时调用OnCheckedChangedListener显然不是99%的开发人员想要的。值得一提的是,ViewCompat.isLaidOut(buttonView)也适用于此目的,并且不会严格遵守可见性。 –

1

检查堆栈跟踪听者

public void onCheckedChanged(CompoundButton buttonView, isChecked) { 
    <breakpoint here> 
} 

如果在堆栈跟踪看到onRestoreInstanceState()可以在布局中使用这样的:

<CheckBox 
... 
android:saveEnabled="false" /> 

...这里建议: Android CheckBox -- Restoring State After Screen Rotation

如果你看到star.setChecked()是一个在堆栈跟踪从你getView()叫那么就由star.setOnCheckedChangedListener(null)star.setChecked()(再之前删除监听器可以监听重置为您做)。像杰森罗宾逊建议。

+0

不适用于适配器。 – delive

+0

救了我一天:)虽然我没有在适配器中使用它。 – SohailAziz

2

它可以在你的onRestoreInstanceState片段中被称为

您可以禁用与

android:saveEnabled="false" 

上的复选框的布局定义

+0

这是一个非常恼人的问题的最佳解决方案。如果onCheckedChanged()被意外调用,请尝试此操作。 – Whome

相关问题