(Android GridView)当我回收convertView时,第一项的CheckBox不起作用

时间:2013-12-01 13:08:54

标签: android gridview android-inflate

我删除了项目中的几乎所有代码,以找到隐藏的bug。有一个包含框架布局的GridView,并且布局包含CheckBox。 但是我无法检查第一个复选框。(其他人工作)

最后(我想)我找到了答案。但这太奇怪了。当我删除回收convertView的行时,错误消失了。我改变了:

        if(convertView == null) {
            layout = (FrameLayout)View.inflate(maincon, R.layout.taste_brand, null);
        } else {
            layout = (FrameLayout) convertView;
        }

FrameLayout layout = (FrameLayout)View.inflate(maincon, R.layout.taste_brand, null);

我真的不知道这种情况。我附上了休息代码。

TasteGridAdapter.java:

public class TasteGridAdapter extends BaseAdapter {

    Context maincon;

    public TasteGridAdapter(Context context) {
        maincon = context;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        FrameLayout layout;

        if(convertView == null) {
            layout = (FrameLayout)View.inflate(maincon, R.layout.taste_brand, null);
        } else {
            layout = (FrameLayout) convertView;
        }

        layout.setLayoutParams(new GridView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT));

        return layout;
    }

    @Override
    public int getCount() {
        return 3;
    }

    @Override
    public Object getItem(int position) {
        return position;
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

}

onCreate of the activity:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.taste);

    TasteGridAdapter adapter = new TasteGridAdapter(this);
    GridView grid = (GridView) findViewById(R.id.taste_grid);
    grid.setAdapter(adapter);
}

taste.xml:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <GridView
        android:layout_weight="1"
        android:id="@+id/taste_grid"
        android:layout_width="match_parent"
        android:layout_height="0dip"
        android:columnWidth="87dip"
        android:gravity="center"
        android:horizontalSpacing="4dip"
        android:numColumns="auto_fit"
        android:padding="2dip"
        android:stretchMode="columnWidth"
        android:verticalSpacing="4dip" />
</LinearLayout>

taste_brand.xml:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="87dp"
    android:layout_height="58dp">
    <CheckBox
        android:id="@+id/taste_brand_check"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />

</FrameLayout>

4 个答案:

答案 0 :(得分:4)

我遇到了GridView中第一个项目的类似问题。要解决问题,请删除“新”关键字,然后更改现有的视图LayoutParams:

LayoutParams lp = layout.getLayoutParams();
lp.height = someHeight;

...对这些LayoutParams做点什么。这个黑客解决了我的问题。结论,尽量避免通过“new”创建新的LayoutParams对象。

答案 1 :(得分:3)

layout.setLayoutParams(new GridView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT));

将此行置于此状态

if(convertView == null){

}

我遇到了同样的问题,但我尝试了这个,它的工作对我来说。我希望它也适合你。

答案 2 :(得分:1)

您遇到的问题与Android在ListViewGridView等中回收视图的方式有关。您提到您的第一个复选框无法检查,而其他复选框仍然有效。我想你会注意到其他人只有出现才能正常工作,因为你没有正确处理回收。

你的行

的原因
FrameLayout layout = (FrameLayout)View.inflate(maincon, R.layout.taste_brand, null);

似乎解决了这个问题,因为现在每次使用时都会再次膨胀视图。我承认,当我开始这样做时,重新膨胀视图似乎是最好的解决方案;然而,它完全违背了回收的目的,并且你失去了获得的所有性能优势。

现在来解决你的问题:

首先,我强烈建议您将ViewHolder模式与BaseAdapter结合使用。有关详细信息,请参见here

其次,您应该创建一个布尔数组来匹配GridView中的所有项目,并使用它来确定是否应该单击某个项目。在复选框侦听器中设置相应布尔值的值,并在getView(..)中使用该值来选中或取消选中该特定框。

总体上更好的解决方案可能是在适配器类中使用模型的数组(或列表),每个模型都包含可通过isCheckedsetChecked(boolean)访问的布尔字段。同样,您可以在getView(..)内使用此功能来正确显示视图并更改复选框OnCheckedChangeListener中的值。

希望有所帮助。

答案 3 :(得分:0)

正如jonstaff所说,这与View回收有关。

如果您正在为GridView View绑定使用自定义Adapter类,请尝试修改其getView()方法以始终实例化 new 视图,如:

public View getView(int position, View convertView, ViewGroup parent){
    SomeView v = new SomeView(context); // <--- here
    ...
    return v;
}

相反典型的:

public View getView(int position, View convertView, ViewGroup parent){
    SomeView v;
    if (convertView == null)
        v = new SomeView (context);
    else
        v= (SomeView)convertView;
    ...
    return v;
}

这可能会影响性能,但它解决了一个小型GridView按钮的问题。