Как получить активность хостинга из вида?


187

У меня есть Activityс 3 EditTextс и пользовательский вид, который действует специализированная клавиатура для добавления информации в EditTextс.

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

Есть ли способ сослаться на родительское действие и сфокусироваться на текущем, EditTextне передавая действие в представление?


7
Правильный ответ - гомино.
— djunod

Ответы:


305

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

private Activity getActivity() {
    Context context = getContext();
    while (context instanceof ContextWrapper) {
        if (context instanceof Activity) {
            return (Activity)context;
        }
        context = ((ContextWrapper)context).getBaseContext();
    }
    return null;
}

13
пока? почему пока?
— Якоб Эрикссон

9
Это просто способ всплыть через весь базовый контекст, пока не будет найдено действие, или выйти из цикла, когда найден корневой контекст. Потому что корневой контекст будет иметь нулевой baseContext, ведущий к концу цикла.
— Гомино

1
Очень хорошо ! Я заменил ((Activity) getContext ()) на getActivity (), и он отлично работает .... Спасибо
— Кристиан

как уже было сказано, getContext () не всегда может представлять объект Activity, если ваш View не вызывается из контекста Activity. Например, это не работает для пользовательских представлений.
— Tohid

@AbhinavSaxena Не могли бы вы привести пример, когда этот код не будет работать? Даже если сам метод возвращает ноль, он никогда не должен туда попасть.
— Tiago

168

следующие методы могут помочь вам

  1. Activity host = (Activity) view.getContext(); и
  2. view.isFocused()

35
Только не забывайте, что getContext()не всегда может возвращать объект Activity, если ваш View не вызывается из контекста Activity. Обязательно планируйте это заранее и предоставьте соответствующий запасной вариант.
— Джунейт

1
@WordPressDeveloper - Как можно создать представление без активности? Вы имеете ввиду удаленный просмотр? Существуют ли другие случаи представлений, созданных вне Действия?
— Алик Эльзин-килака

1
@kilaka Виджеты, фрагменты, RemoteViews, LayoutInflaters - все это случаи, когда вы можете создать представление, не привязанное к Activity.
— Джунейт

4
@WordPressDeveloper - Когда вы создаете представление во фрагменте, его контекст остается активным. Фрагменты могут находиться только в Деятельности.
— АликЭльзин-килака

24
Это довольно опасный актерский состав. Существует большая вероятность (если вы используете appcompat), что контекст, который вы получили, обернут, приведя что-то вроде a ContextThemeWrapperк Activityброску a ClassCastException. Вам понадобится способ развернуть базовый контекст (который должен быть Activity), который сам по себе опасен, поскольку существует нативная версия и версия v7 ContextThemeWrapper.
— Алекс

12

Мне нравится это решение написано на Kotlin

tailrec fun Context?.activity(): Activity? = when (this) {
    is Activity -> this
    else -> (this as? ContextWrapper)?.baseContext?.activity()
}

Использование в Viewклассе

context.activity()

Декомпилированный код:

public static final Activity activity(Context context) {
    while (!(context instanceof Activity)) {
        if (!(context instanceof ContextWrapper)) {
            context = null;
        }
        ContextWrapper contextWrapper = (ContextWrapper) context;
        if (contextWrapper == null) {
            return null;
        }
        context = contextWrapper.getBaseContext();
        if (context == null) {
            return null;
        }
    }
    return (Activity) context;
}

1
спасибо, действительно ценю это за это хорошее сканирование на kotlin
— mochadwi

8

Я взял Gomino «s ответ и изменить его , чтобы полностью соответствовать в myUtils.java , так что я могу использовать его везде , где и всякий раз , когда мне нужно. Надеюсь, кто-то найдет это полезным :)

abstract class myUtils {
    public static Activity getActivity(View view) {
        Context context = view.getContext();
        while (context instanceof ContextWrapper) {
            if (context instanceof Activity) {
                return (Activity)context;
            }
            context = ((ContextWrapper)context).getBaseContext();
        }
        return null;
    }
}

Это не эффективный ответ, так как есть шансы получить значение NULL, как возвращается из этой функции. Мой ответ применим повсеместно, хотя благодаря некоторой тяжелой работе и пониманию: stackoverflow.com/a/51077569/787399
— Абхинав Саксена

-1

В Android 7+ представление больше не имеет доступа к вложенному действию, поэтому view.getContext()больше не может быть приведено к действию.

Вместо этого приведенный ниже код работает в Android 7+ и 6:

private static Activity getActivity(final View view) {
    return (Activity) view.findViewById(android.R.id.content).getContext();
}

6
«В Android 7+ вид не имеет доступа к охватывающему деятельности больше, так view.getContext () не может быть приведен к деятельности» Любые ссылки?
— Простой товарищ

@SimpleFellow, как упомянуто в других комментариях, getContextвероятно, вернет a, ContextThemeWrapperтак что представление больше не имеет прямого доступа к действию. Вместо этого вам придется рекурсивно искать в родительских контекстах, пока вы не найдете родительское действие или не воспользуетесь методом, который я предоставил в этом ответе.
— Себас LG

-1

Свойство расширения Kotlin для View для извлечения родительской активности:

val View.activity: Activity?
get() {
    var ctx = context
    while (true) {
        if (!ContextWrapper::class.java.isInstance(ctx)) {
            return null
        }
        if (Activity::class.java.isInstance(ctx)) {
            return ctx as Activity
        }
        ctx = (ctx as ContextWrapper).baseContext
    }
}

Вы могли бы заменить два ifс whenи isInstance()с !is ContextWrapperилиis Activity
— Дэвид Мигель

Согласно @Gomino корневой контекст будет иметь нулевой baseContext. Таким образом, ваша реализация может вызвать исключение ClassCastException в этом случае
— Дэвид Мигель

Это старое решение. Лучше использовать решение @Vlad
— Федир Цапана,

-1

@Override public boolean shouldOverrideUrlLoading (представление WebView, запрос WebResourceRequest) {if (request.getUrl (). GetHost (). StartWith ("pay.google.com")) {Intent intent = new Intent (Intent.ACTION_VIEW, request.getUrl ()); view.getContext () startActivity (намерение). вернуть истину; } ... ...}


1
Привет и добро пожаловать в Stack Overflow. пожалуйста, объясните свой ответ больше, чем просто пример кода; посмотрите на другие ответы, например.
— Итамар Мушкин
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.