Як отримати активність хостингу з подання?


187

У мене є Activity3 EditTexts та власний перегляд, який діє спеціалізована клавіатура для додавання інформації в EditTexts.

В даний час я переходжу Activityдо перегляду, щоб я міг отримати сфокусований редагування тексту та оновлення вмісту на спеціальній клавіатурі.

Чи існує спосіб посилання на батьківську діяльність та орієнтацію на даний момент, EditTextне передаючи активність перегляду?


7
Правильна відповідь - gomino.
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
Дуже добре ! Я замінив ((Діяльність) getContext ()) на getActivity (), і він працює чудово .... Дякую
Крістіан

як було сказано, getContext () не завжди може представляти об'єкт діяльності, якщо ваш погляд не викликається з контексту діяльності. Наприклад, це не працює для користувацьких переглядів.
Тохід

@AbhinavSaxena Не могли б ви навести приклад, коли цей код не зможе? Хоча сам метод повертає нульове значення, він ніколи не повинен потрапити туди.
Тіаго

168

наступні методи можуть вам допомогти

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

35
Просто не забувайте, що getContext()може не завжди повертати об’єкт активності, якщо ваш Перегляд не викликається з контексту діяльності. Не забудьте спланувати це заздалегідь і забезпечити відповідний запасний варіант.
Джунейт

1
@WordPressDeveloper - Як можна створити подання без активності? Ви маєте на увазі віддалений вигляд? Чи є інші випадки переглядів, які створюються поза діяльністю?
AlikElzin-kilaka

1
@kilaka Віджети, фрагменти, RemoteViews, LayoutInflaters - це всі випадки, коли ви можете створити подання, не пов’язане з діяльністю.
Джунейт

4
@WordPressDeveloper - Коли ви створюєте представлення у фрагменті, це все-таки активність. Фрагменти можуть міститись лише у заходах.
AlikElzin-kilaka

24
Це досить небезпечний склад. Існує хороший шанс (якщо ви використовуєте AppCompat) , що контекст у вас загортають, відкидаючи щось на кшталт ContextThemeWrapperдо Activityкине ClassCastException. Вам знадобиться спосіб розгортання базового контексту (який повинен бути заняттям), що саме по собі небезпечно, оскільки є рідна версія v7 ContextThemeWrapper.
alex

11

Мені подобається таке рішення, написане в Котліні

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

Це не є ефективною відповіддю, оскільки є шанси отримати нуль, як повернуто з цієї функції. Моя відповідь є загальноприйнятою, хоча через важку працю та розуміння: stackoverflow.com/a/51077569/787399
Abhinav Saxena

-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ймовірно, повернеться, 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 ContextWrapperis Activity
Девід Мігель

Відповідно до @Gomino, кореневий контекст матиме нульовий baseContext. Тож ваша реалізація може кинути ClassCastException у цьому випадку
Девід Мігель

Це давнє рішення. Краще використовувати розчин @Vlad
Федір Цапана

-1

@Override public boolean ShouldOverrideUrlLoading (перегляд WebView, WebResourceRequest) {if (request.getUrl (). GetHost (). BeginWith ("pay.google.com")) {Intent intennt = new Intent (Intent.ACTION_VIEW, request.getUrl ()); view.getContext (). startActivity (наміри); повернути правду; } ... ...}


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