Jak uzyskać Hosting Aktywność z widoku?


187

Mam Activity3 EditTexts i niestandardowy widok, który działa na specjalnej klawiaturze, aby dodać informacje do EditTexts.

Obecnie przechodzę Activitydo widoku, aby uzyskać aktualnie skoncentrowany tekst edycji i zaktualizować zawartość z niestandardowej klawiatury.

Czy istnieje sposób odwoływania się do działania nadrzędnego i uzyskiwania aktualnie skoncentrowanego EditTextbez przekazywania działania do widoku?


7
Prawidłowa odpowiedź to gomino.
djunod

Odpowiedzi:


305

Właśnie ściągnąłem ten kod źródłowy z MediaRoutera w oficjalnej bibliotece wsparcia i jak dotąd działa dobrze:

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

13
podczas? dlaczego podczas
Jakob Eriksson,

9
Jest to tylko sposób na przechodzenie przez cały kontekst podstawowy, aż do znalezienia działania, lub wyjście z pętli po znalezieniu kontekstu głównego. Ponieważ kontekst główny będzie miał zerowy kontekst podstawowy, prowadzący do końca pętli.
Gomino

1
Bardzo dobrze ! Zastąpiłem ((Activity) getContext ()) getActivity () i działa dobrze .... Dzięki
Christian

jak powiedziano, getContext () może nie zawsze reprezentować obiekt Activity, jeśli Twój Widok nie jest wywoływany z kontekstu Activity. Np. Nie działa w widokach niestandardowych.
Tohid

@AbhinavSaxena Czy możesz podać przykład, w którym ten kod się nie powiedzie? Mimo że sama metoda zwraca zero, nigdy nie powinna się tam dostać.
Tiago,

168

następujące metody mogą ci pomóc

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

35
Tylko nie zapomnij, że getContext()nie zawsze może zwrócić obiekt Activity, jeśli Twój Widok nie jest wywoływany z kontekstu Activity. Zaplanuj to z wyprzedzeniem i zapewnij odpowiednią rezerwę.
Dzhuneyt,

1
@WordPressDeveloper - Jak można utworzyć widok bez działania? Masz na myśli widok zdalny? Czy istnieją inne przypadki widoków tworzone poza działaniem?
AlikElzin-kilaka

1
Widżety @kilaka, fragmenty, RemoteView, LayoutInflaters to wszystkie przypadki, w których możesz utworzyć widok niepowiązany z działaniem.
Dzhuneyt

4
@WordPressDeveloper - Kiedy tworzysz widok we fragmencie, jego kontekst wciąż pozostaje aktywnością. Fragmenty mogą znajdować się tylko w Działaniach.
AlikElzin-kilaka

24
Jest to dość niebezpieczna obsada. Jest duża szansa (jeśli używasz AppCompat), że kontekst masz jest owinięta, rzucając coś jak ContextThemeWrappersię Activityrzuci ClassCastException. Potrzebny byłby sposób na rozpakowanie podstawowego kontekstu (który powinien być działaniem), co samo w sobie jest niebezpieczne, ponieważ istnieje natywna wersja v7 ContextThemeWrapper.
alex

11

Podoba mi się to rozwiązanie napisane w Kotlinie

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

Zastosowanie w Viewklasie

context.activity()

Kod zdekompilowany:

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
dzięki, naprawdę doceniam to za miłe skanowanie na kotlin
mochadwi

8

Wziąłem Gomino „s odpowiedź i modyfikować ją idealnie dopasować się myUtils.java więc mogę go używać wszędzie tam, gdzie i kiedy muszę. Mam nadzieję, że ktoś uzna to za pomocne :)

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

To nie jest skuteczna odpowiedź, ponieważ istnieje szansa na uzyskanie wartości null po zwróceniu z tej funkcji. Moja odpowiedź ma uniwersalne zastosowanie, choć poprzez ciężką pracę i zrozumienie: stackoverflow.com/a/51077569/787399
Abhinav Saxena

-1

W Androidzie 7+ widok nie ma już dostępu do zamykającej aktywności, więc view.getContext()nie można jej już przesyłać do działania.

Zamiast tego poniższy kod działa w systemach Android 7+ i 6:

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

6
„W Androidzie 7+ widok nie ma już dostępu do zamykającej aktywności, więc view.getContext () nie może być rzutowany na aktywność”. Czy jest jakieś odniesienie?
Simple Fellow

@SimpleFellow, jak wspomniano w innych komentarzach, getContextprawdopodobnie zwróci a, ContextThemeWrapperaby Widok nie miał już bezpośredniego dostępu do działania. Zamiast tego musisz rekurencyjnie przeszukiwać konteksty nadrzędne, dopóki nie znajdziesz działania nadrzędnego lub skorzystaj z metody podanej w tej odpowiedzi.
Sebas LG

-1

Właściwość rozszerzenia Kotlin dla widoku w celu pobrania aktywności nadrzędnej:

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

Można wymienić dwa ifz whenoraz isInstance()z !is ContextWrapperlubis Activity
David Miguel

Według @Gomino kontekst główny będzie miał zerowy baseContext. Tak więc twoja implementacja może zgłosić wyjątek ClassCastException w tym przypadku
David Miguel,

To jest stare rozwiązanie. Lepiej skorzystać z rozwiązania @Vlad
Fedir Tsapana

-1

@Override public boolean shouldOverrideUrlLoading (widok WebView, żądanie WebResourceRequest) {if (request.getUrl (). GetHost (). ()); view.getContext (). startActivity (intent); zwróć prawdę; } ... ...}


1
Cześć, witamy w Stack Overflow. proszę wyjaśnić swoją odpowiedź nie tylko przykładowy kod; spójrz na przykład na inne odpowiedzi.
Itamar Mushkin
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.