【问题标题】:How to disable all buttons in a Layout?如何禁用布局中的所有按钮?
【发布时间】:2022-01-26 18:57:04
【问题描述】:

应用程序的工作方式如下:应用程序向用户提示 30 个按钮,用户可以通过点击猜出正确的按钮。当用户点击某个按钮时,所有按钮(比如包含这些按钮的视图)应该在播放相应的(正确或错误猜测)动画时被锁定。点击按钮本身应该被禁用,直到下一轮。动画完成后,所有之前未点击的按钮(比如包含这些按钮的视图)应该再次可用。
所以我有一个布局,其中包含另一个带有这 30 个按钮的布局:

...
    <RelativeLayout
        android:id="@+id/alphabetContainer"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">

        <include layout="@layout/alphabet" />
    </RelativeLayout>
...

现在我需要锁定按钮以防被点击,然后再解锁。所以我尝试了:

...
private RelativeLayout alphabetPanel;
...
public void onCreate(){
...
alphabetPanel = (RelativeLayout) findViewById(R.id.alphabetContainer);
...
}
...
private void lockButtons(){
alphabetPanel.setEnabled(false);
}

但这不会锁定按钮。我也试过了:

alphabetPanel.setFocusable(false);
alphabetPanel.setClickable(false);

也无济于事。似乎这一切都只依赖于布局本身,而不依赖于它包含的视图。
我还尝试添加一个假布局,通过将其放在前面,将其放置在带有按钮的布局上。这是一种解决方法,但它很棘手,因为两个布局都必须放在一个 RelativeLayout 内:

...
        blockingLayout = new RelativeLayout(this);
        blockingLayout.setLayoutParams(alphabetPanel.getLayoutParams());
...

但这很奇怪:在这种情况下,不知何故,这两种布局都会每隔一秒左右出现和消失,或者根本不出现 - 我完全无法理解,因为代码中没有使用 setVisibility() 方法!
剩下的唯一一种方法是迭代每个视图(按钮)以使其禁用而不是返回。
还有其他方法吗?
更新
最后我不得不在 xml 中添加一个“墙”布局。现在,通过使其可点击和可聚焦,它成为了一种解决方案。

【问题讨论】:

    标签: android android-layout


    【解决方案1】:

    尝试设置每个Button的xml定义

    android:duplicateParentState="true"
    

    我不确定,但我认为这应该让他们不仅看起来残疾,而且应该采取相应的行动。

    【讨论】:

    • thanx,可能是一个很好的解决方案,我想过,但问题是某些按钮必须禁用,而其他按钮则不能。这意味着我必须在启用布局视图后重新禁用每个真正禁用的按钮。
    • 您是否必须确定哪些按钮在运行时被禁用?如果没有,只需将其添加到需要禁用的部分即可。
    • 它的工作方式如下:应用程序提示用户 30 个按钮,用户可以通过点击猜出正确的按钮。因此,当用户点击某个按钮时,所有按钮都应该被​​锁定,同时播放相应的(正确或错误猜测)动画。点击按钮本身应该被禁用,直到下一轮。动画完成后,之前未点击的所有按钮应再次可用。因此,为了以这种方式实现我的目标,我必须创建带有点击按钮的数组,并且每次点击我都应该迭代这个数组以禁用点击按钮。似乎它不是一个足够的解决方案......
    【解决方案2】:

    嗯,禁用父布局不起作用..据我所知,这让我感到惊讶。

    尝试获取您包含的布局,然后禁用它。

    无论如何,如果所有其他方法都失败了,您可以随时循环浏览按钮本身。

      for(int i=0;i<relativeLayout.getChildCount();i++){
           View child=relativeLayout.getChildAt(i);
           //your processing....
           child.setEnabled(false);
      } 
    

    【讨论】:

    • 感谢回答。我上面提到的这个“无论如何”解决方案 :) “剩下的唯一一种方法是迭代每个视图以使其禁用而不是返回。”
    【解决方案3】:

    我使用扩展来锁定和解锁视图

    //lock
    fun View.lock() {
    isEnabled = false
    isClickable = false}
    //unlock
    fun View.unlock() {
    isEnabled = true
    isClickable = true}
    

    如果你想锁定视图组的所有子视图

    //lock children of the view group
    fun ViewGroup.lockAllChildren() {
    views().forEach { it.lock() }}
    
    //unlock children of the view group
    fun ViewGroup.unlockAllChildren() {
    views().forEach { it.unlock() }}
    

    【讨论】:

      【解决方案4】:

      首先定义你的按钮

      Button bit = (Button)findViewById(R.id.but);
      bit.setEnabled(false);
      

      并将启用设置为 false;

      【讨论】:

      • thanx,但这意味着我需要迭代 30 个按钮来禁用它们,而不是每次用户单击按钮时重新启用它们。不是一个方便的解决方案,特别是如果包括我对 npace 答案的评论。
      • 定义按钮数组,如:Button[] bit = new Button[30];//为 30 个按钮并运行 for 循环以禁用
      • 很明显,但我正在寻找更优雅和充分的解决方案。
      【解决方案5】:

      Java:-

      public void disableButtons(Layout layout) {
      
          // Get all touchable views
          ArrayList<View> layoutButtons = layout.getTouchables();
      
          // loop through them, if they are instances of Button, disable them.
          for(View v : layoutButtons){
              if( v instanceof Button ) {
                  ((Button)v).setEnabled(false);
              }
          }
      }
      

      科特林:-

      fun disableButtons(layout: Layout) {
      
          // Get all touchable views
          val layoutButtons: ArrayList<View> = layout.getTouchables()
      
          // loop through them, if they are instances of Button, disable them.
          for (v in layoutButtons) {
              if (v is Button) {
                  (v as Button).setEnabled(false)
              }
          }
      }
      

      将所有可触摸视图检索到一个 ArrayList 中,然后遍历它们并检查它是否是 Button 或 TextView 的实例或您想要的任何一个实例,然后禁用它!

      【讨论】:

        【解决方案6】:

        如果需要数据绑定

        import android.view.ViewGroup
        import android.widget.Button
        import androidx.core.view.children
        import androidx.databinding.BindingAdapter
        
        @BindingAdapter("disableButtons")
        fun ViewGroup.setDisableButtons(disableButtons: Boolean) {
            children.forEach {
                (it as? Button)?.isEnabled = !disableButtons
            }
        }
        

        用法:

        <androidx.constraintlayout.widget.ConstraintLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical"
                android:padding="@dimen/guideline"
                app:disableButtons="@{vm.busy}">
        ....
        </androidx.constraintlayout.widget.ConstraintLayout>
        

        【讨论】:

          【解决方案7】:

          可能在约束布局中工作。使用组小部件并添加所有按钮 ID。 在 java 代码集中为组启用 false。

          【讨论】:

            【解决方案8】:

            用于禁用任何嵌套布局中的所有按钮。

            void DisableAllButtons( ViewGroup viewGroup ){
                for( int i = 0; i < viewGroup.getChildCount(); i++ ){
                    if( viewGroup.getChildAt(i) instanceof ViewGroup ){
                        DisableAllButtons( (ViewGroup) viewGroup.getChildAt(i) );
                    }else if( viewGroup.getChildAt(i) instanceof Button ){
                        viewGroup.getChildAt(i).setEnabled( false );
                    }
                }
            }
            

            【讨论】:

              【解决方案9】:

              在 XML 中的按钮声明中写下这两行

              android:setEnabled="假" android:clickable="false"

              【讨论】:

              • thanx,就像我在问题中提到的那样,我已经尝试过了,但是没有结果。
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2018-04-02
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2015-01-02
              • 1970-01-01
              相关资源
              最近更新 更多