Подтвердить что ты не робот

Android make view исчезнет, ​​щелкнув за ним

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

Как это сделать на Android?

Кроме того, я понимаю, что кнопка "назад" также может помочь пользователям Android с этим - я могу использовать это как второстепенный способ закрыть представления, но некоторые из планшетов даже не используют кнопку "физический" назад больше, он был очень де-подчеркнул.

4b9b3361

Ответ 1

Легкий/глупый способ:

  • Создайте фиктивный пустой вид (скажем, ImageView без источника), заставьте его заполнить родительский

  • Если нажать, сделайте то, что хотите.

Вам нужно, чтобы корневой тег в вашем XML файле был RelativeLayout. Он будет содержать два элемента: ваш фиктивный вид (установите его положение на align the Parent Top). Другой - это ваш первоначальный вид, содержащий представления и кнопку (это представление может быть LinearLayout или что бы вы ни делали), не забудьте установить его положение на align the Parent Top)

Надеюсь, это поможет вам, удачи!

Ответ 2

Это старый вопрос, но я думал, что дам ответ, который не основан на событиях onTouch. Как было предложено RedLeader, это также можно достичь, используя фокус-события. У меня был случай, когда мне нужно было показать и скрыть пучок кнопок, расположенных в пользовательском всплывающем окне, т.е. Все кнопки были помещены в один и тот же ViewGroup. Некоторые вещи, которые вам нужно сделать, чтобы сделать эту работу:

  • Группа просмотра, которую вы хотите скрыть, должна иметь View.setFocusableInTouchMode(true). Это также можно установить в XML с помощью android:focusableintouchmode.

  • Корень вашего корня, т.е. корень всего вашего макета, возможно, какой-то линейный или относительный макет, также должен быть способен фокусироваться в соответствии с № 1 выше

  • Когда отображается группа просмотра, вы вызываете View.requestFocus(), чтобы дать ей фокус.

  • Группа просмотра должна либо переопределить View.onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect), либо реализовать свой собственный OnFocusChangeListener и использовать View.setOnFocusChangeListener()

  • Когда пользователь выходит за пределы вашего фокуса просмотра, он переносится либо в корень представления (поскольку вы устанавливаете его как настраиваемый в # 2), либо в другое представление, которое по своей сути является фокусируемым (EditText или аналогичным)

  • Когда вы обнаруживаете потерю фокуса, используя один из методов в # 4, вы знаете, что фокус перенесен на что-то вне вашей группы просмотра, и вы можете скрыть его.

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

Ответ 3

Найдите прямоугольник представления, а затем определите, находится ли событие click вне представления.

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    Rect viewRect = new Rect();
    mTooltip.getGlobalVisibleRect(viewRect);
    if (!viewRect.contains((int) ev.getRawX(), (int) ev.getRawY())) {
        setVisibility(View.GONE);
    }
    return true;
}

Если вы хотите использовать другое событие касания, попробуйте

return super.dispatchTouchEvent(ev);

Ответ 4

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

У меня есть базовая активность, в которой почти все мои действия расширяются. В нем я:

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    if (myViewIsVisible()){
            closeMyView();
        return true;
    }
    return super.dispatchTouchEvent(ev);
}

Итак, если мой вид виден, он просто закроется, и если нет, он будет вести себя как нормальное событие касания. Не уверен, что это лучший способ сделать это, но, похоже, это работает для меня.

Ответ 5

Мне нужна была особая способность не только удалять представление при нажатии на него, но также позволять клику перейти к обычному действию. Например, у меня есть отдельный layout, notification_bar.xml, который мне нужно динамически раздувать и добавлять к любой текущей активности, когда это необходимо.

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

Чтобы решить эту проблему, вы можете просто создать свою собственную DismissViewGroup, которая расширяет ViewGroup и переопределяет следующий метод:

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    ViewParent parent = getParent();
    if(parent != null && parent instanceof ViewGroup) {
        ((ViewGroup) parent).removeView(this);
    }
    return super.onInterceptTouchEvent(ev);
}

И тогда ваш динамически добавленный вид будет немного похож:

<com.example.DismissViewGroup android:id="@+id/touch_interceptor_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/transparent" ...
    <LinearLayout android:id="@+id/notification_bar_view" ...

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

Ответ 6

Внедрить onTouchListener(). Убедитесь, что координаты касания находятся за пределами координат вашего вида.

Вероятно, есть какой-то способ сделать это с помощью onFocus() и т.д. - Но я этого не знаю.

Ответ 7

Я создал пользовательскую ViewGroup для отображения информационного окна, привязанного к другому представлению (всплывающий шар). Детский вид - это информационное окно, BalloonView - полноэкранный режим для абсолютного позиционирования ребенка и перехватывания касания.

public BalloonView(View anchor, View child) {
    super(anchor.getContext());
    //calculate popup position relative to anchor and do stuff
    init(...);
    //receive child via constructor, or inflate/create default one
    this.child = child;
    //this.child = inflate(...);
    //this.child = new SomeView(anchor.getContext());
    addView(child);
    //this way I don't need to create intermediate ViewGroup to hold my View
    //but it is fullscreen (good for dialogs and absolute positioning)
    //if you need relative positioning, see @iturki answer above 
    ((ViewGroup) anchor.getRootView()).addView(this);
}

private void dismiss() {
    ((ViewGroup) getParent()).removeView(this);
}

Обработать клики внутри дочернего элемента:

child.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        //write your code here to handle clicks inside
    }
});

Отклонить мой просмотр, щелкнув снаружи БЕЗ делегирования касания к базовому виду:

BalloonView.this.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        dismiss();
    }
});

Отклонить мой взгляд, щелкнув снаружи С делегированием касания к базовому виду:

@Override
public boolean onTouchEvent(MotionEvent event) {
    dismiss();
    return false; //allows underlying View to handle touch
}

Отключить нажатие кнопки "Назад":

//do this in constructor to be able to intercept key
setFocusableInTouchMode(true);
requestFocus();

@Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_BACK) {
        dismiss();
        return true;
    }
    return super.onKeyPreIme(keyCode, event);
}

Ответ 8

поблагодарить @ituki за идею

FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/search_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#80000000"
android:clickable="true">

<LinearLayout
    android:clickable="true" // not trigger
    android:layout_width="match_parent"
    android:layout_height="300dp" 
    android:background="#FFF"
    android:orientation="vertical"
    android:padding="20dp">

    ...............

</LinearLayout>
</FrameLayout>

и java-код

mContainer = (View) view.findViewById(R.id.search_container);
    mContainer.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if(event.getAction() == MotionEvent.ACTION_DOWN){
                Log.d("aaaaa", "outsite");
                return true;
            }
            return false;
        }
    });

он работает при касании вне LinearLayout