Na przykład mam:
<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>
Czy istnieje sposób na wyłączenie (setEnable (false)) wszystkich elementów wewnątrz LinearLayout my_layout
?
android
android-layout
Scit
źródło
źródło
ten jest rekurencyjny dla 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); } } }
źródło
Odpowiedź tutu jest na dobrej drodze, ale jego rekurencja jest trochę niezręczna. Myślę, że to jest czystsze:
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); } } }
źródło
A tak naprawdę, czym jest dla mnie praca:
getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE, WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
i aby to cofnąć:
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
źródło
Jeśli chcesz wyłączyć widoki w określonej grupie widoków, możesz użyć interesującego, być może nieco niejasnego
duplicateParentState
. Stan widoku to zestaw atrybutów logicznych, takich jak wciśnięty, włączony, aktywowany i inne. Po prostu użyj tego na każdym dziecku, które chcesz zsynchronizować z nadrzędną ViewGroup:android:duplicateParentState="true"
Zauważ, że powiela cały stan, a nie tylko stan włączony. To może być to, czego chcesz! Oczywiście to podejście jest najlepsze, jeśli ładujesz XML układu.
źródło
Zmieńmy kod 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); } } }
Myślę, że po prostu wyłączanie grupy widoków nie ma sensu. Jeśli chcesz to zrobić, jest inny sposób, którego użyłem do dokładnie tego samego celu. Utwórz widok jako rodzeństwo widoku grupy:
<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" />
a w czasie wykonywania spraw, by był widoczny. Uwaga: nadrzędny układ widoku grupy powinien być układem względnym lub układem ramek. Mam nadzieję, że to pomoże.
źródło
Jeśli jakiś zdesperowany programista przewinie tutaj, mam inną opcję, aby to zrobić. Co również wyłącza przewijanie, o ile z nim eksperymentowałem. Chodzi o to, aby użyć elementu View, takiego jak ten, w RelativeLayout pod wszystkimi elementami interfejsu użytkownika.
<View android:id="@+id/shade" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/primaryShadow" android:visibility="gone"/>
Więc jest ustawione na „zniknięcie” przed jakimś stanem. Następnie ustawiasz jego widoczność na WIDOCZNE, gdy chcesz wyłączyć interfejs użytkownika. Musisz również wdrożyć
OnClickListener
dla tego widoku. SpowodujeonClickListener
to przechwycenie zdarzenia kliknięcia i nie przekaże go do elementów bazowych.źródło
Osobiście używam czegoś takiego (pionowe przechodzenie po drzewie przy użyciu rekurencji)
fun ViewGroup.deepForEach(function: View.() -> Unit) { this.forEach { child -> child.function() if (child is ViewGroup) { child.deepForEach(function) } } }
stosowanie :
viewGroup.deepForEach { isEnabled = false }
źródło
forEach
Chyba brakuje mi metodyandroidx.core.view
metoda: developer.android.com/reference/kotlin/androidx/core/view/…Detale
Rozwiązanie
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) } }
Stosowanie
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 }
źródło
Chociaż nie całkiem tak samo jak wyłączenie widoki w układzie, warto wspomnieć, że można zapobiec wszystkie dzieci od otrzymania poprawki (bez konieczności recurse hierarchii układu) poprzez nadpisanie ViewGroup # onInterceptTouchEvent (MotionEvent) metodę:
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); } }
Następnie możesz uniemożliwić dzieciom otrzymywanie zdarzeń dotykowych:
InterceptTouchEventFrameLayout layout = (InterceptTouchEventFrameLayout) findViewById(R.id.layout); layout.setInterceptTouchEvents(true);
Jeśli masz włączony odbiornik kliknięć
layout
, nadal będzie on wyzwalany.źródło
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); } }
i wywołaj taką metodę:
RelativeLayout rl_root = (RelativeLayout) findViewById(R.id.rl_root); disableLL(rl_root);
źródło
W Kotlinie możesz użyć,
isDuplicateParentStateEnabled = true
zanimView
zostanie dodany doViewGroup
.Jak udokumentowano w
setDuplicateParentStateEnabled
metodzie, jeśli widok potomny ma dodatkowe stany (takie jak stan zaznaczenia dla pola wyboru), nie będzie to miało wpływu na element nadrzędny.Analogiem XML jest
android:duplicateParentState="true"
.źródło
Zastosowanie poniżej funkcji rekurencyjnej, aby Twoje dziecko poglądy widoczne lub zniknął . Pierwszy argument to widok rodzica, a drugi argument decyduje, czy chcesz, aby elementy potomne widoku rodzica były widoczne, czy zniknęły. prawda = widoczne fałsz = nie ma
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); } }
źródło
To dość opóźniona odpowiedź, ale może komuś pomóc. Wiele odpowiedzi wymienionych powyżej wydaje się być dobrych. Ale jeśli twój layout.xml ma zagnieżdżone grupy widoków. Wtedy powyższe odpowiedzi mogą nie dać pełnego wyniku. Dlatego zamieściłem swoją opinię jako fragment. Za pomocą poniższego kodu można wyłączyć wszystkie widoki (w tym zagnieżdżone grupy widoków).
UWAGA: Staraj się unikać zagnieżdżonych ViewGroups, ponieważ nie są one zalecane.
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); } } }
źródło
Zestaw
android:descendantFocusability="blocksDescendants"
dla Twojego widoku ViewGroup. Wszyscy potomkowie nie będą się skupiać.
źródło
Jeśli chcesz wyłączyć zestaw lub powiedzieć określony rodzaj widoku, powiedzmy, że chcesz wyłączyć określoną liczbę przycisków z określonym tekstem lub bez tekstu, możesz użyć tablicy tego typu i zapętlić elementy tablicy podczas wyłączania przycisków za pomocą właściwości setEnabled (false) Możesz to zrobić na wywołaniu funkcji w następujący sposób:
public void disable(){ for(int i=0;i<9;i++){ if(bt[i].getText().equals("")){//Button Text condition bt[i].setEnabled(false); } } }
źródło
Poprawiłem odpowiedź tütü, aby poprawnie wyłączyć komponenty EditText i RadioButton. Poza tym udostępniam sposób, w jaki znalazłem zmianę widoczności widoku i dodanie przezroczystości w wyłączonych widokach.
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); }
źródło
Moje dwa centy działają bez rekurencji
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 } } } }
źródło
Najłatwiejszym sposobem jest utworzenie <View w swoim xml, z match_parent dla wysokości i szerokości, upewnij się, że widok jest ponad wszystkimi innymi widokami, a następnie, jeśli chcesz zapobiec kliknięciom, uczyń go widocznym, dodaj onClickListener do tego widoku z null jako parametrem .
Przykład:
<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>
Następnie w swoim kodzie:
val disableLayoutView = rootView.find<View>(R.id.disable_layout_view) disableLayoutView.visibility = View.VISIBLE disableLayoutView.setOnClickListener(null)
źródło
Lubię mieć kontrolę nad widokiem głównym, więc dodałem
includeSelf
flagę dodeepForEach
fun ViewGroup.deepForEach(includeSelf: Boolean = true, function: View.() -> Unit) { if (includeSelf) function() forEach { it.apply { function() (this as? ViewGroup)?.apply { deepForEach(includeSelf, function) } } } }
źródło
You can have whichever children that you want to have the same state as the parents include android:duplicateParentState="true". Then if you disable the parent, whatever children you have that set on will follow suit.
Umożliwi to dynamiczne kontrolowanie wszystkich stanów jednocześnie z widoku nadrzędnego.
<LinearLayout android:id="@+id/some_parent_something" 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" android:duplicateParentState="true"/> <LinearLayout android:id="@+id/my_layout" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="wrap_content" android:duplicateParentState="true"> <TextView android:id="@+id/my_text_view" android:text="First Name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:duplicateParentState="true" /> <EditText android:id="@+id/my_edit_view" android:width="100px" android:layout_width="wrap_content" android:layout_height="wrap_content" android:duplicateParentState="true" /> <View .../> <View .../> ... <View .../> </LinearLayout> </LinearLayout>
źródło
aby wyłączyć widok, należy wywołać metodę setEnabled z wartością false jako argument. dawny:
Button btn = ... btn.setEnabled(false);
źródło
Dla mnie RelativeLayout lub inny układ na końcu pliku xml z szerokością i wysokością ustawioną na match_parent z atrybutem focusable i klikalnym ustawionym na true.
<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>
źródło