动态添加视图后WRAP_CONTENT无法正常工作

bra*_*ree 35 android android-layout

我正在尝试创建一个动态显示一系列自定义视图的片段.此布局的主要内容是嵌套在LinearLayout中的RelativeLayout(以水平为中心),嵌套在ScrollView中.

RelativeLayout有一些TextView和一个9补丁ImageView,可以通过动态添加的自定义视图进行扩展.但是,图像(下面的achievement_bgImageView)最终会以屏幕大小结束,即使我添加了适当数量的自定义视图,也不会尊重其父RelativeLayout的大小.当我手动设置achievement_mainLayout的大小时,图像可以很好地缩放(请参阅下面注释掉的行),但如果我尝试让RelativeLayout的wrap_content处理自己的大小调整,则无效.

ScrollView IS尊重RelativeLayout的大小,因为所有内容都存在,它只是不伸展以匹配此时内容的imageView.

任何帮助将不胜感激...我的手动计算似乎不足以考虑不同的设备,尽管我考虑到屏幕密度,我手动强迫RelativeLayout到一个恒定的宽度.

值得注意的是,RelativeLayout的测量大小始终等于屏幕的高度,无论其内容的总和是大于还是小于该高度.所以,从本质上讲,WRAP_CONTENT根本就没有做它应该做的事情.我没有引用RelativeLayout的任何边缘,所以循环依赖应该不是问题.

fragment_achievements.xml

<?xml version="1.0" encoding="utf-8"?>

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fillViewport="true" >

    <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center_horizontal">

        <RelativeLayout
                android:layout_width="320dp"
                android:layout_height="wrap_content"
                android:id="@+id/achievements_mainLayout">

            <ImageView
                    android:layout_width="fill_parent"
                    android:layout_height="fill_parent"
                    android:id="@+id/achievements_bgImageView"
                    android:src="@drawable/bkg_achievements9"
                    android:adjustViewBounds="true"
                    android:layout_marginLeft="8dp"
                    android:layout_marginTop="8dp"
                    android:layout_marginRight="8dp"
                    android:layout_centerHorizontal="true"
                    android:scaleType="fitXY"/>

            <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="Name Field"
                    android:id="@+id/achievements_nameTextView"
                    android:layout_alignParentTop="true"
                    android:layout_alignParentLeft="true"
                    android:layout_marginLeft="28dp"
                    android:layout_marginTop="30dp"/>

            <ImageView
                    android:layout_width="52dp"
                    android:layout_height="52dp"
                    android:id="@+id/achievements_avatarImageView"
                    android:layout_below="@+id/achievements_nameTextView"
                    android:layout_alignLeft="@+id/achievements_nameTextView"
                    android:src="@drawable/achieve_avatar"
                    android:layout_marginTop="5dp"/>

            <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textAppearance="?android:attr/textAppearanceSmall"
                    android:text="Top Moment:"
                    android:id="@+id/textView2"
                    android:layout_alignBottom="@+id/achievements_avatarImageView"
                    android:layout_toRightOf="@+id/achievements_avatarImageView"
                    android:layout_marginBottom="16dp"
                    android:layout_marginLeft="4dp"
                    android:textSize="12dp"/>

            <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textAppearance="?android:attr/textAppearanceSmall"
                    android:text="Me Overall:"
                    android:id="@+id/textView3"
                    android:layout_alignTop="@+id/textView2"
                    android:layout_alignLeft="@+id/textView2"
                    android:layout_marginTop="16dp"
                    android:textSize="12dp"/>

            <TextView
                    android:layout_width="52dp"
                    android:layout_height="wrap_content"
                    android:textAppearance="?android:attr/textAppearanceSmall"
                    android:text="153"
                    android:id="@+id/achievements_totalPointsTextView"
                    android:gravity="center"
                    android:layout_alignTop="@+id/achievements_avatarImageView"
                    android:layout_alignRight="@+id/achievements_bgImageView"
                    android:layout_alignEnd="@+id/achievements_bgImageView"
                    android:layout_marginRight="31dp"
                    android:textColor="#f7a033"/>

            <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="Moment"
                    android:id="@+id/achievements_topMomentTextView"
                    android:layout_alignTop="@+id/textView2"
                    android:layout_toRightOf="@+id/textView2"
                    android:layout_marginLeft="5dp"
                    android:textSize="12dp"/>

            <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="153"
                    android:id="@+id/achievements_overallTextView"
                    android:layout_alignTop="@+id/textView3"
                    android:layout_toRightOf="@+id/textView3"
                    android:layout_marginLeft="5dp"
                    android:textSize="12dp"/>

        </RelativeLayout>
    </LinearLayout>
</ScrollView>
Run Code Online (Sandbox Code Playgroud)

AchievementFragment.java

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View fragmentView = null;

    fragmentView = inflater.inflate(R.layout.fragment_achievements, container, false);

    ImageView avatarImageView = (ImageView)fragmentView.findViewById(R.id.achievements_avatarImageView);

    ...

    // Basic Achievement List Setup
    RelativeLayout mainLayout = (RelativeLayout)fragmentView.findViewById(R.id.achievements_mainLayout);
    AchievementRow currentRow = null;

    List achievementTypeList = CampaignManager.sharedManager().sortedAchievementTypeList();

    int achievementCount = achievementTypeList.size();

    for (int i = 0; i < achievementCount; i++) {
        AchievementType achievementType = (AchievementType)achievementTypeList.get(i);

        // Every third achievement creates a new row.
        if ((i % 3) == 0) {
            AchievementRow row = (AchievementRow)inflater.inflate(R.layout.widget_achievementrow, null);

            RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);

            if (currentRow == null) {
                layoutParams.addRule(RelativeLayout.BELOW, avatarImageView.getId());
                layoutParams.setMargins(10, 70, 10, 0);
            } else {
                layoutParams.addRule(RelativeLayout.BELOW, currentRow.getId());
                layoutParams.setMargins(10, 10, 10, 0);
            }

            layoutParams.addRule(RelativeLayout.ALIGN_LEFT, backgroundImageView.getId());
            layoutParams.addRule(RelativeLayout.ALIGN_RIGHT, backgroundImageView.getId());

            row.setLayoutParams(layoutParams);
            row.setId(i+1);
            mainLayout.addView(row);

            currentRow = row;
        }

        // Now setup the Button
        AchievementButton achievementButton = currentRow.buttonForIndex(i % 3);
        achievementButton.achievementType = achievementType;
        achievementButton.setOnClickListener(achievementButtonListener);
        achievementButton.setVisibility(View.VISIBLE);

        CacheManager.sharedManager().fetchAchievementThumbnail(getActivity(), achievementButton, achievementType);
    }

    // This is the manual scaling of mainLayout
    // float scale = getResources().getDisplayMetrics().density;
    // float headerHeight = scale * 150.0f;
    // float rowHeight = scale * 78.0f;
    // ViewGroup.LayoutParams mainLayoutParams = mainLayout.getLayoutParams();
    // mainLayoutParams.height = (int)(headerHeight + (Math.ceil(achievementCount / 3.0) * rowHeight));

    return fragmentView;
}
Run Code Online (Sandbox Code Playgroud)

小智 16

尝试在子节点上调用requestLayout.

我最近遇到了类似的问题,同样感到沮丧的是,像invalidate和requestLayout这样的东西似乎什么也没做.我不明白的是requestLayout不会传播给它的孩子; 它传播给它的父母.要重新测量先前测量的内容,我必须在更改的View上调用requestLayout 而不是View I实际上要调整大小.

  • 您尚未在此答案中显示任何代码示例 (3认同)

Eri*_*ric 12

一旦显示,Android不会使用"wrap_content"刷新视图布局.

因此,如果您添加子视图或动态修改内容,则会被搞砸.我确实认为这是Android UI中的噩梦和真正的缺陷!

为了解决这个问题,我编写了一个静态类,它重新计算大小并使用"wrap_content"强制更新视图的布局

使用的代码和说明可在此处获得:

https://github.com/ea167/android-layout-wrap-content-updater

请享用!

  • 提供演示您的库使用情况的示例代码将非常有用 (4认同)

Jai*_*rea 7

使用WRAP_CONTENT更新视图大小的简单方法是将可见性更改为GONE并返回旧的可见性.

int visibility = view.getVisibility();
view.setVisibility(View.GONE);
view.setVisibility(visibility);
Run Code Online (Sandbox Code Playgroud)

  • 似乎太好了不可能,它对我不起作用 (16认同)

Bar*_*lly 0

您遇到此问题是因为您先设置布局,然后动态添加其内容。

您正在告诉布局换行到还不是他们的内容。获取内容后尝试使用布局充气器

  • 我是否需要先膨胀片段才能找到需要添加自定义视图的元素?或者我误解了你的评论? (8认同)
  • 这个答案是有史以来最糟糕的建议 (5认同)