By default the spinner width is set to fit the largest item in the dropdown but I want it to be the same width as the selected item.
<android.widget.Spinner
    android:id="@+id/tab_spinner"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:entries="@array/countries" />

As you can see in the right side image, the spinner is way too long, because of the long item in the list.
How can I resize it to the selected item width ?
By default, Spinner will try to measure some of your dropdown views and use the max width found. This happens in Spinner#measureContentWidth(), a protected method of Spinner called in Spinner#onMeasure().
One way to solve the issue is to make sure your SpinnerAdapter#getView() method always uses Spinner#getSelectedItemPosition() for its position argument.
I can think of two possible solutions:
1. Creating a custom spinner with a wrapper adapter
Make sure to use this in your xml layout, instead of a normal <Spinner>.
Be careful that DynamicWidthSpinner#getAdapter() will return a WrapperSpinnerAdapter; use its getBaseAdapter() method to access to your adapter.
public class DynamicWidthSpinner extends Spinner {
    public DynamicWidthSpinner(Context context) {
        super(context);
    }
    public DynamicWidthSpinner(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    public DynamicWidthSpinner(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }
    public void setAdapter(SpinnerAdapter adapter) {
        super.setAdapter(adapter != null ? new WrapperSpinnerAdapter(adapter) : null);
    }
    public final class WrapperSpinnerAdapter implements SpinnerAdapter {
        private final SpinnerAdapter mBaseAdapter;
        public WrapperSpinnerAdapter(SpinnerAdapter baseAdapter) {
            mBaseAdapter = baseAdapter;
        }
        public View getView(int position, View convertView, ViewGroup parent) {
            return mBaseAdapter.getView(getSelectedItemPosition(), convertView, parent);
        }
        public final SpinnerAdapter getBaseAdapter() {
            return mBaseAdapter;
        }
        public int getCount() {
            return mBaseAdapter.getCount();
        }
        public View getDropDownView(int position, View convertView, ViewGroup parent) {
            return mBaseAdapter.getDropDownView(position, convertView, parent);
        }
        public Object getItem(int position) {
            return mBaseAdapter.getItem(position);
        }
        public long getItemId(int position) {
            return mBaseAdapter.getItemId(position);
        }
        public int getItemViewType(int position) {
            return mBaseAdapter.getItemViewType(position);
        }
        public int getViewTypeCount() {
            return mBaseAdapter.getViewTypeCount();
        }
        public boolean hasStableIds() {
            return mBaseAdapter.hasStableIds();
        }
        public boolean isEmpty() {
            return mBaseAdapter.isEmpty();
        }
        public void registerDataSetObserver(DataSetObserver observer) {
            mBaseAdapter.registerDataSetObserver(observer);
        }
        public void unregisterDataSetObserver(DataSetObserver observer) {
            mBaseAdapter.unregisterDataSetObserver(observer);
        }
    }
}
2. Adapting your custom adapter
Be careful that parent in getView() might not always be a Spinner.
private class SimpleSpinnerAdapter extends BaseAdapter {
    private LayoutInflater mInflater;
    private int mResource;
    public SimpleSpinnerAdapter(Context context, int resource) {
        mInflater = LayoutInflater.from(context);
        mResource = resource;
    }
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        return createViewFromResource(
                mInflater,
                ((Spinner) parent).getSelectedItemPosition(),
                convertView,
                parent,
                mResource);
    }
    @Override
    public View getDropDownView(int position, View convertView, ViewGroup parent) {
        return createViewFromResource(
                mInflater,
                position,
                convertView,
                parent,
                mResource);
    }
    protected View createViewFromResource(LayoutInflater inflater, int position, 
                                          View convertView, ViewGroup parent,
                                          int resource) {
        View view;
        if (convertView == null) {
            view = inflater.inflate(resource, parent, false);
        } else {
            view = convertView;
        }
        bindView(position, view);
        return view;
    }
    protected void bindView(int position, View view) {
        // Bind your view.
    }
    // getCount(), getItem(), and getItemId() methods.
}
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With