android - 如何更新 ListView 中不可见项目的某些 View ? [安卓]

标签 android listview dialog

社区! 我需要帮助更新 ListView 中的不可见项。这与项目内容无关,而是项目的 View 表示。 好的,让我给你看我的例子。我有一个字符串数组:

<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);

之后,我使用一些方法计算出字符串数组中的哪些项目可用于当前提醒。例如。如果用户在 16:00 设置了 16:45 的提醒,那么他只能选择 15 分钟前30 分钟前 的项目。其他项目应该被禁用。 所以,在谷歌之后,我发现了如何在特定位置访问不可见的 ListView child :

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 ?我试着用这个:

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

但它只在第一次打开对话框后更新 View ,换句话说,我必须用 ListView 打开对话框窗口,关闭它并重新打开。只有在那种情况下,我才会获得更新的 View 。 我知道,我的英语很糟糕,所以下面有截图:

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

ListView 对话框。第一次开业。没有项目被禁用。错误的 List view dialog. First opening. No items are disabled. WRONG

ListView 对话框。二开。 5 项被禁用。正确的 List view dialog. Second opening. 5 items are disabled. RIGHT

谢谢。

最佳答案

您从错误的角度解决了这个问题。您不应该从适配器外部编辑 View ,这就是适配器的用途。相反,编写您自己的适配器。这样做:

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();

}

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

Screenshot

查看完整的示例应用 here .

关于android - 如何更新 ListView 中不可见项目的某些 View ? [安卓],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38919864/

相关文章:

android - 有谁知道如何让我的小部件打开带有输入框的对话框?

c# - 在 C# 中显示带有文本输入的对话框

android - 项目描述文件(.project)与文件系统不同步

android - Activity 转换 : OnActivityReenter: onPreDraw never called

android - Fragment不调用ListView的getView方法

Android ListView 一个项目中的多个图像

java - Android Listview Inside viewpager 始终显示所有页面中最后一个 viewpager 页面数组列表数据

c++ - 如何在MFC中设置对话框的默认大小(以像素为单位)

java - getArguments() 返回 null

android - 从 Android 和 iOS 中的相同代码库开发多个应用程序