Stan
Stan

Reputation: 6561

How to disable all buttons in a Layout?

The way app works is the following: App prompts 30 buttons to user and user may guess the right ones by tapping. When user taps some button all the buttons (say a view containing these buttons) should be locked while corresponding (right or wrong guess) animation is playing. Tapped button by itself should be disabled till the next round. After animation is finished all not tapped previously buttons (say a view containing these buttons) should be available again.
So I have a Layout which includes another layout with these 30 buttons:

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

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

Now I need to lock the buttons from being clicked and then unlock. So I tried:

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

but this doesn't lock buttons. I also tried:

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

Doesn't help either. Seems like it all relies only to a layout by itself but not the views it contains.
Also I tried to add a fake layout to place it over layout with buttons by bringing it to the front. This is a workaround and its tricky cuz both layouts must be placed inside a RelativeLayout only:

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

but this works very strange: somehow both layouts in this case appears and disappears every second or so or doesn't appear at all - I cant understand that at all cuz there is no setVisibility() method used in code!
The only one way left is to iterate every view (button) to make it disabled and than back.
Is there any other way?
UPDATE
Finally I had to add a "wall"-layout into the xml. Now by making it clickable and focusable it becomes a solution.

Upvotes: 4

Views: 8008

Answers (9)

Style-7
Style-7

Reputation: 1209

For disable all buttons in any nested layouts.

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

Upvotes: 0

Zohidjon Akbarov
Zohidjon Akbarov

Reputation: 3223

I used extension to lock and unlock the view

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

if you want to lock all children of the view group

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

Upvotes: 0

Ankit Verma
Ankit Verma

Reputation: 718

Might work in constraint layout . Use group widget and add all the button ids. In the java code set enabled false for the group.

Upvotes: 0

Chinh Nguyen
Chinh Nguyen

Reputation: 653

In case data binding is needed

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

Usage:

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

Upvotes: 0

Gobinath Nataraj
Gobinath Nataraj

Reputation: 310

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

Kotlin:-

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

Retrieve all touchables views into an ArrayList, then loop through them and check if it is an instance of the Button or TextView or which ever you want, then disable it!

Upvotes: 0

Anshul
Anshul

Reputation: 106

write these two lines on your button declartion in XML

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

Upvotes: -2

Shubham Baldava
Shubham Baldava

Reputation: 121

firstly define your button

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

and set enabled false;

Upvotes: 0

npace
npace

Reputation: 4258

Try setting for each Button's xml definition

android:duplicateParentState="true"

I'm not sure, but I think it should make them not only to seem disabled, but also to act accordingly.

Upvotes: 3

Stefan de Bruijn
Stefan de Bruijn

Reputation: 6319

Hmm it surprises me that disabling the parent-layout doesn't work.. as far as i know it should.

Try fetching your included layout instead, and disable that.

Anyway, if all else fails you can always loop through the buttons themselves.

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

Upvotes: 1

Related Questions