Actionbar list navigation width - wrap content

2019-02-03 10:00发布

问题:

By default in actionbar list navigation width of selected item is as wide as widest item. I would like to "wrap_content" in selected item as it's in google+,gmail,maps android apps.

Does someone know hot to do it?

I tried to override getView of navigation adapter but it doesn't work. It looks that this view is wrapped with another view which has width of widest item. I also tried actionbar.setCustom view with spinner but spinner behaviour is same. It uses widest item width.

Thanks for all suggestions, links and help.

回答1:

I've met the same problem. It seems Android will call getView() method for all the items, and finally set the width to the widest item's width.

So here's my solution:

  1. Store the current selected section(e.g. section in your example), say selectedSection, in your code. Actually you have to do it in the onNavigationItemSelected() method of NavigationListener.

  2. Override the getView() method of your SpinnerAdapter, always set it's content to selectedSection.

  3. In the onNavigationItemSelected() method of NavigationListener, try to call the notifyDataSetChanged() method of your spinnerAdapter after you set the current mode to selectedSection.

Here's the sample code:

final int selectedSection = 0;
final String sectionLabels[] = {"short sec", "long section", "looooonger section"};

final ArrayAdapter<String> arrayAdapter =
  new arrayAdapter<String>(this, simple_list_item_1) {
    @Override
    public int getCount() {
      // You need to implement here.
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
      if (convertView == null) {
        convertView = LayoutInflater.from(getContext()).inflate(R.layout.you_entry, null);
      }
      TextView textView = (TextView) convertView.findViewById(R.id.you_text);
      // Set the text to the current section.
      textView.setText(sectionLabels[selectedSection]);
    }

    @Override
    public View getDropDownView(int position, View convertView, ViewGroup parent) {
      // You need to implement here.
    }

  }

actionBar.setListNavigationCallbacks(navigationAdpater,
  new ActionBar.OnNavigationListener() {

    @Override
    public boolean onNavigationItemSelected(int itemPosition, long itemId) {
      // Store the current section.
      selectedSection = itemPosition;
      navigationAdpater.notifyDataSetChanged();
      return true;
    }
  });


回答2:

You need to override the getView() method in your adapter and set the layout params into the textview to wrap content. The spinner will resize automatically for the selected item.

I created a custom adapter extends from ArrayAdapter:

public class CustomAdapter extends ArrayAdapter<String> {

After that I override the getView() method changing the LayoutParams of the current view:

@Override 
public View getView(final int position, final View convertView, final ViewGroup parent) {
            View view = convertView;
            if (null == view) {
                view = LayoutInflater.from(this.getContext())
                         .inflate(android.R.layout.simple_list_item1, null);
                ((TextView) view).setText(getItem(position));
            }
            final LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT,
                                               LayoutParams.WRAP_CONTENT);
            view.setLayoutParams(params);
            return view;
}

In your activity, create adapter instance and set you spinner with it:

List<String> stringList = new ArrayList<String>();
stringList.add("test1");
stringList.add("test12");
stringList.add("test123");
stringList.add("test1234");

final SpinnerAdapter adapter = new CustomAdapter(this.getContext(),
                                                 android.R.layout.simple_list_item1,
                                                 android.R.id.text1, 
                                                 stringList);
mySpinner.setAdapter(adapter);

When you choose something in the list, the spinner will recreate the view, reorder the selected item to the first position, and resize him self to the content's size.



回答3:

Create a spinner and add textviews to that. On the spinner set the maxWidth field to whatever value you want and that would handle this. Another option would be to set the

android:layout_width="0"
android_layout_weight="0.3"

This would mean that the spinner would occupy only 1/3rd of the scrren width.

On the textview you would set :

android:singleLine="false"
android:ellipsize="end"


回答4:

This worked for me. Important part is this. Put the below above code is your adapter and use selectedItemPosition for selecting text from objects array.

int selectedItemPosition = position;
    if (parent instanceof AdapterView) {
        selectedItemPosition = ((AdapterView) parent)
                .getSelectedItemPosition();
    }

Example is given below.

public View getView(int position, View convertView, ViewGroup parent) {
    LayoutInflater inflater = getLayoutInflater();
    final View spinnerCell;
    if (convertView == null) {
        // if it's not recycled, inflate it from layout
        spinnerCell = inflater.inflate(R.layout.layout_spinner_cell, parent, false);
    } else {
        spinnerCell = convertView;
    }
    int selectedItemPosition = position;
    if (parent instanceof AdapterView) {
        selectedItemPosition = ((AdapterView) parent)
                .getSelectedItemPosition();
    }

    TextView title = (TextView) spinnerCell.findViewById(R.id.spinnerTitle);
    title.setText(titles[selectedItemPosition]);
    return spinnerCell;
}

If you need an explanation follow this link: http://coding-thoughts.blogspot.in/2013/11/help-my-spinner-is-too-wide.html