例如我有:
<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
中的所有元素?
答案 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)
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中创建一个
示例:
<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);