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