我想使用一个微调器,最初(当用户还没有做出选择时)显示文本“Select One”。当用户单击微调器时,将显示项目列表,用户可以选择其中一个选项。用户做出选择后,所选项目将显示在微调器中,而不是“Select One”。
我有以下代码来创建一个旋转器:
String[] items = new String[] {"One", "Two", "Three"};
Spinner spinner = (Spinner) findViewById(R.id.mySpinner);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_spinner_item, items);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
使用这段代码,最初会显示项目“One”。我可以在项目中添加一个新项目“Select One”,但“Select One”也会作为第一项显示在下拉列表中,这不是我想要的。
我该如何解决这个问题?
private boolean isFirst = true;
private void setAdapter() {
final ArrayList<String> spinnerArray = new ArrayList<String>();
spinnerArray.add("Select your option");
spinnerArray.add("Option 1");
spinnerArray.add("Option 2");
spin.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
TextView tv = (TextView)selectedItemView;
String res = tv.getText().toString().trim();
if (res.equals("Option 1")) {
//do Something
} else if (res.equals("Option 2")) {
//do Something else
}
}
@Override
public void onNothingSelected(AdapterView<?> parentView) { }
});
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.my_spinner_style,spinnerArray) {
public View getView(int position, View convertView, ViewGroup parent) {
View v = super.getView(position, convertView, parent);
int height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 25, getResources().getDisplayMetrics());
((TextView) v).setTypeface(tf2);
((TextView) v).getLayoutParams().height = height;
((TextView) v).setGravity(Gravity.CENTER);
((TextView) v).setTextSize(TypedValue.COMPLEX_UNIT_SP, 19);
((TextView) v).setTextColor(Color.WHITE);
return v;
}
public View getDropDownView(int position, View convertView,
ViewGroup parent) {
if (isFirst) {
isFirst = false;
spinnerArray.remove(0);
}
View v = super.getDropDownView(position, convertView, parent);
((TextView) v).setTextColor(Color.argb(255, 70, 70, 70));
((TextView) v).setTypeface(tf2);
((TextView) v).setGravity(Gravity.CENTER);
return v;
}
};
spin.setAdapter(adapter);
}
之前提交的答案都没有真正按照我想要的方式解决这个问题。对我来说,理想的解决方案是在旋转器第一次显示时提供“Select One”(或任何初始文本)。当用户点击转轮时,初始文本不应该是显示的下拉框的一部分。
为了使我的特定情况更加复杂,我的旋转器数据来自通过LoaderManager回调加载的游标。
经过大量的实验,我想出了以下解决方案:
public class MyFragment extends Fragment implements
LoaderManager.LoaderCallbacks<Cursor>{
private static final String SPINNER_INIT_VALUE = "Select A Widget";
private Spinner mSpinner;
private int mSpinnerPosition;
private boolean mSpinnerDropDownShowing = false;
private View mSpinnerDropDown;
private MyCursorAdapter mCursorAdapter;
...
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
...
mCursorAdapter = new MyCursorAdapter(getActivity());
mSpinner = (Spinner) rootView.findViewById(R.id.theSpinner);
mSpinner.setOnTouchListener(mSpinnerTouchListener);
mSpinner.setAdapter(mCursorAdapter);
...
}
//Capture the touch events to toggle the spinner's dropdown visibility
private OnTouchListener mSpinnerTouchListener = new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if(mSpinnerDropDown != null && mSpinnerDropDownShowing == false){
mSpinnerDropDownShowing = true;
mSpinnerDropDown.setVisibility(View.VISIBLE);
}
return false;
}
};
//Capture the click event on the spinner drop down items
protected OnClickListener spinnerItemClick = new OnClickListener(){
@Override
public void onClick(View view) {
String widget = ((TextView) view.findViewById(android.R.id.text1)).getText().toString();
if(!widget.equals(SPINNER_INIT_VALUE)){
if(mCursorAdapter != null){
Cursor cursor = mCursorAdapter.getCursor();
if(cursor.moveToFirst()){
while(!cursor.isAfterLast()){
if(widget.equals(cursor.getString(WidgetQuery.WIDGET_NAME))){
...
//Set the spinner to the correct item
mSpinnerPosition = cursor.getPosition() + 1;
mSpinner.setSelection(mSpinnerPosition);
break;
}
cursor.moveToNext();
}
}
}
}
//Hide the drop down. Not the most elegent solution but it is the only way I could hide/dismiss the drop down
mSpinnerDropDown = view.getRootView();
mSpinnerDropDownShowing = false;
mSpinnerDropDown.setVisibility(View.GONE);
}
};
private class MyCursorAdapter extends CursorAdapter {
private final int DISPLACEMENT = 1;
private final int DEFAULT_ITEM_ID = Integer.MAX_VALUE;
private Activity mActivity;
public MyCursorAdapter(Activity activity) {
super(activity, null, false);
mActivity = activity;
}
//When loading the regular views, inject the defualt item
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if(position == 0){
if(convertView == null){
convertView = mActivity.getLayoutInflater().inflate(R.layout.list_item_widget, parent, false);
}
return getDefaultItem(convertView);
}
return super.getView(position - DISPLACEMENT, convertView, parent);
}
//When loading the drop down views, set the onClickListener for each view
@Override
public View getDropDownView(int position, View convertView, ViewGroup parent){
View view = super.getDropDownView(position, convertView, parent);
view.setOnClickListener(spinnerItemClick);
return view;
}
//The special default item that is being injected
private View getDefaultItem(View convertView){
TextView text = (TextView) convertView.findViewById(android.R.id.text1);
text.setText(SPINNER_INIT_VALUE);
return convertView;
}
@Override
public long getItemId(int position) {
if (position == 0) {
return DEFAULT_ITEM_ID;
}
return super.getItemId(position - DISPLACEMENT);
}
@Override
public boolean isEnabled(int position) {
return position == 0 ? true : super.isEnabled(position - DISPLACEMENT);
}
@Override
public int getViewTypeCount() {
return super.getViewTypeCount() + DISPLACEMENT;
}
@Override
public int getItemViewType(int position) {
if (position == 0) {
return super.getViewTypeCount();
}
return super.getItemViewType(position - DISPLACEMENT);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return mActivity.getLayoutInflater().inflate(R.layout.list_item_widget, parent, false);
}
@Override
public void bindView(View view, Context context, Cursor cursor){
if(cursor.isAfterLast()){
return;
}
TextView text = (TextView) view.findViewById(android.R.id.text1);
String WidgetName = cursor.getString(WidgetQuery.WIDGET_NAME);
text.setText(WidgetName);
}
}
}
When extending SpinnerAdapter, you override two View-producing methods, getView(int, View, ViewGroup) and getDropDownView(int, View, ViewGroup). The first one supplies the View inserted into the Spinner itself; the second supplies the View in the drop-down list (as the name suggests). You can override the getView(...) so that, until an item has been selected, it displays a TextView containing a prompt; then, when you detect an item has been selected, you change it to display a TextView corresponding to that.
public class PromptingAdapter extends SpinnerAdapter {
//... various code ...
private boolean selectionmade = false;
//call this method from the OnItemSelectedListener for your Spinner
public setSelectionState(boolean b) {
selectionmade = b;
}
@Override
public View getView(int position, View recycle, ViewGroup container) {
if(selectionmade) {
//your existing code to supply a View for the Spinner
//you could even put "return getDropDownView(position, recycle, container);"
}
else {
View output;
if(recycle instanceof TextView) {
output = recycle;
}
else {
output = new TextView();
//and layout stuff
}
output.setText(R.string.please_select_one);
//put a string "please_select_one" in res/values/strings.xml
return output;
}
}
//...
}
这是我最后一个“all in”按钮旋转器的例子
在activity_my_form.xml
<Button
android:id="@+id/btnSpinnerPlanets"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="left|center_vertical"
android:singleLine="true"
android:text="@string/selectAPlanet"
android:textSize="10sp"
android:background="@android:drawable/btn_dropdown">
</Button>
在strings.xml
<string name="selectAPlanet">Select planet…</string>
<string-array name="planets__entries">
<item>The Sun with a name very long so long long long long longThe Sun with a name very long so long long long long longThe Sun with a name very long so long long long long long</item>
<item>Mercury</item>
<item>Venus</item>
<item>Earth</item>
<item>Mars</item>
<item>Jupiter</item>
<item>Saturn</item>
<item>Uranus</item>
<item>Neptune</item>
</string-array>
在MyFormActivity.java
public class MyFormActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
((Button) findViewById(R.id.btnSpinnerPlanets)).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
final String[] items = view.getResources().getStringArray(R.array.planets__entries);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(MyFormActivity.this, android.R.layout.simple_spinner_dropdown_item, items);
new AlertDialog.Builder(MyFormActivity.this).setTitle("the prompt").setAdapter(adapter, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
((Button) findViewById(R.id.btnSpinnerPlanets)).setText(items[which]);
dialog.dismiss();
}
}).create().show();
}
});
}
}
最后我获得了一个字体大小可配置无第一项可选择的按钮旋转器!!
感谢HRJ