繁体   English   中英

如何在Android上的PopupWindow中设置ListView的宽度?

[英]How to set the width of the ListView in a PopupWindow on Android?

我将ListView作为PopupWindow中的contentView进行了膨胀。 如果我没有设置宽度和高度,我看不到PopupWindow。 如果我这样设置:

setWindowLayoutMode(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);

布局设置为“fill_parent”。 为什么?

ListView和ListView项的布局属性都设置为“wrap_content”。 有什么建议吗? 谢谢。

这是怎么做的:

// Don't use this. It causes ListView's to have strange widths, similar to "fill_parent"
//popupWindow.setWindowLayoutMode(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT);

// Instead, use this:
final int NUM_OF_VISIBLE_LIST_ROWS = 4;
listView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
popupWindow.setWidth(listView.getMeasuredWidth());
popupWindow.setHeight((listView.getMeasuredHeight() + 10) * NUM_OF_VISIBLE_LIST_ROWS);

请注意, setWidth()setHeight()使用原始像素值,因此您需要针对不同的屏幕尺寸和不同的密度进行调整。

我的解决方案是覆盖on List of ListView,如下所示:

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int maxWidth = meathureWidthByChilds() + getPaddingLeft() + getPaddingRight();
    super.onMeasure(MeasureSpec.makeMeasureSpec(maxWidth, MeasureSpec.EXACTLY), heightMeasureSpec);     
}

public int meathureWidthByChilds() {
    int maxWidth = 0;
    View view = null;
    for (int i = 0; i < getAdapter().getCount(); i++) {
        view = getAdapter().getView(i, view, this);
        view.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
        if (view.getMeasuredWidth() > maxWidth){
            maxWidth = view.getMeasuredWidth();
        }
    }
    return maxWidth;
}

我遇到了同样的问题。 我找到的唯一解决方案是将PopupWindow宽度设置为ListView的确切宽度:

listView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
final PopupWindow popup = new PopupWindow(listView, listView.getMeasuredWidth(),
    ViewGroup.LayoutParams.WRAP_CONTENT, true);
popup.showAsDropDown(anchor);

不幸的是,它并没有完全解决问题。 ListView测量自身,以便它只能包装它的第一个子节点。 例如,如果第二个孩子比第一个孩子宽,则第二个孩子将被剪裁。

我不确定,但改变ListView测量自身方式的唯一方法是将其子类化并覆盖onMeasure()方法。 我现在正在尝试这样做,如果我成功的话,我会在这里写评论。

这是SimpleListView类的实现。 我知道这是低效的,我很确定它包含错误,但它显示了如何测量列表视图的宽度。

我还建议阅读这篇文章

    public class SimpleListView extends AdapterView<ListAdapter> {
    private ListAdapter adapter;
    private Drawable divider;
    private int dividerHeight;
    private boolean clipDivider;

    public SimpleListView( final Context context )
    {
        this( context, null );
    }

    public SimpleListView( final Context context, final AttributeSet attrs )
    {
        this( context, attrs, android.R.attr.listViewStyle );
    }

    public SimpleListView( final Context context, final AttributeSet attrs, final int defStyle )
    {
        super( context, attrs, defStyle );

        final TypedArray array =
            context.obtainStyledAttributes( attrs, R.styleable.SimpleListView, defStyle, 0 );

        final Drawable dividerAttribute =
            array.getDrawable( R.styleable.SimpleListView_android_divider );
        if( dividerAttribute != null ) {
            setDivider( dividerAttribute );
        }

        final int dividerHeightAttribute =
            array.getDimensionPixelSize( R.styleable.SimpleListView_android_dividerHeight, 0 );
        if( dividerHeightAttribute != 0 ) {
            setDividerHeight( dividerHeightAttribute );
        }

        array.recycle();
    }

    public Drawable getDivider()
    {
        return this.divider;
    }

    public void setDivider( final Drawable newDivider )
    {
        if( newDivider != null ) {
            this.dividerHeight = newDivider.getIntrinsicHeight();
            this.clipDivider = newDivider instanceof ColorDrawable;
        } else {
            this.dividerHeight = 0;
            this.clipDivider = false;
        }
        this.divider = newDivider;
        requestLayout();
    }

    public int getDividerHeight()
    {
        return this.dividerHeight;
    }

    public void setDividerHeight( final int newHeight )
    {
        this.dividerHeight = newHeight;
        requestLayout();
    }

    @Override
    public ListAdapter getAdapter()
    {
        return this.adapter;
    }

    @Override
    public void setAdapter( final ListAdapter adapter )
    {
        this.adapter = adapter;
        removeAllViewsInLayout();
        requestLayout();
    }

    @Override
    public View getSelectedView()
    {
        throw new UnsupportedOperationException(
            "SimpleListView.getSelectedView() is not supported" );
    }

    @Override
    public void setSelection( final int position )
    {
        throw new UnsupportedOperationException(
            "SimpleListView.setSelection(int) is not supported" );
    }

    @Override
    protected void onMeasure( final int widthMeasureSpec, final int heightMeasureSpec )
    {
        super.onMeasure( widthMeasureSpec, heightMeasureSpec );

        final int widthMode = MeasureSpec.getMode( widthMeasureSpec );
        int widthSize = MeasureSpec.getSize( widthMeasureSpec );
        final int heightMode = MeasureSpec.getMode( heightMeasureSpec );
        int heightSize = MeasureSpec.getSize( heightMeasureSpec );

        int innerWidth = 0;
        int innerHeight = 0;

        final int itemCount = this.adapter == null ? 0 : this.adapter.getCount();
        if( itemCount > 0
            && ( widthMode != MeasureSpec.EXACTLY || heightMode != MeasureSpec.EXACTLY ) ) {
            for( int i = 0; i < itemCount; ++i ) {
                final View convertView = getChildAt( i );
                final View child = this.adapter.getView( i, convertView, this );
                if( convertView == null ) {
                    LayoutParams params = child.getLayoutParams();
                    if( params == null ) {
                        params = new LayoutParams( LayoutParams.WRAP_CONTENT,
                            LayoutParams.WRAP_CONTENT );
                        child.setLayoutParams( params );
                    }
                    addViewInLayout( child, i, params );
                }

                if( child.getLayoutParams() instanceof MarginLayoutParams ) {
                    measureChildWithMargins( child, widthMeasureSpec, 0, heightMeasureSpec, 0 );
                } else {
                    measureChild( child, widthMeasureSpec, heightMeasureSpec );
                }
                innerWidth = Math.max( innerWidth, child.getMeasuredWidth() );
                innerHeight += child.getMeasuredHeight();
            }

            innerHeight += ( itemCount - 1 ) * this.dividerHeight;
        }

        if( widthMode != MeasureSpec.EXACTLY ) {
            final int newWidthSize = getPaddingLeft() + getPaddingRight() + innerWidth;
            widthSize =
                widthMode == MeasureSpec.AT_MOST ? Math.min( widthSize, newWidthSize )
                    : newWidthSize;
        }

        if( heightMode != MeasureSpec.EXACTLY ) {
            final int newHeightSize = getPaddingTop() + getPaddingBottom() + innerHeight;
            heightSize =
                heightMode == MeasureSpec.AT_MOST ? Math.min( heightSize, newHeightSize )
                    : newHeightSize;
        }

        setMeasuredDimension( widthSize, heightSize );
    }

    @Override
    protected void onLayout( final boolean changed, final int left, final int top, final int right,
        final int bottom )
    {
        super.onLayout( changed, left, top, right, bottom );

        if( this.adapter == null ) {
            return;
        }

        positionItems();
        invalidate();
    }

    private void positionItems()
    {
        int top = getPaddingTop();
        final int left = getPaddingLeft();

        for( int i = 0, count = getChildCount(); i < count; ++i ) {
            final View child = getChildAt( i );

            final int width = child.getMeasuredWidth();
            final int height = child.getMeasuredHeight();

            child.layout( left, top, left + width, top + height );
            top += height + this.dividerHeight;
        }
    }

    @Override
    protected void dispatchDraw( final Canvas canvas )
    {
        final boolean drawDividers = this.dividerHeight > 0 && this.divider != null;

        if( drawDividers ) {
            final int left = getPaddingLeft();
            final int right = getWidth() - getPaddingRight();
            final Rect dividerBounds = new Rect( left, 0, right, 0 );

            for( int i = 0, count = getChildCount(); i < count - 1; ++i ) {
                final View child = getChildAt( i );

                dividerBounds.top = dividerBounds.bottom + child.getMeasuredHeight();
                dividerBounds.bottom = dividerBounds.top + this.dividerHeight;
                drawDivider( canvas, dividerBounds );
            }
        }

        super.dispatchDraw( canvas );
    }

    private void drawDivider( final Canvas canvas, final Rect bounds )
    {
        if( !this.clipDivider ) {
            this.divider.setBounds( bounds );
        } else {
            canvas.save();
            canvas.clipRect( bounds );
        }

        this.divider.draw( canvas );

        if( this.clipDivider ) {
            canvas.restore();
        }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM