レイアウト内のすべてのビューを無効にするにはどうすればよいですか?


83

たとえば、私は持っています:

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

LinearLayout内のすべての要素を無効にする(setEnable(false))方法はありmy_layoutますか?

回答:


98

別の方法は、各子でsetEnabled()を呼び出すことです(たとえば、無効にする前に子に対して追加のチェックを実行する場合)

LinearLayout layout = (LinearLayout) findViewById(R.id.my_layout);
for (int i = 0; i < layout.getChildCount(); i++) {
    View child = layout.getChildAt(i);
    child.setEnabled(false);
}

20
ただし、これは第1レベルの子に対してのみ機能します。ネストされたビューがある場合は、機能しません。
htafoya 2012

1つの解決策は、ViewGroupをパラメーターとして渡して、再帰関数を作成することです。クラスのすべての子を確認し、EditTextの場合は無効にします。
StoneLam

125

これは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);
       }
    }
}

良いスニペットですが、scrollviewsは引き続きスクロール可能であり、追加機能にはさらにいくつかのコードが必要です
htafoya 2012

スピナーが無効にならない理由がわからない:(
Vivek Singh

ViewPagersも、その中のビューを含め、無効になることはありません。
ラファエルC

1
setEnabled()の実装はビューのサブクラスにあるため、機能しません。つまり、ビューごとに異なる方法で実装できます。したがって、そのようなアプローチが存在するすべてのビューで機能する方法はありません
RexSplode 2017年

81

チュチュの答えは正しい方向に進んでいますが、彼の再帰は少し厄介です。私はこれがよりきれいだと思います:

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

優れたソリューション。ありがとう
Blodhgard 2015

これが正解です。それは再帰的に通過します。現在受け入れられている答えは、1レベルだけ深くなります。
ステルスラビ

24

実際、私にとっての仕事は次のとおりです。

getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE, WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);

そしてそれを元に戻すには:

getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);

3
仕事をする素敵なシンプルなソリューション!
schm1 2017年

2
このソリューションは、アクティビティ内のすべてのビューを無効にします。本当に質問に対処していません。アクティビティ内の特定のViewGroupのみを無効にすることが目標である場合はどうなりますか?
AlanKley 2018年

2
それはまさに私が探していたものです、ありがとう!しかし、ユーザーがどこかをクリックしたいかどうかを検出できますか?
Skizo-ozᴉʞS

1
グレートシンプルなソリューション
WHOATEMYNOODLES

1
1つまたはセットのビューのみを無効/有効にする場合はsetEnabled(bool)を使用するか、ビューが1つのビューのすべての子である場合は、このビューのすべての子をループしてすべて無効にしますが、このソリューションが最適だと思います(私はこの答えを意味します)ありがとうIdan
Mohammad Elsayed

21

特定のViewGroupでビューを無効にすることに関心がある場合は、興味深い、おそらく少しあいまいなを使用できますduplicateParentState。ビューステートは、押された、有効にされた、アクティブ化されたなどのブール属性のセットです。親ViewGroupに同期する各子でこれを使用するだけです。

android:duplicateParentState="true"

有効な状態だけでなく、状態全体を複製することに注意してください。これはあなたが望むものかもしれません!もちろん、このアプローチは、レイアウトXMLをロードする場合に最適です。


13

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

ビューグループを無効にするだけでは意味がないと思います。あなたがそれをしたいのなら、私がまったく同じ目的のために使った別の方法があります。グループビューの兄弟としてビューを作成します。

<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" />

実行時に、それを表示します。注:グループビューの親レイアウトは、相対レイアウトまたはフレームレイアウトのいずれかである必要があります。これがお役に立てば幸いです。


1
SpinnerがViewGroupを拡張するため、コードでSpinnerなどが無効になることはありません
qbait

12

絶望的な開発者がここを下にスクロールした場合、私にはそれを行う別のオプションがあります。これはまた、私が実験した限り、スクロールを無効にします。アイデアは、すべてのUI要素の下でRelativeLayoutでこのようなView要素を使用することです。

<View
                android:id="@+id/shade"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="@color/primaryShadow"
                android:visibility="gone"/>

したがって、ある条件の前に「なくなった」ように設定されます。次に、UIを無効にする場合は、可視性をVISIBLEに設定します。またOnClickListener、このビューを実装する必要があります。これonClickListenerはクリックイベントをキャッチし、それを基になる要素に渡しません。


1
それはそう、私が探していたものだ、私は必死だったと狂ったようにスクロールをあなたの解決策が見つかりました:D
Skizo-ozᴉʞSを

1
D;実際に、私は私の心にそれを持っていたし、私はクレイジー孤独じゃないので、同じ考えを持つ他の誰かを探していたかなりいい解決策、
リカール

12

私は個人的にこのようなものを使用します(再帰を使用した垂直ツリートラバーサル)

fun ViewGroup.deepForEach(function: View.() -> Unit) {
    this.forEach { child ->
        child.function()
        if (child is ViewGroup) {
            child.deepForEach(function)
        }
    }
}

使用法 :

   viewGroup.deepForEach { isEnabled = false }

1
エレガントなソリューション。
ラファエルC

不足しているforEach私は推測する方法
Skizo-ozᴉʞS

Skizo-ozᴉʞS@それはだandroidx.core.view方法:developer.android.com/reference/kotlin/androidx/core/view/...
Achraf AMIL

4

詳細

  • Android Studio 3.1.4
  • Kotlin 1.2.70
  • minSdkVersion19でチェックイン

解決

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

使用法

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  }

魅力のように働いた;)
Skizo-ozᴉʞS

3

レイアウト内のビューを無効にすることとまったく同じではありませんが、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);
    }

}

次に、子供がタッチイベントを受け取らないようにすることができます。

InterceptTouchEventFrameLayout layout = (InterceptTouchEventFrameLayout) findViewById(R.id.layout);
layout.setInterceptTouchEvents(true);

クリックリスナーがに設定されている場合layoutでも、トリガーされます。


この答えが大好きです。すべての子を無効にするためにViewGroupを常にトラバースするのに比べて、かなり軽量で効率的です。レイアウトがクリックに応答する問題を解決するには、setInterceptTouchEvents()でレイアウトを無効/有効にするだけです
AlanKley 2018年

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

そしてこのようなメソッドを呼び出します:

RelativeLayout rl_root = (RelativeLayout) findViewById(R.id.rl_root);
disableLL(rl_root);

2

KotlinではisDuplicateParentStateEnabled = trueViewがに追加される前に使用できますViewGroup

setDuplicateParentStateEnabledメソッドに記載されているように、子ビューに追加の状態(チェックボックスのチェック状態など)がある場合、これらは親の影響を受けません。

xmlアナログはandroid:duplicateParentState="true"です。


1

再帰関数以下の使用は、あなたの子ビューを作るために見えるか、ゴーン。最初の引数は親ビューであり、2番目の引数は親ビューの子を表示するか削除するかを決定します。true =目に見えるfalse =なくなった

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

1

これはかなり遅れた答えですが、誰かを助けるかもしれません。上記の多くの答えは良いようです。ただし、layout.xmlにネストされたビューグループがある場合。その場合、上記の回答は完全な結果を提供しない可能性があります。したがって、私は自分の意見をスニペットとして投稿しました。以下のコードを使用すると、すべてのビュー(ネストされたビューグループを含む)を無効にできます。

注:ネストされたViewGroupは推奨されないため、避けてください。

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

0

セットする

android:descendantFocusability="blocksDescendants"

ビューグループビューの場合。すべての子孫が焦点を合わせるわけではありません。


彼は焦点について尋ねていません。
ステルスラビ

0

一連のビューを無効にしたい場合、または特定の種類のビューを言いたい場合は、特定のテキストがある、またはテキストがない固定数のボタンを無効にしたい場合は、そのタイプの配列を使用して、配列要素をループできます。 setEnabled(false)プロパティを使用してボタンを無効にしている間次のような関数呼び出しでこれを行うことができます。

public void disable(){
        for(int i=0;i<9;i++){
                if(bt[i].getText().equals("")){//Button Text condition
                    bt[i].setEnabled(false);
            }
        }
}

0

EditTextコンポーネントとRadioButtonコンポーネントを適切に無効にするために、tütü応答を改善しました。さらに、ビューの可視性を変更し、無効にされたビューに透明度を追加する方法を共有しています。

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

0

私の2セントは再帰なしで機能します

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

0

最も簡単な方法は、xmlに<ビューを作成し、高さと幅にmatch_parentを指定して、ビューが他のすべてのビューの上にあることを確認します。クリックを防ぎたい場合は、ビューを表示し、パラメーターとしてnullを使用してそのビューにonClickListenerを追加します。 。

例:

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

次に、コードで:

val disableLayoutView = rootView.find<View>(R.id.disable_layout_view)
disableLayoutView.visibility = View.VISIBLE
disableLayoutView.setOnClickListener(null)

0

ルートビューを制御したいので、includeSelfフラグをに追加しましたdeepForEach

fun ViewGroup.deepForEach(includeSelf: Boolean = true, function: View.() -> Unit) {
    if (includeSelf) function()
    forEach {
        it.apply {
            function()
            (this as? ViewGroup)?.apply { deepForEach(includeSelf, function) }
        }
    }
}

-1

私の場合、RelativeLayoutまたはxmlファイルの最後にある、幅と高さがmatch_parentに設定され、属性がフォーカス可能でクリック可能が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>

-2

ビューを無効にするには、引数としてfalseを指定してメソッドsetEnabledを呼び出す必要があります。例:

Button btn = ...
btn.setEnabled(false);
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.