linearlayout layout_width examples ejemplo dinamico constraint caracteristicas android android-layout

layout_width - table layout android



WRAP_CONTENT no funciona después de agregar vistas dinámicamente (8)

Estoy intentando crear un fragmento que presenta dinámicamente una serie de vistas personalizadas. El contenido principal de este diseño es un RelativeLayout anidado en un LinearLayout (para centrarlo horizontalmente), anidado en un ScrollView.

RelativeLayout tiene unas pocas vistas de texto y una vista de imagen de 9 parches diseñada para escalar con las vistas personalizadas agregadas dinámicamente. Sin embargo, la imagen (logros_bgImageView a continuación) está terminando como el tamaño de la pantalla, y no respeta el tamaño de su RelativeLayout principal incluso después de haber agregado la cantidad apropiada de vistas personalizadas. La imagen se ajusta bien cuando configuro manualmente el tamaño de logros_mainLayout (vea las líneas comentadas a continuación), pero no hace nada si trato de que wrap_content de RelativeLayout maneje su propio tamaño.

El ScrollView IS respeta el tamaño del RelativeLayout, ya que todo el contenido está presente, es simplemente el imageView que no se estira para coincidir con el contenido en este punto.

Cualquier ayuda sería apreciada ... Mis cálculos manuales no parecen ser lo suficientemente buenos para tener en cuenta los diferentes dispositivos, a pesar del hecho de que estoy considerando la densidad de la pantalla y estoy forzando manualmente el RelativeLayout a un ancho constante.

Vale la pena señalar que el tamaño medido de RelativeLayout siempre es igual a la altura de la pantalla, independientemente de si la suma de su contenido es mayor o menor que esa altura. Entonces, esencialmente, WRAP_CONTENT simplemente no hace lo que se supone que debe hacer. No tengo nada que haga referencia a ningún borde de RelativeLayout, por lo que las dependencias circulares no deberían ser un problema.

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; }


Android NO actualiza el diseño de las vistas con "wrap_content" una vez que se ha mostrado.

Por lo tanto, si agrega una vista secundaria o modifica el contenido dinámicamente, está arruinado. Estoy de acuerdo en que esto es una pesadilla y una falla real en la interfaz de usuario de Android.

Para resolverlo, escribí una clase estática que vuelve a calcular los tamaños y fuerza la actualización del diseño para las vistas con "wrap_content"

El código y las instrucciones de uso están disponibles aquí:

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

¡Disfrutar!


Configure los parámetros de diseño nuevamente (ancho y alto), justo después de agregar la vista. Esto funcionó para mí.

Si la vista principal es un FrameLayout, entonces haga algo como esto:

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);


Creo que una respuesta aún mejor que la proporcionada hasta ahora es que solo debe configurar el recurso de imagen y establecerlo como totalmente transparente cuando se infla, luego, cuando desee configurar dinámicamente la imagen, solo la hace completamente opaca (o la opacidad que le dé). querer).

Sobre la inflación:

ImageView yourImageView = (ImageView) findViewById(R.id.xmlid); yourImageView.setImageResource(somethingDrawable); yourImageView.setAlpha(0f);

Más tarde, cuando estés listo para configurar dinámicamente la imagen:

yourImageView.setAlpha(1f);


Debe usar NestedScrollView en lugar de una simple vista de desplazamiento. Aquí está mi código de diseño de actividad de muestra

<?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>

Aquí está el código para viewpager personalizado

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; } }

Función de configuración para viewpager en la actividad.

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); } }

Aquí está el código de diseño de muestra 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>


Está teniendo este problema porque primero configura su diseño y luego agrega su contenido de forma dinámica.

Usted le está diciendo al diseño que se ajuste al contenido que aún no es su. Intenta usar tu diseño de inflado después de haber capturado tu contenido


Intenta llamar requestLayout a los niños.

Hace poco tuve un problema similar y me frustré de manera similar porque cosas como invalidar y requestLayout parecían no hacer nada. Lo que no entendí es que requestLayout no se propaga a sus hijos; Se propaga hasta sus padres . Para volver a medir algo que se midió previamente, tuve que llamar a requestLayout en la vista que cambió en lugar de a la vista que realmente quería cambiar de tamaño.


Ok, resolví esto midiendo manualmente el RelativeLayout inmediatamente después de agregar todas las vistas y estableciendo la altura mainLayoutParams explícitamente. Ojalá fuera más inteligente y supiera por qué no estaba haciendo esto correctamente en primer lugar, pero bueno.

... mainLayout.measure(0, 0); ViewGroup.LayoutParams mainLayoutParams = mainLayout.getLayoutParams(); mainLayoutParams.height = mainLayout.getMeasuredHeight() + 10; ...


Una forma sencilla de actualizar el tamaño de una Vista con WRAP_CONTENT es cambiar la visibilidad a GONE y volver a la visibilidad anterior.

int visibility = view.getVisibility(); view.setVisibility(View.GONE); view.setVisibility(visibility);