레이아웃 내의 모든보기를 비활성화하려면 어떻게해야합니까?


84

예를 들면 다음과 같습니다.

<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
그러나 이것은 첫 번째 수준의 자식에 대해서만 작동하며 중첩 된 뷰가있는 경우 작동하지 않습니다.
htafoya 2012-07-12

한 가지 해결책은 재귀 함수를 만들고 ViewGroup을 매개 변수로 전달하는 것입니다. 모든 자식에 대한 클래스를 확인하고 EditText 인 경우 비활성화합니다.
StoneLam

126

이것은 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

스피너가 왜 비활성화되지 않았는지 확실하지 않습니다 :(
Vivek Singh

ViewPagers는 내부 뷰를 포함하여 비활성화되지 않습니다.
Raphael C

1
setEnabled () 구현이 뷰의 하위 클래스에 있기 때문에 작동하지 않습니다. 즉, 뷰마다 다르게 구현 될 수 있습니다. 그래서이 같은 접근 방식은 현존하는 모든보기 위해 작동 할 방법이 없다
RexSplode

83

투투의 대답은 올바른 방향이지만 그의 재귀는 약간 어색합니다. 나는 이것이 더 깨끗하다고 ​​생각한다.

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

이것이 정답입니다. 재귀 적으로 진행됩니다. 현재 받아 들여지는 답변은 한 단계 만 진행됩니다.
Stealth Rabbi

이것이 최고의 답변입니다. 이것은 레이아웃 내부의 모든 터치를 비활성화했습니다. 그것이 내가 원했던 것입니다. 감사!
Dinith Rukshan Kumara

24

실제로 나를 위해 일하는 것은 :

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

실행 취소하려면 :

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

3
작업을 수행하는 멋진 간단한 솔루션!
Schm1 2010 년

2
이 솔루션은 활동의 모든보기를 비활성화합니다. 실제로 질문을 해결하지 않습니다. 활동에서 특정 ViewGroup 만 비활성화하는 것이 목표 인 경우 어떻게됩니까?
AlanKley

2
바로 제가 찾고 있던 것입니다. 감사합니다 !! 하지만 사용자가 어딘가를 클릭하고 싶은지 감지 할 수 있습니까?
Skizo-ozᴉʞS

1
훌륭한 간단한 솔루션
WHOATEMYNOODLES

1
하나 또는 뷰 세트 만 비활성화 / 활성화하려면 setEnabled (bool)를 사용하거나 뷰가이 뷰의 모든 자식을 통해 한 뷰 루프의 모든 자식 인 경우 모두 비활성화하지만이 솔루션은 최선이라고 생각합니다. (나는이 대답을 의미합니다) 감사합니다 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);
   }
 }
}

뷰 그룹을 비활성화하는 데는 의미가 없다고 생각합니다. 당신이 그것을 원한다면, 정확히 같은 목적으로 사용한 또 다른 방법이 있습니다. groupview의 형제로보기 만들기 :

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

12

나는 개인적으로 이와 같은 것을 사용합니다 (재귀를 사용한 수직 트리 순회)

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

사용법 :

   viewGroup.deepForEach { isEnabled = false }

1
우아한 솔루션.
Raphael C

forEach내가 추측 하는 방법을 놓치고있다
Skizo-ozᴉʞS

Skizo - ozᴉʞS @ 그것은이다 androidx.core.view방법 : developer.android.com/reference/kotlin/androidx/core/view/...
라프 Amil

5

세부

  • Android 스튜디오 3.1.4
  • Kotlin 1.2.70
  • minSdkVersion 19에서 확인했습니다.

해결책

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

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

코 틀린에서는 사용할 수 isDuplicateParentStateEnabled = true가되기 전에 View받는 사람에 추가됩니다 ViewGroup.

setDuplicateParentStateEnabled메서드에 설명 된대로 자식보기에 추가 상태 (예 : 확인란에 대해 선택된 상태)가 있으면 부모의 영향을받지 않습니다.

xml 아날로그는 android:duplicateParentState="true".


1

아래의 재귀 함수를 사용하여 자식보기를 표시 하거나 사라 집니다. 첫 번째 인수는 부모보기이고 두 번째 인수는 부모보기의 자식을 표시할지 여부를 결정합니다. 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"

ViewGroup보기를 위해. 모든 후손은 초점을 맞추지 않습니다.


그는 초점에 대해 묻지 않습니다.
Stealth Rabbi

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

가장 쉬운 방법은 높이와 너비에 대해 match_parent를 사용하여 <View를 XML에 만들고보기가 다른 모든보기 위에 있는지 확인한 다음 클릭을 방지하려면 해당보기에 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) }
        }
    }
}

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

이렇게하면 부모보기에서 모든 상태를 한 번에 동적으로 제어 할 수 있습니다.

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

-1

뷰를 비활성화하려면 인수에 대해 false를 사용하여 setEnabled 메서드를 호출해야합니다. 전의:

Button btn = ...
btn.setEnabled(false);

-1

나를 위해 RelativeLayout 또는 너비와 높이가 match_parent로 설정된 xml 파일 끝에있는 다른 레이아웃과 focusable 속성과 clickable이 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>
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.