Android子视图高度与ListView项目中的父级不匹配
Posted
技术标签:
【中文标题】Android子视图高度与ListView项目中的父级不匹配【英文标题】:Android child view height not match parent in ListView item 【发布时间】:2012-08-25 20:09:57 【问题描述】:如上所述,我的列表项是FrameLayout
,里面有两个视图。
ColorView
是我为在整个视图中显示颜色而制作的自定义视图。
(FrameLayout
的高度是“wrap_content”)
它似乎在我的 ICS 设备上运行良好,但不适用于我的 android 2.2 模拟器和 Android 1.6 G1。
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_
android:layout_>
<org.mariotaku.twidere.view.ColorView
android:id="@+id/status_background"
android:layout_
android:layout_
android:layout_gravity="center"
android:background="@drawable/ic_label_user"/>
<RelativeLayout
android:id="@+id/status_content"
android:layout_
android:layout_
android:paddingBottom="6dp"
android:paddingRight="6dp"
android:paddingTop="6dp">
<org.mariotaku.twidere.view.RoundCorneredImageView
android:id="@+id/profile_image"
android:layout_
android:layout_
android:layout_marginLeft="6dp"
android:scaleType="fitCenter"/>
<TextView
android:id="@+id/name"
android:layout_
android:layout_
android:layout_alignParentTop="true"
android:layout_alignWithParentIfMissing="true"
android:layout_marginLeft="6dp"
android:layout_toLeftOf="@+id/time"
android:layout_toRightOf="@+id/profile_image"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:attr/textColorPrimary"
android:textStyle="bold"/>
<TextView
android:id="@+id/text"
android:layout_
android:layout_
android:layout_alignLeft="@+id/name"
android:layout_alignParentRight="true"
android:layout_alignWithParentIfMissing="true"
android:layout_below="@+id/name"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:attr/textColorSecondary"/>
<TextView
android:id="@+id/time"
android:layout_
android:layout_
android:layout_alignBaseline="@+id/name"
android:layout_alignParentRight="true"
android:layout_alignWithParentIfMissing="true"
android:drawablePadding="3dp"
android:gravity="center_vertical|right"
android:textColor="?android:attr/textColorSecondary"/>
<ImageView
android:id="@+id/image_preview"
android:layout_
android:layout_
android:layout_alignWithParentIfMissing="true"
android:layout_below="@+id/text"
android:layout_marginLeft="16dp"
android:layout_marginTop="3dp"
android:layout_toRightOf="@+id/profile_image"
android:background="@drawable/image_preview_background"
android:drawablePadding="3dp"
android:scaleType="fitCenter"
android:visibility="gone"/>
<TextView
android:id="@+id/reply_retweet_status"
android:layout_
android:layout_
android:layout_alignWithParentIfMissing="true"
android:layout_below="@+id/image_preview"
android:layout_toRightOf="@+id/profile_image"
android:drawablePadding="3dp"
android:paddingLeft="6dp"
android:paddingTop="3dp"
android:textColor="?android:attr/textColorSecondary"/>
</RelativeLayout>
<TextView
android:id="@+id/list_gap_text"
android:layout_
android:layout_
android:layout_gravity="center"
android:gravity="center"
android:text="@string/tap_to_load_more"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textStyle="bold"
android:visibility="gone"/>
</FrameLayout>
是否有任何解决方法或其他方法来解决这个问题?
编辑
ColorView
的代码
package org.mariotaku.twidere.view;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.View;
public class ColorView extends View
private int mColor = Color.TRANSPARENT;
public ColorView(Context context)
this(context, null);
public ColorView(Context context, AttributeSet attrs)
this(context, attrs, 0);
public ColorView(Context context, AttributeSet attrs, int defStyle)
super(context, attrs, defStyle);
public void setColor(int color)
mColor = color;
invalidate();
@Override
protected void onDraw(Canvas canvas)
super.onDraw(canvas);
canvas.drawColor(mColor);
【问题讨论】:
点赞帮助你获得关注。 可以添加ColorView
的代码吗?
添加了,很简单。
左边的条带是哪一个布局视图?
这是ColorView
的背景,一个9patch的drawable。 !IMG
【参考方案1】:
我们只需要处理类似的问题。我们注意到,在属于 ListView 项的一部分的视图上使用 match_height 不会按预期工作。以下代码应该可以工作:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_
android:layout_ >
<FrameLayout
android:id="@+id/content"
android:layout_
android:layout_
android:layout_toLeftOf="@+id/color_bar" >
<!-- Put the content views of your item here. You do not have to use frame layout, it can be any kind of view. -->
<TextView
android:layout_
android:layout_
android:padding="8dp"
android:text="@string/app_name" />
</FrameLayout>
<View
android:id="@id/color_bar"
android:layout_
android:layout_
android:layout_alignBottom="@id/content"
android:layout_alignParentRight="true"
android:layout_alignTop="@id/content"
android:background="@android:color/darker_gray" />
</RelativeLayout>
诀窍基本上是将彩色视图与内容视图的顶部和底部对齐。无论内容的高度是多少,都会被彩色视图采用。
附带说明,如Android's documentation 中所述,您不应使用 FrameLayout 来包含多个子级。
编辑
我的同事让我注意到,如果我们使用 LinearLayout 作为列表视图项的根元素,match_parent 会按预期工作:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_
android:layout_
android:orientation="horizontal" >
<TextView
android:id="@+id/content"
android:layout_
android:layout_
android:layout_weight="1"
android:padding="8dp"
android:text="@string/app_name" />
<View
android:id="@+id/color_bar"
android:layout_
android:layout_
android:background="@android:color/darker_gray" />
</LinearLayout>
我在装有 Android 2.2 的设备上对此进行了测试,它运行正常。
【讨论】:
【参考方案2】:好伤心,没人知道怎么处理。
但最后我使用了一种解决方法来解决这个问题。
新布局 XML:
<?xml version="1.0" encoding="utf-8"?>
<org.mariotaku.twidere.view.ColorLabelRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_
android:layout_
android:padding="6dp">
<org.mariotaku.twidere.view.RoundCorneredImageView
android:id="@+id/profile_image"
android:layout_
android:layout_
android:scaleType="fitCenter"/>
<TextView
android:id="@+id/name"
android:layout_
android:layout_
android:layout_alignParentTop="true"
android:layout_alignWithParentIfMissing="true"
android:layout_marginLeft="3dp"
android:layout_toLeftOf="@+id/time"
android:layout_toRightOf="@+id/profile_image"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:attr/textColorPrimary"
android:textStyle="bold"/>
<TextView
android:id="@+id/text"
android:layout_
android:layout_
android:layout_alignLeft="@+id/name"
android:layout_alignParentRight="true"
android:layout_alignWithParentIfMissing="true"
android:layout_below="@+id/name"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:attr/textColorSecondary"/>
<TextView
android:id="@+id/time"
android:layout_
android:layout_
android:layout_alignBaseline="@+id/name"
android:layout_alignParentRight="true"
android:layout_alignWithParentIfMissing="true"
android:drawablePadding="3dp"
android:gravity="center_vertical|right"
android:textColor="?android:attr/textColorSecondary"/>
<ImageView
android:id="@+id/image_preview"
android:layout_
android:layout_
android:layout_alignWithParentIfMissing="true"
android:layout_below="@+id/text"
android:layout_marginLeft="16dp"
android:layout_marginTop="3dp"
android:layout_toRightOf="@+id/profile_image"
android:background="@drawable/image_preview_background"
android:drawablePadding="3dp"
android:scaleType="fitCenter"
android:visibility="gone"/>
<TextView
android:id="@+id/reply_retweet_status"
android:layout_
android:layout_
android:layout_alignWithParentIfMissing="true"
android:layout_below="@+id/image_preview"
android:layout_toRightOf="@+id/profile_image"
android:drawablePadding="3dp"
android:paddingLeft="6dp"
android:paddingTop="3dp"
android:textColor="?android:attr/textColorSecondary"/>
<TextView
android:id="@+id/list_gap_text"
android:layout_
android:layout_
android:layout_centerInParent="true"
android:gravity="center"
android:text="@string/tap_to_load_more"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textStyle="bold"
android:visibility="gone"/>
</org.mariotaku.twidere.view.ColorLabelRelativeLayout>
ColorLabelRelativeLayout
的代码:
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012 Mariotaku Lee <mariotaku.lee@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.view;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.widget.RelativeLayout;
public class ColorLabelRelativeLayout extends RelativeLayout
private final Paint mPaintLeft = new Paint(), mPaintRight = new Paint(), mPaintBackground = new Paint();
private final Rect mRectLeft = new Rect(), mRectRight = new Rect(), mRectBackground = new Rect();
private final float mDensity;
public ColorLabelRelativeLayout(Context context)
this(context, null);
public ColorLabelRelativeLayout(Context context, AttributeSet attrs)
this(context, attrs, 0);
public ColorLabelRelativeLayout(Context context, AttributeSet attrs, int defStyle)
super(context, attrs, defStyle);
setWillNotDraw(false);
mDensity = context.getResources().getDisplayMetrics().density;
mPaintLeft.setColor(Color.TRANSPARENT);
mPaintRight.setColor(Color.TRANSPARENT);
mPaintBackground.setColor(Color.TRANSPARENT);
public void drawLabel(int left, int right, int background)
mPaintBackground.setColor(background);
mPaintLeft.setColor(left);
mPaintRight.setColor(right);
invalidate();
public void drawLeft(int color)
drawLabel(color, mPaintRight.getColor(), mPaintBackground.getColor());
public void drawRight(int color)
drawLabel(mPaintLeft.getColor(), color, mPaintBackground.getColor());
public void drawBackground(int color)
drawLabel(mPaintLeft.getColor(), mPaintRight.getColor(), color);
@Override
public void onDraw(Canvas canvas)
canvas.drawRect(mRectBackground, mPaintBackground);
canvas.drawRect(mRectLeft, mPaintLeft);
canvas.drawRect(mRectRight, mPaintRight);
super.onDraw(canvas);
@Override
public void onSizeChanged(int w, int h, int oldw, int oldh)
mRectBackground.set(0, 0, w, h);
mRectLeft.set(0, 0, (int)(4 * mDensity), h);
mRectRight.set(w - (int)(4 * mDensity), 0, w, h);
super.onSizeChanged(w, h, oldw, oldh);
它对我来说真的很好用。
【讨论】:
【参考方案3】:是否需要使用ColorView
?我问这个是因为如果你不将它用于其他任何事情,那么使用它只是一种浪费。你有父FrameLayout
,你应该将ColorView
上使用的drawable设置为父FrameLayout
的背景。
【讨论】:
根视图用于多选模式下的另一个背景,ColorView
不仅用于背景,还用于该颜色标签。
@mariotaku 多选模式意味着什么(上下文操作栏)?根据当前情况简单地更改Framelayout
的背景不是更容易吗?
为了向后兼容,我使用了一些解决方法i.imgur.com/F4X9t.png 这适用于Android 1.6,通过更改FrameLayout
背景。你可以在这里看到完整的源代码。 github.com/mariotaku/twidere
@mariotaku 代码库太大了,我无法查看并找到问题。你应该修改列表行的代码,我感觉你的逻辑很复杂。此外,1.6 代表了大约 0.5% 的安卓手机,你可以放弃 1.6 并切换到 Eclair(如果这迫使你使用各种“黑客”)。【参考方案4】:
创建一个自定义布局扩展 FrameLayout 或其他布局,然后覆盖 onLayout 方法。
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b)
super.onLayout(changed, l, t, r, b);
Log.d("onLayout", getWidth() + "x" + getHeight());
final View statusView = findViewById(R.id.status_background);
if (statusView.getVisibility() == VISIBLE)
final LayoutParams p = (LayoutParams) statusView.getLayoutParams();
if (p.width != getWidth() || p.height != getHeight())
p.width = getWidth();
p.height = getHeight();
statusView.post(new Runnable()
@Override
public void run()
statusView.setLayoutParams(p);
);
【讨论】:
【参考方案5】:@softlete 答案的更新:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_
android:layout_
android:background="@android:color/transparent">
<RelativeLayout
android:layout_
android:layout_
android:padding="10dp">
<RelativeLayout
android:id="@+id/messageContent"
android:layout_
android:layout_
android:layout_alignParentTop="true"
android:layout_marginRight="20dp"
android:layout_marginLeft="20dp"
android:padding="5dp"
android:background="@drawable/message_bg">
<TextView
android:id="@+id/message"
android:layout_
android:layout_
android:layout_marginRight="20dp"
android:text="un mensaje supremamente largo debe ir aqui para probar el layout"
android:textColor="@android:color/black"
android:textSize="16dp"/>
</RelativeLayout>
<RelativeLayout
android:id="@+id/imageContainer"
android:layout_
android:layout_
android:layout_alignParentRight="true"
android:paddingTop="10dp"
android:paddingBottom="10dp">
<de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/image"
android:layout_
android:layout_
android:src="@drawable/com_facebook_profile_default_icon" />
</RelativeLayout>
</RelativeLayout>
</LinearLayout>
“最小高度”由@+id/imageContainer
的边距(顶部+底部)加上@+id/image
的+高度给出(可以使用您想要的任何视图/布局)
【讨论】:
以上是关于Android子视图高度与ListView项目中的父级不匹配的主要内容,如果未能解决你的问题,请参考以下文章
ArrayIndexOutOfBoundsException 与 ListView 中的多个视图的自定义 Android 适配器
包装在 HorizontalScrollView 中的 Android Listview 高度不正确,其中列表项的高度不同