我将ListView作为PopupWindow中的contentView进行了膨胀。 如果我没有设置宽度&身高,我看不到PopupWindow。 如果我这样设置:
setWindowLayoutMode(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
布局设置如“fill_parent”。为什么呢?
ListView和ListView项的布局属性都设置为“wrap_content”。 有什么建议吗?感谢。
答案 0 :(得分:3)
这是怎么做的:
// 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()
使用原始像素值,因此您需要针对不同的屏幕尺寸和不同的密度进行调整。
答案 1 :(得分:3)
我的解决方案是覆盖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;
}
答案 2 :(得分:1)
我遇到了同样的问题。我找到的唯一解决方案是将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()
方法。我现在正在尝试这样做,如果我成功的话,我会在这里写评论。
答案 3 :(得分:1)
这是SimpleListView
类实现。我知道这是低效的,我很确定它包含错误,但它显示了如何测量列表视图的宽度。
我还建议您阅读this article。
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();
}
}
}
答案 4 :(得分:0)
您可以在XML文件中放置一个临时控件,例如:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:entries="@array/popitems" />
<TextView
android:layout_width="wrap_content"
android:layout_height="0dp"
android:text="My name is ZhengGuangyu"
android:visibility="invisible" />
</LinearLayout>
请注意TextView
的文字。您应该列出listview的最长文本。
如果您的列表视图包含以下字符串:
然后你应该把橙色写到TextView
;
然后使用:
popupWindow.setWidth(LayoutParams.WRAP_CONTENT);
popupWindow.setHeight(LayoutParams.WRAP_CONTENT);
它对我有用,你可以尝试一下。