如何禁用布局中的所有视图?

时间:2011-08-15 18:19:39

标签: android android-layout

例如我有:

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

有没有办法禁用(setEnabled(false))LinearLayout my_layout中的所有元素?

23 个答案:

答案 0 :(得分:107)

这个是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);
       }
    }
}

答案 1 :(得分:85)

另一种方法是在每个孩子上调用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);
}

答案 2 :(得分:69)

tutu的回答是在正确的轨道上,但他的递归有点尴尬。我认为这更清洁了:

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

答案 3 :(得分:14)

实际上对我有用的是:

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

并撤消它:

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

答案 4 :(得分:10)

让我们改变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);
   }
 }
}

我认为,只是让viewgroup禁用是没有意义的。如果你想这样做,我还有另一种方法用于完全相同的目的。创建视图作为您的组视图的兄弟:

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

并在运行时使其可见。注意:您的groupview的父布局应该是相对布局或框架布局。希望这会有所帮助。

答案 5 :(得分:8)

如果一些绝望的开发人员向下滚动,我还有另一种选择。就我实验而言,这也禁用了滚动。我们的想法是在所有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将捕获click事件,并且不会将其传递给基础元素。

答案 6 :(得分:7)

如果您有兴趣禁用特定ViewGroup中的视图,则可以使用有趣的,也许有些晦涩的TimeBetweenEvictionRunsMillis = 3600000。视图状态是一组布尔属性,例如按下,启用,激活等。只需在要同步到父级ViewGroup的每个孩子上使用此子项即可

duplicateParentState

请注意,它复制了整个状态,而不仅是启用状态。这可能就是您想要的!当然,如果要加载布局XML,这种方法是最好的。

答案 7 :(得分:2)

详细信息

  • Android Studio 3.1.4
  • 科林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  }

答案 8 :(得分: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);

答案 9 :(得分:1)

虽然与布局中的禁用视图不完全相同,但值得一提的是,您可以阻止所有子项接收触摸(无需递归布局层次结构) )通过覆盖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上设置了点击监听器,它仍会被触发。

答案 10 :(得分: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);
    }
}

答案 11 :(得分: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>

答案 12 :(得分:0)

最简单的方法是在xml中创建一个,并使用match_parent作为高度和宽度,确保该视图位于其他所有视图之上,然后在要防止单击时使其可见,请在该视图上添加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)

答案 13 :(得分:0)

我的两分钱功能没有递归

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

答案 14 :(得分:0)

对于我来说,RelativeLayout或xml文件末尾的任何其他布局,其宽度和高度设置为match_parent,而属性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>

答案 15 :(得分: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) }
        }
    }
}

答案 16 :(得分:0)

我个人使用类似的东西(使用递归进行垂直树遍历)

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

用法:

   viewGroup.deepForEach { isEnabled = false }

答案 17 :(得分:0)

在Kotlin中,可以在将isDuplicateParentStateEnabled = true添加到View之前使用ViewGroup

setDuplicateParentStateEnabled方法中所述,如果子视图具有其他状态(例如复选框的选中状态),则这些状态将不受父视图的影响。

xml类似物是android:duplicateParentState="true"

答案 18 :(得分:0)

这是一个相当迟缓的答案。但它可能对某人有所帮助。上面提到的许多答案似乎都很好。但是如果你的layout.xml有嵌套的视图组。然后上述答案可能无法提供完整的结果。因此我发表了我的观点作为片段。使用下面的代码,可以禁用所有视图(包括嵌套ViewGroups)。

注意:请尝试避免嵌套的ViewGroups,因为不推荐使用它们。

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

答案 19 :(得分:0)

我改进了tütü响应,以正确禁用EditText和RadioButton组件。此外,我正在分享一种方法,我发现它可以更改视图可见性并在禁用的视图中添加透明度。

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

答案 20 :(得分: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);
            }
        }
}

答案 21 :(得分:-1)

设置

android:descendantFocusability="blocksDescendants"

对于您的ViewGroup视图。所有后代都不会关注。

答案 22 :(得分:-1)

要禁用视图,必须使用false调用方法setEnabled作为参数。 例如:

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