扩大布局后更改TextView的文本

时间:2018-10-12 18:10:01

标签: java android

我有一个布局default_label.xml,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/label"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

然后,我有了这个类,基本上可以让我为微调器设置默认按钮文本:

public class NothingSelectedSpinnerAdapter implements SpinnerAdapter, ListAdapter {

    protected static final int EXTRA = 1;
    protected SpinnerAdapter adapter;
    protected Context context;
    protected int nothingSelectedLayout;
    protected int nothingSelectedDropdownLayout;
    protected LayoutInflater layoutInflater;
    protected TextView label;

    /**
     * Use this constructor to have NO 'Select One...' item, instead use
     * the standard prompt or nothing at all.
     *
     * @param spinnerAdapter        wrapped Adapter.
     * @param nothingSelectedLayout layout for nothing selected, perhaps
     *                              you want text grayed out like a prompt...
     * @param context               Context
     */
    public NothingSelectedSpinnerAdapter(
            SpinnerAdapter spinnerAdapter,
            int nothingSelectedLayout, Context context) {

        this(spinnerAdapter, nothingSelectedLayout, -1, context);
    }

    /**
     * Use this constructor to Define your 'Select One...' layout as the first
     * row in the returned choices.
     * If you do this, you probably don't want a prompt on your spinner or it'll
     * have two 'Select' rows.
     *
     * @param spinnerAdapter                wrapped Adapter. Should probably return false for isEnabled(0)
     * @param nothingSelectedLayout         layout for nothing selected, perhaps you want
     *                                      text grayed out like a prompt...
     * @param nothingSelectedDropdownLayout layout for your 'Select an Item...' in
     *                                      the dropdown.
     * @param context                       Context
     */
    public NothingSelectedSpinnerAdapter(SpinnerAdapter spinnerAdapter,
                                         int nothingSelectedLayout, int nothingSelectedDropdownLayout, Context context) {
        this.adapter = spinnerAdapter;
        this.context = context;
        this.nothingSelectedLayout = nothingSelectedLayout;
        this.nothingSelectedDropdownLayout = nothingSelectedDropdownLayout;
        layoutInflater = LayoutInflater.from(context);
    }

    @Override
    public final View getView(int position, View convertView, ViewGroup parent) {
        // This provides the View for the Selected Item in the Spinner, not
        // the dropdown (unless dropdownView is not set).
        if (position == 0) {
            return getNothingSelectedView(parent);
        }
        return adapter.getView(position - EXTRA, null, parent); // Could re-use
        // the convertView if possible.
    }

    public int getPosition(String value) {
        int index = 0;
        for (int i = 1; i < getCount() + EXTRA; i++) {
            if (getItem(i).equals(value)) {
                index = i;
                break;
            }
        }
        return index;
    }


    public TextView getNothingSelectedView(ViewGroup parent) {
        label = (TextView) layoutInflater.inflate(nothingSelectedLayout, parent, false);
        return label;
    }

    @Override
    public View getDropDownView(int position, View convertView, ViewGroup parent) {
        // Android BUG! http://code.google.com/p/android/issues/detail?id=17128 -
        // Spinner does not support multiple view types
        if (position == 0) {
            return new View(context);
        }
        if (adapter.getItem(position-EXTRA).toString().equals("")){
            View view = nothingSelectedDropdownLayout == -1 ?
                    new View(context) :
                    getNothingSelectedDropdownView(parent);
            view.setEnabled(false);
            view.setOnClickListener(null);
            return view;
        }

        // Could re-use the convertView if possible, use setTag...
        return adapter.getDropDownView(position - EXTRA, null, parent);
    }

    protected View getNothingSelectedDropdownView(ViewGroup parent) {
        return layoutInflater.inflate(nothingSelectedDropdownLayout, parent, false);
    }

    @Override
    public int getCount() {
        int count = adapter.getCount();
        return count == 0 ? 0 : count + EXTRA;
    }

    @Override
    public Object getItem(int position) {
        return position == 0 ? null : adapter.getItem(position - EXTRA);
    }

    @Override
    public int getItemViewType(int position) {
        return 0;
    }

    @Override
    public int getViewTypeCount() {
        return 1;
    }

    @Override
    public long getItemId(int position) {
        return position >= EXTRA ? adapter.getItemId(position - EXTRA) : position - EXTRA;
    }

    @Override
    public boolean hasStableIds() {
        return adapter.hasStableIds();
    }

    @Override
    public boolean isEmpty() {
        return adapter.isEmpty();
    }

    @Override
    public void registerDataSetObserver(DataSetObserver observer) {
        adapter.registerDataSetObserver(observer);
    }

    @Override
    public void unregisterDataSetObserver(DataSetObserver observer) {
        adapter.unregisterDataSetObserver(observer);
    }

    @Override
    public boolean areAllItemsEnabled() {
        return false;
    }

    @Override
    public boolean isEnabled(int position) {
        return position != 0; // Don't allow the 'nothing selected'
        // item to be picked.
    }

}

我想做的就是更改TextView的文本,例如:

NothingSelectedSpinnerAdapter myAdapter = new NothingSelectedSpinnerAdapter(adapter, R.layout.default_label, getContext());
myAdapter.setText("Custom Label");
mySpinner.setAdapter(myAdapter);

但是,当我尝试将以下方法添加到上述NothingSelectedSpinnerAdapter类中时:

public void setText(String text) {
    label.setText(text);
}

我收到以下错误:

  

java.lang.NullPointerException:尝试调用虚拟方法'void   android.widget.TextView.setText(java.lang.CharSequence)'上的null   对象引用

我应该改变什么?

1 个答案:

答案 0 :(得分:0)

看看以下三行:

  

NothingSelectedSpinnerAdapter myAdapter = new NothingSelectedSpinnerAdapter(adapter, R.layout.default_label, getContext());

实例化适配器,标签null

  

myAdapter.setText("Custom Label");

TextView 标签仍为null,这就是label.setText();导致NullPointerException

的原因
  

mySpinner.setAdapter(myAdapter);

现在,运行时将能够绘制Spinner项目。这涉及到重复调用getView()(对于应该绘制的每个项目至少调用一次)。为getView()执行position = 0之后,您将为 label 分配一个值。从现在开始,您可以安全地致电setText()

如果您希望随时可以调用myAdapter.setText("Custom Label");而不用担心适配器的内部工作,那么可以引入一个字段private String mLabelText并实现以下方法

public void setText(String labelText){
    mLabelText = labelText;
    if (label != null){
        label.setText(labelText);
    }
}

最后一步:别忘了在初始化 label

后立即设置文本
public TextView getNothingSelectedView(ViewGroup parent) {
    label = (TextView) layoutInflater.inflate(nothingSelectedLayout, parent, false);
    label.setText(mLabelText);
    return label;
}