Por ejemplo tengo:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<Button
android:id="@+id/backbutton"
android:text="Back"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<LinearLayout
android:id="@+id/my_layout"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/my_text_view"
android:text="First Name"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<EditText
android:id="@+id/my_edit_view"
android:width="100px"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<View .../>
<View .../>
...
<View .../>
</LinearLayout>
</LinearLayout>
¿Hay alguna forma de deshabilitar (setEnable (false)) todos los elementos dentro de LinearLayout my_layout
?
android
android-layout
Scit
fuente
fuente
este es recursivo para ViewGroups
private void disableEnableControls(boolean enable, ViewGroup vg){ for (int i = 0; i < vg.getChildCount(); i++){ View child = vg.getChildAt(i); child.setEnabled(enable); if (child instanceof ViewGroup){ disableEnableControls(enable, (ViewGroup)child); } } }
fuente
La respuesta de tutu va por buen camino, pero su recursividad es un poco incómoda. Creo que esto es más limpio:
private static void setViewAndChildrenEnabled(View view, boolean enabled) { view.setEnabled(enabled); if (view instanceof ViewGroup) { ViewGroup viewGroup = (ViewGroup) view; for (int i = 0; i < viewGroup.getChildCount(); i++) { View child = viewGroup.getChildAt(i); setViewAndChildrenEnabled(child, enabled); } } }
fuente
Realmente lo que me funciona es:
getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE, WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
y deshacerlo:
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
fuente
Si está interesado en deshabilitar las vistas en un ViewGroup específico, puede usar el interesante, quizás un poco oscuro
duplicateParentState
. Un estado de vista es un conjunto de atributos booleanos como presionado, habilitado, activado y otros. Solo use esto en cada niño que desee sincronizar con ViewGroup padre:android:duplicateParentState="true"
Tenga en cuenta que duplica todo el estado y no solo el estado habilitado. ¡Esto puede ser lo que quieras! Por supuesto, este enfoque es mejor si está cargando XML de diseño.
fuente
Cambiemos el código de tütü
private void disableEnableControls(boolean enable, ViewGroup vg){ for (int i = 0; i < vg.getChildCount(); i++){ View child = vg.getChildAt(i); if (child instanceof ViewGroup){ disableEnableControls(enable, (ViewGroup)child); } else { child.setEnabled(enable); } } }
Creo que no tiene sentido simplemente desactivar el grupo de vistas. Si quieres hacerlo, hay otra forma que he usado exactamente para el mismo propósito. Cree una vista como hermana de su vista de grupo:
<View android:visibility="gone" android:id="@+id/reservation_second_screen" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="bottom" android:background="#66ffffff" android:clickable="false" />
y en tiempo de ejecución, hazlo visible. Nota: el diseño principal de su vista de grupo debe ser relativo o de marco. Espero que esto ayude.
fuente
Si algún desarrollador desesperado se desplaza hasta aquí, tengo otra opción para hacerlo. Lo que también deshabilita el desplazamiento hasta donde experimenté con él. La idea es usar el elemento View como este en un RelativeLayout, debajo de todos los elementos de la interfaz de usuario.
<View android:id="@+id/shade" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/primaryShadow" android:visibility="gone"/>
Por lo que está configurado para "desaparecer" antes de alguna condición. Y luego configura su visibilidad en VISIBLE cuando desea deshabilitar su interfaz de usuario. También tienes que implementar
OnClickListener
para esta Vista. EstoonClickListener
detectará el evento de clic y no lo pasará a los elementos subyacentes.fuente
Yo personalmente uso algo como esto (recorrido de árbol vertical usando recursividad)
fun ViewGroup.deepForEach(function: View.() -> Unit) { this.forEach { child -> child.function() if (child is ViewGroup) { child.deepForEach(function) } } }
uso:
viewGroup.deepForEach { isEnabled = false }
fuente
forEach
Supongo que falta el métodoandroidx.core.view
método: developer.android.com/reference/kotlin/androidx/core/view/…Detalles
Solución
fun View.forEachChildView(closure: (View) -> Unit) { closure(this) val groupView = this as? ViewGroup ?: return val size = groupView.childCount - 1 for (i in 0..size) { groupView.getChildAt(i).forEachChildView(closure) } }
Uso
val layout = LinearLayout(context!!) layout.forEachChildView { it.isEnabled = false } val view = View(context!!) view.forEachChildView { it.isEnabled = false } val fragment = Fragment.instantiate(context, "fragment_id") fragment.view?.forEachChildView { it.isEnabled = false }
fuente
Aunque no es lo mismo que deshabilitar vistas dentro de un diseño, vale la pena mencionar que puede evitar que todos los niños reciban toques (sin tener que repetir la jerarquía del diseño) anulando el método ViewGroup # onInterceptTouchEvent (MotionEvent) :
public class InterceptTouchEventFrameLayout extends FrameLayout { private boolean interceptTouchEvents; // ... public void setInterceptTouchEvents(boolean interceptTouchEvents) { this.interceptTouchEvents = interceptTouchEvents; } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { return interceptTouchEvents || super.onInterceptTouchEvent(ev); } }
Entonces puede evitar que los niños reciban eventos táctiles:
InterceptTouchEventFrameLayout layout = (InterceptTouchEventFrameLayout) findViewById(R.id.layout); layout.setInterceptTouchEvents(true);
Si tiene un detector de clics activado
layout
, aún se activará.fuente
private void disableLL(ViewGroup layout){ for (int i = 0; i < layout.getChildCount(); i++) { View child = layout.getChildAt(i); child.setClickable(false); if (child instanceof ViewGroup) disableLL((ViewGroup) child); } }
y llamar a un método como este:
RelativeLayout rl_root = (RelativeLayout) findViewById(R.id.rl_root); disableLL(rl_root);
fuente
En Kotlin, puede usar
isDuplicateParentStateEnabled = true
antes de queView
se agregue alViewGroup
.Como se documenta en el
setDuplicateParentStateEnabled
método, si la vista secundaria tiene estados adicionales (como estado marcado para una casilla de verificación), estos no se verán afectados por el padre.El análogo xml es
android:duplicateParentState="true"
.fuente
Utilice la siguiente función recursiva para hacer que las vistas de su hijo sean visibles o desaparezcan . El primer argumento es su vista principal y el segundo argumento decide si desea que los elementos secundarios de la vista principal estén visibles o desaparezcan. verdadero = visible falso = desaparecido
private void layoutElemanlarininGorunumunuDegistir(View view, boolean gorunur_mu_olsun) { ViewGroup view_group; try { view_group = (ViewGroup) view; Sabitler.konsolaYazdir(TAG, "View ViewGroup imiş!" + view.getId()); } catch (ClassCastException e) { Sabitler.konsolaYazdir(TAG, "View ViewGroup değilmiş!" + view.getId()); return; } int view_eleman_sayisi = view_group.getChildCount(); for (int i = 0; i < view_eleman_sayisi; i++) { View view_group_eleman = view_group.getChildAt(i); if (gorunur_mu_olsun) { view_group_eleman.setVisibility(View.VISIBLE); } else { view_group_eleman.setVisibility(View.GONE); } layoutElemanlarininGorunumunuDegistir(view_group_eleman, gorunur_mu_olsun); } }
fuente
Esta es una respuesta bastante tardía, pero podría ayudar a alguien. Muchas de las respuestas mencionadas anteriormente parecen ser buenas. Pero si su layout.xml tiene grupos de vistas anidados. Entonces, es posible que las respuestas anteriores no proporcionen un resultado completo. Por lo tanto, he publicado mi opinión como un fragmento. Con el siguiente código, se pueden deshabilitar todas las vistas (incluidos los grupos de vistas anidados).
NOTA: Intente evitar ViewGroups anidados, ya que no se recomiendan.
private void setEnableView(boolean b) { LinearLayout layout = (LinearLayout)findViewById(R.id.parent_container); ArrayList<ViewGroup> arrVg = new ArrayList<>(); for (int i = 0; i < layout.getChildCount(); i++) { View child = layout.getChildAt(i); if (child instanceof ViewGroup) { ViewGroup vg = (ViewGroup) child; arrVg.add(vg); } child.setEnabled(b); } for (int j=0;j< arrVg.size();j++){ ViewGroup vg = arrVg.get(j); for (int k = 0; k < vg.getChildCount(); k++) { vg.getChildAt(k).setEnabled(b); } } }
fuente
Conjunto
android:descendantFocusability="blocksDescendants"
para su vista ViewGroup. Todos los descendientes no se enfocarán.
fuente
Si desea deshabilitar un conjunto de, o decir un tipo particular de vista, digamos que desea deshabilitar un número fijo de botones con un texto en particular o sin texto, entonces puede usar una matriz de ese tipo y recorrer los elementos de la matriz. mientras deshabilita los botones usando la propiedad setEnabled (false) Puede hacerlo en una llamada de función como esta:
public void disable(){ for(int i=0;i<9;i++){ if(bt[i].getText().equals("")){//Button Text condition bt[i].setEnabled(false); } } }
fuente
Mejoré el tutú respuesta a desactivar adecuadamente Componentes EditText y RadioButton. Además, estoy compartiendo una forma que encontré para cambiar la visibilidad de la vista y agregar transparencia en las vistas deshabilitadas.
private static void disableEnableControls(ViewGroup view, boolean enable){ for (int i = 0; i < view.getChildCount(); i++) { View child = view.getChildAt(i); child.setEnabled(enable); if (child instanceof ViewGroup){ disableEnableControls((ViewGroup)child, enable); } else if (child instanceof EditText) { EditText editText = (EditText) child; editText.setEnabled(enable); editText.setFocusable(enable); editText.setFocusableInTouchMode(enable); } else if (child instanceof RadioButton) { RadioButton radioButton = (RadioButton) child; radioButton.setEnabled(enable); radioButton.setFocusable(enable); radioButton.setFocusableInTouchMode(enable); } } } public static void setLayoutEnabled(ViewGroup view, boolean enable) { disableEnableControls(view, enable); view.setEnabled(enable); view.setAlpha(enable? 1f: 0.3f); } public static void setLayoutEnabled(ViewGroup view, boolean enable, boolean visibility) { disableEnableControls(view, enable); view.setEnabled(enable); view.setAlpha(enable? 1f: 0.3f); view.setVisibility(visibility? View.VISIBLE: View.GONE); }
fuente
Mis dos centavos funcionan sin recursividad
package io.chord.ui.utils import android.view.View import android.view.ViewGroup import androidx.core.view.forEach class ViewUtils { companion object { fun setViewState(view: View, state: Boolean) { var depth = 0 val views: MutableMap<Int, MutableList<View>> = mutableMapOf() views[depth] = mutableListOf(view) while(true) { val currentViews = views[depth] val nextViews = mutableListOf<View>() currentViews!!.forEach { view -> if(view is ViewGroup) { view.forEach { children -> nextViews.add(children) } } } if(nextViews.size == 0) { break } depth++ views[depth] = nextViews } views.flatMap { it.value }.forEach { it.isEnabled = state } } } }
fuente
La forma más fácil es crear una <Vista en su xml, con match_parent para la altura y el ancho, asegúrese de que la vista esté por encima de todas las demás vistas, luego, cuando desee evitar los clics, hágalo visible agregue un onClickListener a esa vista con nulo como parámetro .
Ejemplo:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <Button android:id="@+id/backbutton" android:text="Back" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <LinearLayout android:id="@+id/my_layout" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/my_text_view" android:text="First Name" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <EditText android:id="@+id/my_edit_view" android:width="100px" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <View android:id="@+id/disable_layout_view" android:layout_width="match_parent" android:layout_height="match_parent" android:visibility="gone"/> </LinearLayout> </LinearLayout>
Luego en tu código:
val disableLayoutView = rootView.find<View>(R.id.disable_layout_view) disableLayoutView.visibility = View.VISIBLE disableLayoutView.setOnClickListener(null)
fuente
Me gusta tener un control sobre la vista raíz, así que agregué la
includeSelf
bandera adeepForEach
fun ViewGroup.deepForEach(includeSelf: Boolean = true, function: View.() -> Unit) { if (includeSelf) function() forEach { it.apply { function() (this as? ViewGroup)?.apply { deepForEach(includeSelf, function) } } } }
fuente
Para mí, RelativeLayout o cualquier otro diseño al final del archivo xml con el ancho y la altura establecidos en match_parent con el atributo enfocable y en el que se puede hacer clic establecido en verdadero.
<RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" android:clickable="true" android:focusable="true"> <ProgressBar android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" /> </RelativeLayout>
fuente
para deshabilitar una vista, debe llamar al método setEnabled con false como argumento. ex:
Button btn = ... btn.setEnabled(false);
fuente