問題
遇到一個spinner 背景的問題,記錄一下.
我在xml中定義了一個spinner
android:id="@+id/tracking_mode_spinner"
android:layout_width="wrap_content"
android:layout_height="33dp"
android:spinnerMode="dropdown"
android:background="@drawable/corner_white_bg_nor"
android:popupBackground="@drawable/spinner_pop_bg"/>
在java中調(diào)用:
mSpinner = findViewById(R.id.layout_spinner);
mSpinner.setDropDownVerticalOffset(mContext.getResources()
.getDimensionPixelSize(R.dimen.spinner_offset));
mSpinner.setDropDownWidth(mContext.getResources()
.getDimensionPixelSize(R.dimen.spinner_width));
mSpinner.setAnimation(null);
SpinnerAdapter adapter = SpinnerAdapter.createFromResource(mContext,
CameraFramingMode.createFramingModeEntries(true, false), R.layout.layout_spinner_pop_selectable_item);
mSpinner.setAdapter(adapter);
mSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
adapter.setSelectedPosition(position);
updateView();
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
adapter 是這樣使用:
SpinnerAdapter adapter = SpinnerAdapter.createFromResource(mContext,
CameraFramingMode.createFramingModeEntries(true, false), R.layout.layout_spinner_pop_selectable_item);
SpinnerAdapter 定義成這個
public static class SpinnerAdapter<T> extends ArrayAdapter<T> {
private int selectedPosition;
void setSelectedPosition(int selectedPosition) {
this.selectedPosition = selectedPosition;
}
SpinnerAdapter(@NonNull Context context, int resource, @NonNull T[] objects) {
super(context, resource, R.id.text, objects);
}
@Override
public View getDropDownView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
View view = super.getDropDownView(position, convertView, parent);
TextView icon = view.findViewById(R.id.icon);
if (selectedPosition == position) {
FontsUtils.setTypeface(icon);
icon.setText(FontIcons.OK);
icon.setVisibility(View.VISIBLE);
} else {
icon.setVisibility(View.INVISIBLE);
}
return view;
}
static @NonNull
SpinnerAdapter<CharSequence> createFromResource(@NonNull Context context,
CharSequence[] items, @LayoutRes int textViewResId) {
return new SpinnerAdapter<>(context, textViewResId, items);
}
}
layout_spinner_pop_selectable_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/selector_spinner_item_bg"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:id="@+id/text"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:background="@android:color/transparent"
/>
<TextView
android:id="@+id/icon"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center_vertical"
/>
</LinearLayout>
但是我發(fā)現(xiàn)spinner 設(shè)置的bg會被item的bg覆蓋selector_spinner_item_bg.
抓取控件樹發(fā)現(xiàn),spinner的顯示會把下拉框一個item作為顯示的內(nèi)容.
這樣子會有問題,當(dāng)item的布局樣式和spinner不一樣時,spinner的樣式會被覆蓋.
舉個例子:當(dāng)item背景要紅色,spinner背景要黑色時,spinner設(shè)置了黑色背景無用.
原因
spinner源碼中:makeView 獲取view是通過Adapter#getView的方式獲取的
/**
* Obtain a view, either by pulling an existing view from the recycler or
* by getting a new one from the adapter. If we are animating, make sure
* there is enough information in the view's layout parameters to animate
* from the old to new positions.
*
* @param position Position in the spinner for the view to obtain
* @param addChild true to add the child to the spinner, false to obtain and configure only.
* @return A view for the given position
*/
private View makeView(int position, boolean addChild) {
View child;
if (!mDataChanged) {
child = mRecycler.get(position);
if (child != null) {
// Position the view
setUpChild(child, addChild);
return child;
}
}
// Nothing found in the recycler -- ask the adapter for a view
child = mAdapter.getView(position, null, this);
// Position the view
setUpChild(child, addChild);
return child;
}
DropDownAdapter#getView,這個方法不是抽象,所以當(dāng)我們沒有重寫此方法時,他返回的就是item的view.
public View getView(int position, View convertView, ViewGroup parent) {
return getDropDownView(position, convertView, parent);
}
修改
知道原因了就好修改了,我們重寫getView重新設(shè)置一個view即可.