为什么 ListView 中的 imageButton 在滚动之前不会切换?

Why imageButton in a ListView does not toggle untill scrolled?

我通过自定义适配器有一个简单的 listView。列表视图中的每一行都由一个 ImageButton 和 TextView 组成。

想法是在用户点击它时更改 ImageButton,但它不起作用。但是,对于滚动和回收的视图,ImageButton 会发生变化。我的意思是,当用户向下滚动列表并返回顶部并点击 ImageButton 时,对于那些滚动并再次返回的行,它会按预期工作。

你们能帮我解决我所缺少的吗?我对 Android 非常陌生,并且已经被困在这个问题上大约一个星期了,现在试图解决这个问题。

以下是示例测试应用的 APK: https://www.dropbox.com/s/pzlahtqkgj010m8/app-ListViewExample.apk?dl=0 以下是我的代码的相关部分:

avtivity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">


    <ListView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/listView"

        />
</RelativeLayout>

为了在 ListView 中呈现单行,使用了以下 xml:

single_row.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal" android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginTop="20dp"
    android:layout_marginBottom="20dp"
    >


    <ImageButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/imageButton"
        android:src="@drawable/b"
        android:layout_weight="2"
        style="@style/ListView.first"
        android:layout_gravity="center"
        />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="Large Text"
        android:id="@+id/textView"
        android:layout_weight="10"
        android:layout_gravity="center"
        />
</LinearLayout>

来到Java代码,

MainActivity.java 是

public class MainActivity extends AppCompatActivity {

    String[] titles;
    ListView list;
    private listViewAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Resources res = getResources();

        titles = res.getStringArray(R.array.titles);
        list = (ListView) findViewById(R.id.listView);
        adapter = new listViewAdapter(this, titles);
        list.setAdapter(adapter);
    }
}

自定义适配器 listViewAdapter.java 看起来像这样

class sListItem {
    public ImageButton button;
    public TextView text;
    public boolean active;
}

public class listViewAdapter extends ArrayAdapter<String> {

    private final String[] titles;
    Context context;

    private int size = 15;
    public sListItem mp[] = new sListItem[size];


    public listViewAdapter(Context context, String[] titles) {
        super(context, R.layout.single_row, R.id.imageButton, titles);
        this.context = context;
        this.titles = titles;

    }

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View row = inflater.inflate(R.layout.single_row, parent, false);

        if(mp[position] == null)
            mp[position] = new sListItem();

        mp[position].button = (ImageButton) row.findViewById(R.id.imageButton);
        mp[position].button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mp[position].active = !mp[position].active;

                setIcon(position, mp[position].active);
            }
        });

        mp[position].text = (TextView) row.findViewById(R.id.textView);
        mp[position].text.setText(titles[position]);
        setIcon(position, mp[position].active);

        return row;
    }


    private void setIcon(int position, boolean active) {
        Drawable drawable;

        if(active){
            drawable = getContext().getResources().getDrawable(R.drawable.a);
        } else {
            drawable = getContext().getResources().getDrawable(R.drawable.b);
        }
        mp[position].button.setImageDrawable(drawable);
    }
}

编辑: 添加 link 示例测试应用程序。

您应该通过在点击侦听器中调用 notifydatasetchanged 告诉适配器更新

 mp[position].button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mp[position].active = !mp[position].active;
                setIcon(position, mp[position].active);
                notifydatasetchanged();
            }
        });