Android Layout делает всех детей недоступными для просмотра

Я использую Relative Layout и много кнопок в нем с TextViews и т.д. Я хочу сделать все из них не clickable, если не произойдет какое-либо событие.

Я попытался установить RelativeLayout.setClickable(false);, но все элементы внутри макета clickable.

Я знаю один способ сделать это, устанавливая каждый дочерний элемент not clickable, но это не является подходящим способом, потому что у меня много дочерних элементов, таких как текстовые представления кнопок и т.д. внутри макета. Я не могу сделать каждый дочерний элемент не интерактивным.

Здесь мой вопрос Как установить все в setClickable(false); в layout??

Ответы

Ответ 1

Когда вы говорите, что вы на самом деле имеете в виду прикосновение? События касания выполняются по элементам. Они сначала отправляются на верхний уровень, который говорит, что если он обрабатывал его, и если бы он не попадал на каждого дочернего элемента представления.

Когда создается событие касания, вызывается метод представления onTouch в цепочке, если какое-либо из них возвращает true (истинное значение "Я справлялся с этим!" ), он перестает спускаться к детям.

Чтобы сделать ваш блок relativelayout касанием и кликами для всех его детей, вам просто нужно установить onTouchListener, например:

YOUR_RELATIVE_LAYOUT.setOnTouchListener(new OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        // ignore all touch events
        return true;
    }
});

Это игнорирует все события касания, происходящие на относительном макете (и всех его дочерних элементах), который включает в себя простое касание, а затем выпуск событий (называемых щелчками).

Ответ 2

Я нашел альтернативный способ достижения этого. Вы можете создать блокировку LinearLayout поверх всех своих представлений сестры в RelativeLayout, как показано ниже:

<RelativeLayout
    android:id="@+id/rl_parent"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- the children views begins -->
    ...
    <!-- the children views ends -->

    <LinearLayout
        android:id="@+id/ll_mask"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/transparent"
        android:clickable="true"
        android:orientation="horizontal"
        android:visibility="visible"/>

</RelativeLayout>

Позже вы можете переключить видимость LinearLayout на GONE, чтобы снова разрешить просмотр детей:

mMask.setVisibility(View.VISIBLE); // blocks children
mMask.setVisibility(View.GONE); // children clickable

Ответ 3

Вы можете использовать следующую функцию, чтобы найти все дочерние представления и отменить клик.

  public void setClickable(View view) {
    if (view != null) {
        view.setClickable(false);
        if (view instanceof ViewGroup) {
            ViewGroup vg = ((ViewGroup) view);
            for (int i = 0; i < vg.getChildCount(); i++) {
                setClickable(vg.getChildAt(i));
            }
        }
    }
}

Ответ 4

Очень простой и надежный способ сделать это - создать подкласс и переопределить onInterceptTouchEvent:

public class MyRelativeLayout extends RelativeLayout {
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        // true if you do not want the children to be clickable.
        return mShouldInterceptAllTouch;
    }
}

Не нужно вызывать какие-либо из дочерних методов.

Вы по-прежнему можете вызвать setOnClickListener на свой объект myRelativeLayout. Кроме того, вы можете использовать класс в XML, как если бы вы использовали RelativeLayout

Ответ 5

Поскольку вы собираетесь выполнить щелчок для некоторых элементов в макете, когда эта конкретная функция будет выполнена,

  • Вы можете хранить статический флаг как логическое
  • Создайте статический булев глобально и объявите его как false, после выполнения конкретной функции измените его на true.
  • поэтому во всех функциях onclick, выполняющих проверку этого флага, если это правда, выполняйте необходимую функцию.

Ответ 6

Если используется библиотека Butterknife, представления могут быть сгруппированы и функциональность может быть выполнена в группе. См. http://jakewharton.github.io/butterknife/,

@BindViews({ R.id.first_name, R.id.middle_name, R.id.last_name })
List<EditText> nameViews;

Метод apply позволяет вам действовать сразу во всех представлениях в списке.

ButterKnife.apply(nameViews, DISABLE);
ButterKnife.apply(nameViews, ENABLED, false);

Интерфейсы Action и Setter позволяют указать простое поведение.

static final ButterKnife.Action<View> DISABLE = new ButterKnife.Action<View>() {
  @Override public void apply(View view, int index) {
    view.setEnabled(false);
  }
};

static final ButterKnife.Setter<View, Boolean> ENABLED = new ButterKnife.Setter<View, Boolean>() {
  @Override public void set(View view, Boolean value, int index) {
    view.setEnabled(value);
  }
};

Например, если текстовые поля сгруппированы, вы можете сделать

static final ButterKnife.Setter<TextView, Boolean> ENABLED = new ButterKnife.Setter<TextView, Boolean>() {
        @Override public void set(TextView view, Boolean value, int index) {
            view.setClickable(value);
            view.setLongClickable(value);
            if(value){
                view.setTextColor(color);
            } else {
                view.setTextColor(color);
            }
        }
    };

Ответ 7

Если вы хотите, чтобы дочерние ViewGroup не реагировали на сенсорные события, но вы хотите, ViewGroup сама ViewGroup реагировала на щелчки, например, вы можете создать свой собственный подкласс ViewGroup, переопределить onInterceptTouchEvent() и всегда возвращать true. Это будет перехватывать все сенсорные события до того, как их увидят дети, и в то же время ваша пользовательская группа ViewGroup будет реагировать на сенсорные события.

Таким образом, вместо RelativeLayout вы можете использовать свой собственный подкласс:

public class ControlFreakRelativeLayout extends RelativeLayout {
    private boolean mWithholdTouchEventsFromChildren;

    // Constructors omitted for sake of brevity

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return mWithholdTouchEventsFromChildren || super.onInterceptTouchEvent(ev);
    }

    public void setWithholdTouchEventsFromChildren(boolean withholdTouchEventsFromChildren) {
        mWithholdTouchEventsFromChildren = withholdTouchEventsFromChildren;
    }
}

Ответ 8

В качестве альтернативы вы можете создать интерактивную ViewGroup с дочерними представлениями через FrameLayout вместо RelativeLayout. Просто поместите ваши дочерние представления в FrameLayout, используя отступы и гравитацию, сделайте FrameLayout кликабельным, а все дочерние представления не кликабельными:

<FrameLayout
    android:layout_width="51dp"
    android:layout_height="59dp"
    android:layout_gravity="center"
    android:clickable="true"
    android:focusable="true"
    android:onClick="@{() -> activity.onClick()}"
    android:padding="5dp">

    <android.support.v7.widget.AppCompatImageButton
        android:layout_width="wrap_content"
        android:layout_height="29dp"
        android:layout_gravity="center"
        android:clickable="false"
        app:srcCompat="@drawable/ic_back" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|left"
        android:layout_marginBottom="5dp"
        android:layout_marginLeft="5dp"
        android:clickable="false"
        android:text="@string/back" />
</FrameLayout>

Ответ 9

Вы можете сделать общий метод, в котором вы можете написать код для отключения всех ваших представлений внутри вашего относительного макета и вызвать этот метод в onCreate(), а затем вы можете включить свой конкретный вид внутри макета вашего события.

Ответ 10

на ваших кнопках и используйте функцию setClickable и передайте значение false для него. тогда, когда ваш четный цикл снова будет включен ot и setClickable в true

Ответ 11

Проблема: то же, что и оригинальный вопрос, но другой вариант использования. я хочу прогрессбар виджет который в контейнере с прозрачными цветами фона. Я хочу отключить все клики на других элементах, которые находятся под моим прозрачным цветом фона.

Решение: просто установите свой контейнер кликабельным в моем случае. Относительный макет, он также может работать с любым другим макетом, оставьте свой макет кликабельным, если вы хотите, чтобы в соответствии с условиями в моем случае до завершения вызова API. после этого просто установите ваш родитель кликабельный false.

Android XML

<RelativeLayout
android:id="@+id/rl_parent"
android:layout_width="match_parent"
android:layout_height="match_parent">

<!-- the children views begins -->
...
<!-- the children views ends -->


</RelativeLayout>

Джава:

rl_parent.setClickable(true); // when to disable all clicks of children view

rl_parent.setClickable(false); // when to enable all clicks of children view