android - GridView Adapter.getView() 未正确设置选定状态

标签 android button gridview adapter selected

我有一个 GridView,我正在用 ArrayAdapter 的自定义子类填充它。该适配器返回我自定义为可选择的按钮(参见 Android ImageButton with a selected state? )。到目前为止,这是有效的,单击按钮可以选择它们(在选择器背景下可见)。

问题是:我无法从一开始就将这些按钮设置为选中状态。当我第一次启动 View 时,它们只是显示为未选中。

我创建了一个简单的测试项目来说明问题:

package com.example.buttonselection;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.GridView;

public class MainActivity extends Activity {

    public class SelectButtonAdapter extends ArrayAdapter<String> {

        public SelectButtonAdapter(Context context) {
            super(context, 0);
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            String name = getItem(position);

            View rowView = convertView;
            if (rowView == null || !(rowView instanceof Button)) {
                rowView = new Button(getContext());
                ((Button)rowView).setOnClickListener(new OnClickListener() {
                    public void onClick(View button) {
                        if (button.isSelected()){
                            button.setSelected(false);
                        } else {
                            button.setSelected(true);
                        }
                    }
                });
            }

            Button button = (Button)rowView;
            button.setText(name);
            button.setBackgroundResource(R.drawable.button_selection);

            button.setSelected(true); // this does not work

            return button;
        }
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        GridView grid = (GridView)findViewById(R.id.gridview);

        SelectButtonAdapter adapter = new SelectButtonAdapter(this);
        adapter.add("One");
        adapter.add("Two");
        adapter.add("Three");
        grid.setAdapter(adapter);
    }
}

因此,我什至无法恢复使用 onSaveInstanceState 保存的按钮的状态。我该如何解决或解决这个问题?

我很感激任何帮助!

编辑:这是我的 button_selection.xml,虽然这应该没问题,因为稍后选择按钮可以正常工作。

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:state_pressed="true">
        <shape>

            <solid android:color="@color/bet_button_pressed" />

            <stroke
                android:width="2dip"
                android:color="@color/white" />

        </shape>
    </item>

    <item android:state_selected="true">
        <shape>

            <solid android:color="@color/bet_button_selected" />

            <stroke
                android:width="2dip"
                android:color="@color/white" />

        </shape>
    </item>

        <item>
        <shape>

            <gradient
                android:angle="90"
                android:startColor="@color/bet_button_dark_green"
                android:endColor="@color/bet_button_light_green"
                android:centerX="0.5"
                android:centerY="0.5" />

            <stroke
                android:width="2dip"
                android:color="@color/white" />

        </shape>
    </item>
</selector>

最佳答案

好吧,我找到了解决此错误的方法。我只是在外部存储一个按钮被选中的天气,并覆盖按钮的 ondraw-method 以在每次绘制时设置正确的状态。这具有额外的优势,即可以更轻松地保留选择。

这里是解决方法(只是一个简单的概念证明,我的生产代码更复杂):

package com.example.buttonselection;

import java.util.HashSet;
import java.util.Set;

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.GridView;

public class MainActivity extends Activity {

    public class SelectButtonAdapter extends ArrayAdapter<String> {

        public SelectButtonAdapter(Context context) {
            super(context, 0);
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            String name = getItem(position);

            View rowView = convertView;
            if (rowView == null || !(rowView instanceof Button)) {
                rowView = new Button(getContext()) {
                    @Override
                    protected void onDraw(Canvas canvas) {
                        setSelected(selectedButtons.contains(getText()));
                        super.onDraw(canvas);
                    }
                };
                ((Button)rowView).setOnClickListener(new OnClickListener() {
                    public void onClick(View button) {
                        String text = ((Button)button).getText().toString();

                        if(selectedButtons.contains(text)) {
                            selectedButtons.remove(text);
                        } else {
                            selectedButtons.add(text);
                        }
                        button.invalidate();
                    }
                });
            }

            Button button = (Button)rowView;
            button.setText(name);
            button.setBackgroundResource(R.drawable.button_selection);

            return button;
        }

    }
    private Set<String> selectedButtons = new HashSet<String>();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        GridView grid = (GridView)findViewById(R.id.gridview);

        SelectButtonAdapter adapter = new SelectButtonAdapter(this);
        adapter.add("One");
        adapter.add("Two");
        adapter.add("Three");
        grid.setAdapter(adapter);

        // this selects the first button from the start
        selectedButtons.add("One");
    }

}

旁注: 有人会认为,4.1 版 API 不会包含如此明显的错误。浪费在这上面的时间令人沮丧,并且没有动力为这个系统开发更多。

关于android - GridView Adapter.getView() 未正确设置选定状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12545302/

相关文章:

html - 如何将按钮代码从 HTML 转换为 HAML?

Android Facebook SDK SSO Logcat "Failed to find provider info for com.facebook.katana.provider.AttributionIdProvider"

android - 在 eclipse (android) 中更改附加源

java - Android 服务、上下文、构建器

HTML/CSS 试图调整按钮的大小,使它们的大小都相同

ios - 将 "Delete"按钮添加到 UITableViewCell

android - GridView 右侧的未知空间

c# - 使用 Entity Framework 从数据库加载图像到 gridview

android - FingerprintManagerCompat isHardwareDetected 在 targetAPI 25 中返回 false

c# - 无法从 Gridview 获取值