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; }
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.
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)
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With