1

我在 PopupWindow 中为 ListView 充气,我希望弹出窗口的行为如下:

  • 当高度为 < x 时包装列表视图
  • 当列表视图的高度 > x 时设置弹出窗口的高度 = x(列表视图可滚动)

弹出窗口由附加到 EditText 的 TextWatcher 显示,因为它旨在显示搜索建议。ListView 底层的适配器由自定义加载器管理,只要用户在 EditText 中键入内容就会启动。我试图覆盖onMeasure()列表视图并将测量的高度传递给调用的侦听器PopupWindow.update(),但这会创建一个循环,因为后者最终会调用第一个。使用以下代码,弹出窗口会根据需要包装包含的 ListView,但高度不限于任何值。我需要一个解决方案来将高度限制为最大值,比如 300dp。

etFiltro.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) {
            /...
        }
        @Override
        public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) {
            Log.i("loader","text changed");
            filtro = String.valueOf(charSequence);
            getSupportLoaderManager().restartLoader(0,null,loaderCallbacks);
            if (popupWindow.isShowing()) popupWindow.dismiss();
        }
        @Override
        public void afterTextChanged(Editable editable) {               
            popupWindow.showAsDropDown(etFiltro);
        }
    });

private LoaderManager.LoaderCallbacks<Cursor> loaderCallbacks = new LoaderManager.LoaderCallbacks<Cursor>() {

    MyListView suggestionList;
    SimpleCursorAdapter adapter;
    int mHeight;

    @Override
    public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
        SuggestionLoader loader = new SuggestionLoader(MainActivity.this, databaseConnector, filtro);
        loader.setUpdateThrottle(500);
        View view = ((LayoutInflater)getSystemService(LAYOUT_INFLATER_SERVICE)).inflate(R.layout.popup_window,null);
        suggestionList = (MyListView) view.findViewById(R.id.suggestionList);
        adapter = new SimpleCursorAdapter(MainActivity.this,android.R.layout.simple_list_item_1,null,
                new String[]{"note"},new int[]{android.R.id.text1},0);
        suggestionList.setAdapter(adapter);
        suggestionList.setEmptyView(view.findViewById(R.id.tvNoSuggestions));
        //ensure previous popup is dismissed
        if (popupWindow!=null) popupWindow.dismiss();
        popupWindow = new PopupWindow(view,etFiltro.getWidth(),0);
        popupWindow.setWindowLayoutMode(0,WindowManager.LayoutParams.WRAP_CONTENT);
        popupWindow.setAnimationStyle(0);//0 = no animation; -1 = default animation            
        Log.i("loader","onCreateLoader");
        return loader;
    }

    @Override
    public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor) {
        adapter.changeCursor(cursor);           
        Log.i("loader","onLoadFinished");

    }

    @Override
    public void onLoaderReset(Loader<Cursor> cursorLoader) {
        Log.i("loader", "onLoaderReset");
        adapter.changeCursor(null);
    }
};
4

1 回答 1

2

我自己找到了解决方案。对于任何偶然发现这个问题的人,答案是onMeasure()像这样覆盖 ListView 的方法:

public class MyListView extends ListView {

public MyListView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
}

public MyListView(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public MyListView(Context context) {
    super(context);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

    //set your custom height. AT_MOST means it can be as tall as needed,
    //up to the specified size.

    int height = MeasureSpec.makeMeasureSpec(300,MeasureSpec.AT_MOST);

    super.onMeasure(widthMeasureSpec,height);               
}
}
于 2014-02-25T00:21:39.720 回答