我正在尝试创建一个动态显示一系列自定义视图的片段。此布局的主要内容是嵌套在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>
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;
}
答案 0 :(得分:14)
尝试对孩子们调用requestLayout。
我最近遇到了类似的问题,同样感到沮丧的是,像invalidate和requestLayout这样的东西似乎什么也没做。我不明白的是,requestLayout并没有传播给它的孩子; it propagates up to its parents。要重新测量先前测量的内容,我不得不在更改的视图而不是我实际想要调整大小的视图上调用requestLayout。
答案 1 :(得分:9)
Android一旦显示,就不会刷新带有“wrap_content”的视图布局。
因此,如果您添加子视图或动态修改内容,那么您就搞砸了。 我确实认为这是Android UI中的噩梦和真正的缺陷!
为了解决这个问题,我编写了一个静态类,重新计算大小,并使用“wrap_content”强制更新视图的布局
此处提供了使用的代码和说明:
https://github.com/ea167/android-layout-wrap-content-updater
享受!
答案 2 :(得分:6)
使用WRAP_CONTENT更新视图大小的简单方法是将可见性更改为GONE并返回旧的可见性。
int visibility = view.getVisibility();
view.setVisibility(View.GONE);
view.setVisibility(visibility);
2014年在ANDROID JELLY BEAN上进行测试
可能不适用于更新的安卓版本
答案 3 :(得分:0)
您遇到此问题是因为您首先设置了布局,然后动态添加其内容。
你告诉布局要包装到还不是他们的内容。在抓取内容后尝试使用布局inflater
答案 4 :(得分:0)
好的,我通过在添加所有视图并显式设置mainLayoutParams高度后立即手动测量RelativeLayout来解决这个问题。我希望自己更聪明,并且知道为什么它首先没有自动正确地做到这一点,但是哦。好吧。
...
mainLayout.measure(0, 0);
ViewGroup.LayoutParams mainLayoutParams = mainLayout.getLayoutParams();
mainLayoutParams.height = mainLayout.getMeasuredHeight() + 10;
...
答案 5 :(得分:0)
您应该使用NestedScrollView而不是简单的scrollview。 这是我的示例活动布局代码
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#F0ECE6"
>
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
<android.support.design.widget.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMode="fixed"
app:tabIndicatorHeight="6dp"
android:layout_marginTop="-10dp"
app:tabGravity="fill"/>
</android.support.design.widget.AppBarLayout>
<wsit.rentguru.utility.CustomViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>
这是自定义viewpager的代码
public class CustomViewPager extends ViewPager {
private boolean enabled;
public CustomViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
this.enabled = false;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (this.enabled) {
return super.onTouchEvent(event);
}
return false;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (this.enabled) {
return super.onInterceptTouchEvent(event);
}
return false;
}
public void setPagingEnabled(boolean enabled) {
this.enabled = enabled;
}
}
活动中的viewpager的设置功能
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragment(new SampleFragment(), " ");
viewPager.setAdapter(adapter);
}
class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
@Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
@Override
public int getCount() {
return mFragmentList.size();
}
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
@Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
这是示例SampleFragment布局代码
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#F0ECE6"
android:fillViewport="true"
android:scrollbars="vertical"
android:animateLayoutChanges="true"
xmlns:android="http://schemas.android.com/apk/res/android">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#F0ECE6"
android:focusableInTouchMode="true"
>
<Spinner
android:id="@+id/product_category"
android:layout_margin="20dp"
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="@drawable/edittext_rectangle_box"
android:gravity="center|left"
android:textSize="14sp"
android:paddingLeft="10dp"
android:drawableRight="@drawable/ic_down_arrow"
/>
<Spinner
android:id="@+id/product_sub_category"
android:layout_below="@+id/product_category"
android:layout_marginRight="20dp"
android:layout_marginLeft="20dp"
android:layout_width="match_parent"
android:layout_height="40dp"
android:gravity="center|left"
android:visibility="gone"
android:paddingLeft="10dp"
android:background="@android:color/white"
android:drawableRight="@drawable/ic_down_arrow"
/>
<EditText
android:id="@+id/product_title"
android:layout_below="@+id/product_sub_category"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_marginTop="15dp"
android:background="@android:color/white"
android:hint="PRODUCT TITLE"
android:singleLine="true"
android:imeOptions="actionDone"
android:layout_width="match_parent"
android:gravity="center|left"
android:padding="10dp"
android:textSize="14sp"
android:textColorHint="#000000"
android:layout_height="40dp" />
<LinearLayout
android:id="@+id/availability_layout"
android:layout_below="@+id/product_title"
android:layout_marginRight="20dp"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/availability"
android:textStyle="bold"
android:paddingBottom="10dp"
android:textSize="14sp"
/>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:weightSum="2">
<Button
android:id="@+id/from"
android:background="@android:color/white"
android:hint="FROM"
android:layout_weight="1"
android:gravity="center|left"
android:padding="10dp"
android:textSize="14sp"
android:textStyle="normal"
android:textColorHint="#000000"
android:layout_width="0dp"
android:layout_height="40dp"
android:layout_marginRight="10dp"/>
<Button
android:id="@+id/to"
android:background="@android:color/white"
android:hint="TO"
android:layout_weight="1"
android:gravity="center|left"
android:padding="10dp"
android:textSize="14sp"
android:textColorHint="#000000"
android:layout_width="0dp"
android:layout_height="40dp"
android:layout_marginLeft="10dp"/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/product_location_layout"
android:layout_below="@+id/availability_layout"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_marginTop="20dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/product_location"
android:textStyle="bold"
android:paddingBottom="10dp"
android:textSize="14sp"
/>
<Spinner
android:id="@+id/state_spinner"
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="@drawable/edittext_rectangle_box"
android:gravity="center|left"
android:textSize="14sp"
android:layout_marginBottom="10dp"
android:drawableRight="@drawable/ic_down_arrow"
android:paddingLeft="10dp"
/>
<EditText
android:id="@+id/area"
android:background="@android:color/white"
android:hint="Area"
android:gravity="center|left"
android:padding="10dp"
android:textSize="14sp"
android:textColorHint="#000000"
android:layout_width="match_parent"
android:layout_height="40dp"
android:singleLine="true"
android:imeOptions="actionNext"
android:layout_marginBottom="10dp"
/>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:weightSum="2">
<EditText
android:id="@+id/zipCode"
android:background="@android:color/white"
android:hint="Zip Code"
android:layout_weight="1"
android:gravity="center|left"
android:padding="10dp"
android:textSize="14sp"
android:textColorHint="#000000"
android:layout_width="0dp"
android:layout_height="40dp"
android:singleLine="true"
android:imeOptions="actionNext"
android:layout_marginRight="10dp"/>
<EditText
android:id="@+id/city"
android:background="@android:color/white"
android:hint="City"
android:layout_weight="1"
android:gravity="center|left"
android:padding="10dp"
android:textSize="14sp"
android:singleLine="true"
android:imeOptions="actionDone"
android:textColorHint="#000000"
android:layout_width="0dp"
android:layout_height="40dp"
android:layout_marginLeft="10dp"/>
</LinearLayout>
</LinearLayout>
<Button
android:id="@+id/tab1_next"
android:layout_width="150dp"
android:layout_height="40dp"
android:text="NEXT"
android:layout_below="@+id/product_location_layout"
android:layout_margin="20dp"
android:layout_alignParentRight="true"
android:background="@color/next_button"
android:textColor="@android:color/white"
android:layout_marginBottom="20dp"
/>
</RelativeLayout>
</android.support.v4.widget.NestedScrollView>
答案 6 :(得分:0)
添加视图后立即再次设置布局参数(宽度和高度)。这对我有用。
如果父View是FrameLayout,那么执行以下操作:
ImageView view = (ImageView) LayoutInflater.from(activity).inflate(R.layout.image_object_view, null);
imageObjectsHolder.addView(view);
FrameLayout.LayoutParams param = new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
view.setLayoutParams(param);
答案 7 :(得分:0)
我的问题已通过将layout_width设置为某些特定的dp 得以解决。
因此从“包装内容”或“匹配父项”更改
android:layout_width="300dp"
将解决它,但我知道这不是所有情况下的解决方案。但是也许您有一些父级宽度,因此可以将其应用于textview。 高度与wrap_content一起离开,它将起作用。