操作栏列表导航宽度 - 自适应内容

11

默认情况下,在操作栏列表导航中,选定项的宽度与最宽的项一样宽。我想在选定项中使用“wrap_content”,就像 Google+、Gmail 和 Maps Android 应用程序中一样。

有人知道如何做吗?

我尝试了覆盖导航适配器的getView方法,但它不起作用。看起来,此视图包含另一个视图,该视图具有最宽项的宽度。我还尝试了actionbar.setCustom view与spinner,但spinner的行为相同。它使用最宽的项宽度。

感谢所有建议、链接和帮助。

当前状态

要求的状态

4个回答

13

我遇到了同样的问题。看起来 Android 会为所有的项调用 getView() 方法,最后将宽度设置为最宽的项的宽度。

所以这是我的解决方案:

  1. 在你的代码中存储当前选择的部分(例如你的示例中的部分),称为 selectedSection。实际上,你必须在 NavigationListener 的 onNavigationItemSelected() 方法中执行此操作。

  2. 覆盖 SpinnerAdapter 的 getView() 方法,总是将其内容设置为 selectedSection。

  3. 在 NavigationListener 的 onNavigationItemSelected() 方法中,当你将当前模式设置为 selectedSection 后,尝试调用 spinnerAdapter 的 notifyDataSetChanged() 方法。

这是示例代码:

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;
    }
  });

1
非常好的答案!!!谢谢。 你还可以用textView.setText(sectionLabels[actionBar.getSelectedNavigationIndex()]);替换textView.setText(sectionLabels[selectedSection]); 这样你就不需要selectedSection了。 - Martin Vandzura
啊,是的!我们不需要选定的部分;-) @vandzi - Wei Jiang
2
有一种更简单的方法。在getView()中调用((AdapterView) parent).getSelectedItemPosition()来获取当前位置。 - Kirill Rakhman

3

您需要在适配器中覆盖getView()方法,并将布局参数设置为TextView以包裹内容。选定的项目会自动调整下拉列表的大小。

我创建了一个扩展自ArrayAdapter的自定义适配器:

public class CustomAdapter extends ArrayAdapter<String> {

之后,我覆盖了getView()方法并更改了当前视图的LayoutParams:
@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;
}

在你的活动中,创建适配器实例并使用它设置你的下拉列表:
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);

当您在列表中选择某个项目时,旋转器将重新创建视图,将所选项目重新排序到第一位置,并调整大小以适应内容的大小。


0

这对我有用。重要的部分是这个。将下面的代码放在适配器上方,并使用selectedItemPosition从对象数组中选择文本。

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

以下是示例。
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;
}

如果您需要解释,请访问此链接:http://coding-thoughts.blogspot.in/2013/11/help-my-spinner-is-too-wide.html


0
创建一个下拉菜单并添加文本视图。在下拉菜单中,将maxWidth字段设置为所需的任何值即可处理此问题。另一种选择是设置

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

这意味着旋转器将仅占屏幕宽度的三分之一。

在文本视图上,您将设置:

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

谢谢。不幸的是,它不起作用。我知道如何设置固定宽度。但我想将微调器宽度设置为所选项目的宽度。 - Martin Vandzura
你可以使用OnGlobalLayoutChangeListener并将下拉框的宽度设置为所选项的宽度。 - lokoko

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接