如何在ListView中更新某些不可见项目的视图? [Android的]

时间:2016-08-12 13:59:13

标签: android listview dialog

社会! 我需要帮助更新ListView中的不可见项。它不是项目内容,而是项目的视图表示。 好的,让我告诉你我的例子。我有一个字符串数组:

<string-array name="reminder_notifications">
    <item>15 minutes before</item>
    <item>30 minutes before</item>
    <item>1 hour before</item>
    <item>1.5 hour before</item>
    <item>5 hours before</item>
    <item>8 hours before</item>
    <item>1 day before</item>
</string-array>

在Activity中我创建了适配器:

adapterNotifications = ArrayAdapter.createFromResource(this, R.array.reminder_notifications, R.layout.dialog_list_multiple_choise);

之后,我用一些方法计算出来自字符串数组的whitch项目可用于当前提醒。例如。如果用户在16:00设置16:45的提醒,则他只能选择项15 minutes before30 minutes before。其他项目应禁用。 所以,谷歌之后我发现了如何在某个位置访问隐形ListView孩子:

public View getViewByPosition(int position, ListView listView) {
    final int firstListItemPosition = listView.getFirstVisiblePosition();
    final int lastListItemPosition = firstListItemPosition + listView.getChildCount() - 1;
    if (position < firstListItemPosition || position > lastListItemPosition ) {
        return listView.getAdapter().getView(position, listView.getChildAt(position), listView);
    } else {
        final int childIndex = position - firstListItemPosition;
        return listView.getChildAt(childIndex);
    }
}

现在,我正面临着最后一个问题(我希望) - 如何更新我从上面的方法获得的项目视图?我试着用这个:

View v = getViewByPosition(position, lvNotifications);
v.setEnabled(true);

但它只在第一次打开对话框后更新View,另外一个词我必须用ListView打开对话框窗口,关闭它并重新打开。只有在这种情况下,我才会得到更新的视图。 我知道,我的英文很糟糕所以下面有截图:

主对话框。在使用ListView打开对话框之前 Main dialog. Before opening the dialog with ListView

列表视图对话框。首先开放。没有项目被禁用。错误 List view dialog. First opening. No items are disabled. WRONG

列表视图对话框。第二次开放。 5项禁用。对 List view dialog. Second opening. 5 items are disabled. RIGHT

谢谢。

1 个答案:

答案 0 :(得分:1)

你从错误的一面解决了这个问题。您不应该从适配器外部编辑视图,这是适配器的用途。相反,编写自己的适配器。这样做:

import android.content.Context;
import android.support.annotation.NonNull;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.TextView;

/**
 * A {@link ArrayAdapter} to let the user select multiple notification times.
 */
public class ReminderNotificationsAdapter extends BaseAdapter implements CompoundButton.OnCheckedChangeListener {

    /**
     * A array with all currently selected entries
     */
    private boolean[] mSelected;

    /**
     * A array with all enabled entries
     */
    private boolean[] mEnabled;

    /**
     * The items to be shown
     */
    private String[] mItems;

    /**
     * A {@link Context}
     */
    private Context mContext;

    /**
     * Creates a new instance
     *
     * @param context a {@link Context}
     * @param items all selectable items
     * @param checkedItems all selected items. This array will be updated with the users selectiion
     * @param enabledItems all enabled items
     */
    public ReminderNotificationsAdapter(Context context, String[] items, boolean[] checkedItems, boolean[] enabledItems) {
        // Check array sizes
        if(items.length != checkedItems.length || checkedItems.length != enabledItems.length) {
            throw new RuntimeException("All arrays must be the same size");
        }

        // Add all and store params
        this.mContext = context;
        this.mItems = items;
        this.mSelected = checkedItems;
        this.mEnabled = enabledItems;

    }

    @Override
    public int getCount() {
        return this.mItems.length;

    }

    @Override
    public String getItem(int i) {
        return this.mItems[i];

    }

    @Override
    public long getItemId(int i) {
        return this.getItem(i).hashCode();

    }

    @NonNull
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View v = convertView;

        // Create view if not provided to convert
        if(v == null) {
            v = LayoutInflater.from(this.mContext).inflate(R.layout.dialog_list_multiple_choise, parent, false);
        }

        // Prepare text view
        TextView tv = (TextView) v.findViewById(android.R.id.text1);
        tv.setText(this.getItem(position));
        tv.setEnabled(this.isEnabled(position));

        // Prepare checkbox
        CheckBox cb = (CheckBox) v.findViewById(android.R.id.checkbox);
        cb.setTag(position);
        cb.setChecked(this.mSelected[position]);
        cb.setEnabled(this.isEnabled(position));
        cb.setOnCheckedChangeListener(this);

        // Return view
        return v;

    }

    @Override
    public boolean isEnabled(int position) {
        return this.mEnabled[position];

    }

    @Override
    public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
        this.mSelected[(Integer) compoundButton.getTag()] = b;

    }
}

并像这样使用它:

@Override
public void onClick(View view) {
    // Tell what string should be shown
    String[] entries = this.getResources().getStringArray(R.array.reminder_notifications);

    // Tell what entries should be already selected
    final boolean[] selectedEntries = new boolean[entries.length];
    selectedEntries[2] = true;

    // Tell what entries should be enabled
    boolean[] enabledEntries = new boolean[entries.length];
    enabledEntries[0] = true;
    enabledEntries[1] = true;
    enabledEntries[2] = true;
    enabledEntries[3] = true;

    // Create the adapter
    ReminderNotificationsAdapter a = new ReminderNotificationsAdapter(this, entries, selectedEntries, enabledEntries);

    // Create and show the dialog
    new AlertDialog.Builder(this)
            .setTitle("Add notification")
            .setAdapter(a, null)
            .setPositiveButton("Set", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialogInterface, int i) {
                    // Do what you want to do with the selected entries
                    Toast.makeText(MainActivity.this, Arrays.toString(selectedEntries), Toast.LENGTH_SHORT).show();

                }
            })
            .setNegativeButton("Dismiss", null)
            .show();

}

我只是使用一个布尔数组来告诉应该启用和选择哪些条目,如果你愿意,可以在那里做一些更优雅的事情。在提供给适配器构造函数的数组中更新用户的选择。 AlertDialog看起来像这样:

Screenshot

请参阅完整的示例应用here