Android Spinner页脚

时间:2011-08-10 02:35:00

标签: android spinner footer

有没有办法在微调器下拉列表中添加页脚?例如,假设我正在从数据库中填充一个微调器,但我想在列表的底部进行选择,而不管我如何安排列表。列表可能是“Database Item 1,2 ...,3 ...”,并在列表底部选择“Add Item to Database”。

到目前为止,我已经使用了您的CustomSpinner类,如下所示:

public class CustomSpinner extends Spinner implements OnItemClickListener {

private AlertDialog myDialog = null;
private OnClickListener myButtonClickListener = null;
private GrainSpinnerAdapter adapter = null;

public CustomSpinner(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public void setButtonClickListener(OnClickListener listener) {
    myButtonClickListener = listener;
}

public void setAdapter(GrainSpinnerAdapter adapter){
    this.adapter = adapter;
}

@Override
public boolean performClick() {
    Context context = getContext();

    //Inflate the layout
    final LayoutInflater inflater = LayoutInflater.from(getContext());
    final View v = inflater.inflate(R.layout.my_custom_spinner, null);

    // set up list view
    final ListView lv = (ListView) v.findViewById(R.id.list);
    lv.setAdapter(adapter);
    lv.setSelection(getSelectedItemPosition());
    lv.setOnItemClickListener(this);

    // set up button
    final Button btn = (Button) v.findViewById(R.id.addButton);
    btn.setOnClickListener(myButtonClickListener);

    // build our dialog
    AlertDialog.Builder builder = new AlertDialog.Builder(context);

    // show prompt, just as our Spinner parent does
    if (getPrompt() != null) {
        builder.setTitle(getPrompt());
    }

    // create and show dialog
    myDialog = builder.setView(v).create();
    myDialog.show();

    return true;
}

@Override
public void onItemClick(AdapterView<?> view, View itemView, int position, long id) {
    setSelection(position);
    if (myDialog != null) {
        myDialog.dismiss();
        myDialog = null;
    }

}

} 我想使用一个单独的适配器,如:

public class GrainListAdapter extends SimpleCursorAdapter {

private static final String DEFAULT_UNITS = "American";
private Button upButton;
private Context myContext;
private RecipeGrainActivity parentActivity;
private Button downButton;
private String units;
private double getLbs;

public GrainListAdapter(Context context, int layout, Cursor c, String[] from, int[] to) {
    super(context, layout, c, from, to);
    myContext = context;
    parentActivity = (RecipeGrainActivity) myContext;

    //Checks for metric pref.
    SharedPreferences myPrefs = PreferenceManager.getDefaultSharedPreferences(context);
    units = String.valueOf(myPrefs.getString(context.getString(R.string.pref_measurement), DEFAULT_UNITS));
}

@Override
public void bindView(View view, Context context, Cursor cursor) {
    int idColumn = cursor.getColumnIndex("_id");
    final int getId = cursor.getInt(idColumn);
    final double increment = 0.25;

    UnitsConversions convert = new UnitsConversions();

    int nameColumn = cursor.getColumnIndex("name");
    String getName = cursor.getString(nameColumn);
    TextView name = (TextView)view.findViewById(R.id.GrainName);
    name.setText(getName);

    int originColumn = cursor.getColumnIndex("origin");
    String getOrigin = cursor.getString(originColumn);
    TextView origin = (TextView)view.findViewById(R.id.GrainOrigin);
    origin.setText(getOrigin);

    if(units.equals("Metric")){
        //Sets labels to metric.
        String kilos = context.getResources().getString (R.string.kilograms);
        TextView weightLabel = (TextView)view.findViewById(R.id.GrainLbsLabel);
        weightLabel.setText(kilos);
    }


}

@Override
public View newView(Context context, Cursor cursor, final ViewGroup parent) {
    View view = View.inflate(context, R.layout.grain_list_item, null);
    return view;
}

}

这允许我为微调器中的每个listitem构建一个自定义行。我想我可以使用我的活动中的customspinner.setadapter()将适配器设置为CustomSpinner。但是,CustomSpinner类中定义的ListView使用类中引用的适配器。如何将我的适配器传递给类,以便它可以使用它?

以下是我必须将自定义项添加到布局中的方法:

<com.bluelightuniverse.android.brewmobile.CustomSpinner
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/GrainNameSpinner"
    android:layout_toRightOf="@id/GrainOriginSpinner"
    android:layout_toLeftOf="@+id/AddGrainButton">
</com.bluelightuniverse.android.brewmobile.CustomSpinner>

3 个答案:

答案 0 :(得分:8)

在CursorAdapter中,覆盖方法getCount()和getDropDownView: 例如,如果要在结尾放置一个按钮,则可以执行以下操作:

new SimpleCursorAdapter(...) {

        @Override
        public int getCount() {
            return super.getCount()+1;
        }

        @Override
        public View getDropDownView(int position, View convertView,
                ViewGroup parent) {
            View res=null;
            if (position == getCount()-1) {
                //better not try to reuse our view as it can be requested for the spinner or by the list with different kind of layouts.
                View mButton= getActivity().getLayoutInflater().inflate(R.layout.create_activity_button, parent,false);
                mButton.setOnClickListener(ObservationListFragment.this);
                res= mButton;
            } else if (convertView != null && android.R.id.button1 == convertView.getId() ){
             // If the adapter is trying to recycle our footer view, we force the generation of a new view (check on the id of our custom view)
                res= super.getDropDownView(position, null, parent);
            } else {
                res= super.getDropDownView(position, convertView, parent);
            }
            return res;
        }
    };

答案 1 :(得分:0)

您可以使用MergeAdapter:这可以让您创建一个接收数据库适配器的适配器和一个静态视图(将项添加到数据库的按钮)并将其设置为Spinner视图。我已将此用于ListView s但不用于Spinner s,因此不确定它是否会起作用,但我认为它会。

答案 2 :(得分:0)

我一直在尝试在Spinners的对话框中制作更复杂的视图。

为了做你所解释的,我创建了Spinner的子类。我检查了Android Spinner的 source 并覆盖了performClick基本上按照您的意愿执行操作:使用自定义视图填充您自己的对话框。

package me.ribose.example; // you'll have to change this

import android.app.AlertDialog;
import android.content.Context;
import android.database.DataSetObserver;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.SpinnerAdapter;

public class CustomSpinner extends Spinner implements OnItemClickListener {
    private AlertDialog mDialog = null;
    private OnClickListener mButtonClickListener = null;

    public UnitSelectionSpinner(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public void setButtonClickListener(OnClickListener listener) {
        mButtonClickListener = listener;
    }

    @Override
    public boolean performClick() {
        Context context = getContext();

        // get the set adapter
        final DropDownAdapter adapter = new DropDownAdapter(getAdapter());

        // inflate our layout
        final LayoutInflater inflater = LayoutInflater.from(getContext());
        final View v = inflater.inflate(R.layout.customSpinner, null);

        // set up list view
        final ListView lv = (ListView) v.findViewById(R.id.list);
        lv.setAdapter(adapter);
        lv.setSelection(getSelectedItemPosition());
        lv.setOnItemClickListener(this);

        // set up button
        final Button btn = (Button) v.findViewById(R.id.addButton);
        btn.setOnClickListener(mButtonClickListener);

        // build our dialog
        AlertDialog.Builder builder = new AlertDialog.Builder(context);

        // show prompt, just as our Spinner parent does
        if (getPrompt() != null) {
            builder.setTitle(getPrompt());
        }

        // create and show dialog
        mDialog = builder.setView(v).create();
        mDialog.show();

        return true;
    }

    @Override
    public void onItemClick(AdapterView<?> view,
                            View itemView, int position, long id) {
        setSelection(position);
        if (mDialog != null) {
            mDialog.dismiss();
            mDialog = null;
        }
    }

    /**
     * <p>Wrapper class for an Adapter. Transforms the embedded Adapter instance
     * into a ListAdapter.</p>
     */
    private static class DropDownAdapter implements ListAdapter, SpinnerAdapter {
        private SpinnerAdapter mAdapter;

        /**
         * <p>Creates a new ListAddapter wrapper for the specified adapter.</p>
         *
         * @param adapter the Adapter to transform into a ListAdapter
         */
        public DropDownAdapter(SpinnerAdapter adapter) {
            this.mAdapter = adapter;
        }

        public int getCount() {
            return mAdapter == null ? 0 : mAdapter.getCount();
        }

        public Object getItem(int position) {
            return mAdapter == null ? null : mAdapter.getItem(position);
        }

        public long getItemId(int position) {
            return mAdapter == null ? -1 : mAdapter.getItemId(position);
        }

        public View getView(int position, View convertView, ViewGroup parent) {
            return getDropDownView(position, convertView, parent);
        }

        public View getDropDownView(int position, View convertView, ViewGroup parent) {
            return mAdapter == null ? null :
                    mAdapter.getDropDownView(position, convertView, parent);
        }

        public boolean hasStableIds() {
            return mAdapter != null && mAdapter.hasStableIds();
        }

        @Override
        public void registerDataSetObserver(DataSetObserver observer) {
            if (mAdapter != null) {
                mAdapter.registerDataSetObserver(observer);
            }
        }

        @Override
        public void unregisterDataSetObserver(DataSetObserver observer) {
            if (mAdapter != null) {
                mAdapter.unregisterDataSetObserver(observer);
            }
        }

        /**
         * <p>Always returns false.</p>
         *
         * @return false
         */
        public boolean areAllItemsEnabled() {
            return true;
        }

        /**
         * <p>Always returns false.</p>
         *
         * @return false
         */
        public boolean isEnabled(int position) {
            return true;
        }

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

        public int getViewTypeCount() {
            return 1;
        }

        public boolean isEmpty() {
            return getCount() == 0;
        }
    }
}

您需要我的customSpinner.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">
    <ListView
            android:id="@+id/list"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:layout_weight="1"
            android:layout_marginTop="5px"
            android:cacheColorHint="@null"
            android:background="@android:color/background_light"
            android:divider="@android:drawable/divider_horizontal_bright"
            android:scrollbars="vertical">
    </ListView>
    <Button
            android:id="@+id/addButton"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="Add to Database">
    </Button>
</LinearLayout>

当然,将android:text作为字符串资源。

更多的话:只需在您的活动布局中根据需要制作一个CustomSpinner并调用setButtonClickListener(可能在您设置适配器的位置附近)为您的按钮添加回调,也许提示用户添加或任何您需要的内容。当然,在添加到数据库后,适配器上有notifyDataSetChanged()。在Spinner上工作的所有东西都应该与这个自定义微调器完全相同。

旁注(更新):您必须确保适配器的列表项具有黑色文本(例如:android:textColor="@android:color/primary_text_light_nodisable")!我更改了上面的XML,因此它不需要项目的白色背景(然后使项目高亮不起作用)。


代码注释:由于制作Android的人决定不轻松自定义微调器对话框(使用AlertDialog.Builder使用setSingleChoiceItems()进行硬编码以及使用“转换”私有类SpinnerAdapterListAdapter s),我必须复制他们的整个内部类以获得所需的效果。另请注意,他们是糟糕的记录员(请参阅DropDownAdapterisEnabled / areAllItemsEnabled了解当天的笑声!)。