Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to wrap text content in ActionBarSherlock navigation spinner

I'm trying to wrap the text content of my ActionBar navigation spinner (I'm using ActionBar Sherlock). It seems that my spinner takes the width of the items contained within the dropdown list.

How can I make the selected item in the spinner be "wrapped" according to its width ? An example may be found in GMaps action bar spinner.

like image 664
kaffein Avatar asked Sep 24 '12 17:09

kaffein


2 Answers

UPDATE:

Download my example project here: Spinner width test (Dropbox folder) (it contains both solutions provided in this answer).

Since the kerning (letter-spacing) of the characters is different depending on the text, the width of the spinner also changed width the answer I postet earlier (below)

So instead of substring the title, just set the width of the TextView in pixel like this:

textView.setWidth(200);
  • The text will now get truncated and ending with "..".

  • The width of the spinner remains the same size.

  • You can set different width for the drop down list and the spinner

  • You still need a custom SpinnerAdapter, but you don't need a custom
    SpinnerItem Class, just give the adapter a String[] array.

spinner.setAdapter(new TruncatedSpinnerAdapter(stringArray));//String[]

In TruncatedSpinnerAdapter:

public class TruncatedSpinnerAdapter implements SpinnerAdapter {

    String[] spinnerItem;

    public TruncatedSpinnerAdapter(String[] spinnerItem) {
        this.spinnerItem = spinnerItem;
    }

//    ...more required interface callbacks here...

    /**
     * Returns the View that is shown when a spinner item is selected.
     */
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View view = getLayoutInflater().inflate(
                android.R.layout.simple_spinner_item, null);
        TextView textView = (TextView) view.findViewById(android.R.id.text1);
        textView.setText(spinnerItem[position]);
        //Set the width of the TextView in pixel. 
        //the text will now get truncated and ending with ".."
        textView.setWidth(200);
        return textView;
    }

The Answer before update:

You can wrap the text sort of by creating a custom SpinnerAdapter where you control the length of the text you show in the spinner view and in the spinner drop down view.

 /**
     * A SpinnerItemAdapter to handle SpinnerItem Objects, 
     * displays the ArrayList of SpinnerItem Objects.
     */
    public class SpinnerItemAdapter implements SpinnerAdapter{

        /**
         * The internal data, ArrayList of SpinnerItem Objects.
         */
        SparseArray<SpinnerItem> spinnerItem;

        public SpinnerItemAdapter(SparseArray<SpinnerItem> spinnerItem){
            this.spinnerItem = spinnerItem;
        }

        /**
         * Returns the Size
         */
        @Override
        public int getCount() {
            return spinnerItem.size();
        }
        /**
         * Returns a SpinnerItem Object at the specified position.
         */
        @Override
        public Object getItem(int position) {
            return spinnerItem.valueAt(position);
        }


//    ...more required interface callbacks here...


        /**
         * Views displayed when the Spinner is clicked, the drop 
         * down list of spinner items.
         */
        @Override
        public View getDropDownView(int position, View convertView,
                ViewGroup parent) {
            View view=getLayoutInflater().inflate(android.R.layout.simple_spinner_dropdown_item, null); 
            TextView v=(TextView)view.findViewById(android.R.id.text1);
            v.setText(spinnerItem.valueAt(position).getDropDownTitle());     
            return v;
        }
        /**
         * Returns the View that is shown when a spinner item is selected.
         */
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View view=getLayoutInflater().inflate(android.R.layout.simple_spinner_item, null); 
            TextView v=(TextView)view.findViewById(android.R.id.text1);
            v.setText(spinnerItem.valueAt(position).getShortTitle());   
            return v;
        }

    }

populate the adapter with a custom SpinnerItem Class that can hold and return a shortened title for the spinner view.

class SpinnerItem {

    // SpinnerItem fields, including variable of type SpinnerItem
    public String title = "";
    // sets the width of the spinnerItem
    public int titleLength = 10;//default value
    public int titleDropDownLength = 20;

    public long id;

    // SpinnerItem methods()

    /**
     * Title with max characters displayed, set by titleLength;
     * 
     * @return title of the spinnerItem.
     */
    public CharSequence getShortTitle() {
        if (title.length() == 0)
            return "?";//
        else if (title.length() > 0 && title.length() <= titleLength) {
            return title;
        } else {
            String shortTile = title.substring(0, titleLength).trim() + "..";
            return shortTile;
        }
    }

    public CharSequence getDropDownTitle() {
        if (title.length() == 0)
            return "?";//
        else if (title.length() > 0 && title.length() <= titleDropDownLength) {
            return title;
        } else {
            String shortTile = title.substring(0, titleDropDownLength).trim() + "..";
            return shortTile;
        }
    }
}

with the SpinnerItem class you can control the length of the title shown in the spinner item view by setting a MAX title length when you create the SpinnerItem Object.

//Create an ArrayList for the Adapter with SpinnerItems
        SparseArray<SpinnerItem> spinnerItems = new SparseArray<SpinnerItem>();

        //Some dummy Cheese titles for the spinner items
        String[] sCheeseStrings = {
               "Abbaye de Belloc", "Abbaye du Mont des Cats", "Abertam", "Abondance", "Ackawi",
               "Acorn", "Adelost", "Affidelice au Chablis", "Afuega'l Pitu", "Airag", "Airedale"};

        for (int i = 0; i < sCheeseStrings.length; i++) {
            SpinnerItem spinnerItem= new SpinnerItem(); 
            spinnerItem.title=sCheeseStrings[i];
            spinnerItem.id=i;
            spinnerItem.titleLength=MAX_TITLE_LENGTH;
            spinnerItem.titleDropDownLength=MAX_DROP_DOWN_TITLE_LENGTH;
            spinnerItems.append(i, spinnerItem);
        }
        spinnerAdapter = new SpinnerItemAdapter(spinnerItems);

Then add the spinnerAdapter to the Spinner

spinner.setAdapter(spinnerAdapter);

ActionBar: Spinner in menu.xml Example

        // For API below 11 use ActionBar Sherlock with Android Support Library
//       getSupportMenuInflater().inflate(R.menu.activity_menu, menu);
        // For API above 11
        getMenuInflater().inflate(R.menu.activity_menu, menu);
        spinner_menu = (Spinner) menu.findItem(R.id.menu_spinner).getActionView();
        spinner_menu.setAdapter(spinnerAdapter);
like image 187
TouchBoarder Avatar answered Nov 04 '22 03:11

TouchBoarder


Actually android will try to call getView() for all the items, and set the width of the spinner with the widest width. Please refer to my solution in an other thread. https://stackoverflow.com/a/15356679/2159849

like image 33
Wei Jiang Avatar answered Nov 04 '22 05:11

Wei Jiang