【问题标题】:How to update certain View of invisible item in ListView? [Android]如何更新 ListView 中不可见项的某些视图? [安卓]
【发布时间】:2016-08-12 13:59:12
【问题描述】:

社区! 我需要帮助更新 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);

之后,我通过一些方法从字符串数组中计算出哪些项目可用于当前提醒。例如。如果用户在 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);

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

主对话框。在使用 ListView 打开对话框之前

列表视图对话框。第一次开幕。没有项目被禁用。错误的

列表视图对话框。二开。 5 个项目被禁用。对

谢谢。

【问题讨论】:

    标签: android listview dialog


    【解决方案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 如下所示:

    查看完整的示例应用 here

    【讨论】:

    • 伙计,你真是太棒了。谢谢!非常感谢您的解释!请告诉我 CheckedTextView 或 TextView + CheckBox 哪个更好?
    • CheckedTextView 旨在与 ListView 和 setMultipleChoiceItems(...) 和 setSingleChoiceItems(...) 一起使用,而不是像我的解决方案中那样单独使用或作为普通视图使用。使用 TextView 和 RelativeLayout,如果做得好,这也支持 RTL 布局并且没有视觉差异。请参阅我在答案末尾链接的 GitHub 存储库中使用的布局。我对我的解决方案做了一些细微的改动(用 BaseAdapter 替换了 ArrayAdapter,更改了一些填充)
    猜你喜欢
    • 2015-06-13
    • 1970-01-01
    • 2023-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-25
    相关资源
    最近更新 更多