Wie bekomme ich Hosting-Aktivitäten aus einer Sicht?

186

Ich habe eine Activitymit 3 EditTexts und eine benutzerdefinierte Ansicht, die eine spezielle Tastatur zum Hinzufügen von Informationen in die EditTexts fungiert.

Derzeit übergebe ich das Activityin die Ansicht, damit ich den aktuell fokussierten Bearbeitungstext abrufen und den Inhalt über die benutzerdefinierte Tastatur aktualisieren kann.

Gibt es eine Möglichkeit, auf die übergeordnete Aktivität zu verweisen und den aktuellen Fokus zu erhalten, EditTextohne die Aktivität in die Ansicht zu übertragen?

mAndroid
quelle
7
Die richtige Antwort ist von Gomino.
Djunod

Antworten:

300

Ich habe gerade diesen Quellcode aus dem MediaRouter in der offiziellen Support-Bibliothek abgerufen und bis jetzt funktioniert es einwandfrei :

private Activity getActivity() {
    Context context = getContext();
    while (context instanceof ContextWrapper) {
        if (context instanceof Activity) {
            return (Activity)context;
        }
        context = ((ContextWrapper)context).getBaseContext();
    }
    return null;
}
Gomino
quelle
12
während? warum während?
Jakob Eriksson
9
Es ist nur eine Möglichkeit, durch den gesamten Basiskontext zu sprudeln, bis die Aktivität gefunden wurde, oder die Schleife zu verlassen, wenn der Stammkontext gefunden wurde. Weil der Stammkontext einen Null-Basiskontext hat, der zum Ende der Schleife führt.
Gomino
1
Sehr gut ! Ich habe ((Aktivität) getContext ()) durch getActivity () ersetzt und es funktioniert gut .... Danke
Christian
Wie bereits erwähnt, stellt getContext () möglicherweise nicht immer ein Aktivitätsobjekt dar, wenn Ihre Ansicht nicht aus einem Aktivitätskontext aufgerufen wird. ZB funktioniert es nicht für benutzerdefinierte Ansichten.
Tohid
@AbhinavSaxena Können Sie uns ein Beispiel geben, bei dem dieser Code fehlschlagen würde? Obwohl die Methode selbst null zurückgibt, sollte sie niemals dort ankommen.
Tiago
168

Die folgenden Methoden können Ihnen helfen

  1. Activity host = (Activity) view.getContext();; und
  2. view.isFocused()
Dira
quelle
34
Vergessen Sie jedoch nicht, dass getContext()ein Aktivitätsobjekt möglicherweise nicht immer zurückgegeben wird, wenn Ihre Ansicht nicht aus einem Aktivitätskontext aufgerufen wird. Stellen Sie sicher, dass Sie dies im Voraus planen und einen geeigneten Fallback bereitstellen.
Dzhuneyt
1
@WordPressDeveloper - Wie kann eine Ansicht ohne Aktivität erstellt werden? Du meinst Remote View? Gibt es andere Fälle von Ansichten, die außerhalb einer Aktivität erstellt werden?
AlikElzin-Kilaka
1
@ kilaka Widgets, Fragmente, RemoteViews, LayoutInflaters sind alle Fälle, in denen Sie eine Ansicht erstellen können, die nicht an eine Aktivität gebunden ist.
Dzhuneyt
4
@WordPressDeveloper - Wenn Sie eine Ansicht in einem Fragment erstellen, ist der Kontext immer noch die Aktivität. Fragmente können sich nur in Aktivitäten befinden.
AlikElzin-Kilaka
24
Dies ist eine ziemlich gefährliche Besetzung. Es besteht eine gute Chance (wenn Sie Appcompat verwenden), dass der Kontext, den Sie haben, umbrochen wird, und wenn Sie so etwas wie ein ContextThemeWrapperto Activitywerfen , wird ein geworfen ClassCastException. Sie benötigen eine Möglichkeit, den Basiskontext (der eine Aktivität sein sollte) zu entpacken, was an sich gefährlich ist, da es eine native und v7-Version von gibt ContextThemeWrapper.
Alex
9

Ich mag diese in Kotlin geschriebene Lösung

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

Verwendung im ViewUnterricht

context.activity()

Dekompilierter Code:

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;
}
Vlad
quelle
danke, schätze es wirklich für diese nette Scan-Aktivität auf kotlin
mochadwi
8

Ich nahm Gomino ‚s Antwort und modifizierte es perfekt in myUtils.java passen , damit ich sie verwenden kann , wo immer und wann immer ich brauche. Hoffe jemand findet es hilfreich :)

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;
    }
}
brownieGirl
quelle
Dies ist keine effektive Antwort, da die Wahrscheinlichkeit besteht, dass diese Funktion null zurückgibt. Meine Antwort ist universell anwendbar, allerdings durch harte Arbeit und Verständnis: stackoverflow.com/a/51077569/787399
Abhinav Saxena
-1

In Android 7+ hat die Ansicht keinen Zugriff mehr auf die umschließende Aktivität und view.getContext()kann daher nicht mehr in eine Aktivität umgewandelt werden.

Stattdessen funktioniert der folgende Code in Android 7+ und 6:

private static Activity getActivity(final View view) {
    return (Activity) view.findViewById(android.R.id.content).getContext();
}
Sebas LG
quelle
6
„In Android 7+ die Ansicht hat keinen Zugriff auf die umschließenden Aktivität mehr, so view.getContext () nicht gecastet in einer Aktivität sein kann“ jede Bezugnahme?
Einfacher Gefährte
@SimpleFellow wird, wie in anderen Kommentaren erwähnt, getContextwahrscheinlich a zurückgeben, ContextThemeWrappersodass die Ansicht keinen direkten Zugriff mehr auf die Aktivität hat. Stattdessen müssen Sie die übergeordneten Kontexte rekursiv durchsuchen, bis Sie die übergeordnete Aktivität gefunden haben, oder die in dieser Antwort angegebene Methode verwenden.
Sebas LG
-1

Kotlin-Erweiterungseigenschaft für Ansicht zum Abrufen der übergeordneten Aktivität:

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
    }
}
Fedir Tsapana
quelle
Sie könnten die beiden ifdurch whenund die isInstance()mit !is ContextWrapperoderis Activity
David Miguel
Laut @Gomino hat der Root-Kontext einen null baseContext. Daher kann Ihre Implementierung in diesem Fall eine ClassCastException auslösen
David Miguel
Das ist eine alte Lösung. Besser zu verwenden Lösung von @Vlad
Fedir Tsapana
-1

@Override public boolean shouldOverrideUrlLoading (WebView-Ansicht, WebResourceRequest-Anforderung) {if (request.getUrl (). GetHost (). StartsWith ("pay.google.com")) {Intent intent = new Intent (Intent.ACTION_VIEW, request.getUrl ()); view.getContext (). startActivity (intent); return true; } ... ...}

Tomcolins Cox Violet CHilton c
quelle
1
Hallo, und willkommen bei Stack Overflow. Bitte erläutern Sie Ihre Antwort mehr als nur das Codebeispiel. Schauen Sie sich zum Beispiel andere Antworten an.
Itamar Mushkin