Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WRAP_CONTENT not working after dynamically adding views

I'm trying to create a fragment that lays out a series of custom views dynamically. The main content for this layout is a RelativeLayout nested in a LinearLayout (to center it horizontally), nested in a ScrollView.

The RelativeLayout has a few TextViews and a 9 patch ImageView that is meant to scale with the dynamically added custom views. However, the image (achievements_bgImageView below) is ending up as the size of the screen, and is not respecting the size of its parent RelativeLayout even after I've added the appropriate amount of custom views. The image scales fine when I manually set the size of achievements_mainLayout (see the commented out lines below), but does nothing if I try to let that RelativeLayout's wrap_content handle its own sizing.

The ScrollView IS respecting the size of the RelativeLayout, as all the content is present, it's simply the imageView that isn't stretching to match the content at this point.

Any help would be appreciated... My manual calculations don't seem to be good enough to account for different devices, despite the fact I'm accounting for screen density and I'm manually forcing the RelativeLayout to a constant width.

It's worth noting that the measured size of the RelativeLayout is always equal to the height of the screen, regardless of whether or not the sum of its content is greater or less than that height. So, essentially, WRAP_CONTENT is simply not doing what it's supposed to be doing. I have nothing referencing any edge of of the RelativeLayout, so circular dependencies shouldn't be a problem.

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> 

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; } 
like image 309
brainfree Avatar asked Jan 07 '14 21:01

brainfree


People also ask

Is this possible to add views in a layout dynamically?

This example demonstrates How to Dynamically Add Views into View. Step 1 − Create a new project in Android Studio, go to File ⇒ New Project and fill all required details to create a new project. Step 2 − Add the following code to res/layout/activity_main.

What is the difference between Wrap_content and Match_parent?

FILL_PARENT (renamed MATCH_PARENT in API Level 8 and higher), which means that the view wants to be as big as its parent (minus padding) WRAP_CONTENT, which means that the view wants to be just big enough to enclose its content (plus padding)


1 Answers

Try calling requestLayout on the children.

I recently had a similar problem and was similarly frustrated that things like invalidate and requestLayout seemed to do nothing. What I didn't understand is that requestLayout doesn't propagate down to its children; it propagates up to its parents. To re-measure something that was previously measured, I had to call requestLayout on the View that changed rather than the View I actually wanted to resize.

like image 78
elliotbay Avatar answered Oct 08 '22 10:10

elliotbay