Come ottenere attività di hosting da una vista?


187

Ho un Activitycon 3 EditTextsecondi e una vista personalizzata che funge da tastiera specializzata per aggiungere informazioni ai messaggi di posta EditTextelettronica.

Attualmente sto passando alla Activityvista in modo da poter ottenere il testo di modifica attualmente focalizzato e aggiornare i contenuti dalla tastiera personalizzata.

Esiste un modo per fare riferimento all'attività principale e focalizzare l'attenzione attualmente EditTextsenza passare l'attività nella vista?


7
La risposta corretta è di gomino.
Djunod,

Risposte:


305

Ho appena estratto quel codice sorgente da MediaRouter nella libreria di supporto ufficiale e finora funziona benissimo:

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

13
mentre? perché mentre?
Jakob Eriksson,

9
È solo un modo per passare in rassegna tutto il contesto di base, fino a quando non viene trovata l'attività o uscire dal ciclo quando viene trovato il contesto di root. Causa il contesto radice avrà un baseContext nullo, che porta alla fine del ciclo.
Gomino,

1
Molto bene ! Ho sostituito ((Activity) getContext ()) con getActivity () e funziona benissimo .... Grazie
Christian

come è stato detto, getContext () potrebbe non rappresentare sempre un oggetto Activity se View non viene chiamato da un contesto Activity. Ad esempio, non funziona per le visualizzazioni personalizzate.
Tohid

@AbhinavSaxena Potresti darci un esempio in cui questo codice fallirebbe? Anche se il metodo stesso restituisce null, non dovrebbe mai arrivarci.
Tiago,

168

i seguenti metodi possono aiutarti

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

35
Non dimenticare che getContext()potrebbe non restituire sempre un oggetto Activity se la tua vista non viene chiamata da un contesto Activity. Assicurati di pianificare questo in anticipo e fornire un fallback appropriato.
Dzhuneyt,

1
@WordPressDeveloper - Come si può creare una vista senza un'attività? Intendi la visualizzazione remota? Esistono altri casi di visualizzazioni creati al di fuori di un'attività?
AlikElzin-Kilaka,

1
Widget, frammenti, visualizzazioni remote, layoutInflaters sono tutti i casi in cui è possibile creare una vista non legata a un'attività.
Dzhuneyt,

4
@WordPressDeveloper - Quando crei una vista in un frammento, il suo contesto è ancora l'attività. I frammenti possono risiedere solo nelle attività.
AlikElzin-Kilaka,

24
Questo è un cast piuttosto pericoloso da realizzare. C'è una buona possibilità (se stai usando appcompat) che il contesto che hai è avvolto, lanciando qualcosa come un ContextThemeWrapperto Activitylanci a ClassCastException. Avresti bisogno di un modo per scartare il contesto di base (che dovrebbe essere un'attività), che di per sé è pericoloso in quanto esiste una versione nativa e v7 di ContextThemeWrapper.
alex,

12

Mi piace questa soluzione scritta in Kotlin

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

Utilizzo in Viewclasse

context.activity()

Codice decompilato:

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
grazie, lo apprezzo davvero per questa bella attività di scansione su kotlin
mochadwi,

8

Ho preso Gomino 's risposta e modificato per adattarsi perfettamente a myUtils.java modo da poter utilizzare ovunque e ogni volta che ho bisogno. Spero che qualcuno lo trovi utile :)

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

Questa non è la risposta efficace, poiché ci sono possibilità di ottenere null come restituito da questa funzione. La mia risposta è universalmente applicabile, anche se attraverso un duro lavoro e comprensione: stackoverflow.com/a/51077569/787399
Abhinav Saxena,

-1

In Android 7+ la vista non ha più accesso all'attività inclusa, quindi view.getContext()non può più essere trasmessa a un'attività.

Invece, il codice seguente funziona in Android 7+ e 6:

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

6
"In Android 7+ la vista non ha più accesso all'attività inclusa, quindi view.getContext () non può essere trasmesso a un'attività" Qualche riferimento?
Simple Fellow

@SimpleFellow come menzionato in altri commenti, getContextprobabilmente restituirà un ContextThemeWrapperquindi la vista non ha più accesso diretto all'attività. Invece, devi cercare ricorsivamente tra i contesti principali fino a trovare l'attività principale o utilizzare il metodo che ho fornito in questa risposta.
Sebas LG

-1

Proprietà estensione Kotlin per Visualizza per recuperare l'attività principale:

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

Puoi sostituire i due ifcon whene isInstance()con !is ContextWrapperois Activity
David Miguel il

Secondo @Gomino il contesto root avrà un baseContext nullo. Quindi la tua implementazione potrebbe generare ClassCastException in questo caso
David Miguel,

Questa è una vecchia soluzione. Meglio usare la soluzione di @Vlad
Fedir Tsapana il

-1

@Override public boolean shouldOverrideUrlLoading (visualizzazione WebView, richiesta WebResourceRequest) {if (request.getUrl (). GetHost (). StartWith ("pay.google.com")) {Intent intent = new Intent (Intent.ACTION_VIEW, request.getUrl ()); view.getContext () startActivity (intenti).; ritorno vero; } ... ...}


1
Ciao e benvenuto su Stack Overflow. per favore spiega la tua risposta più del semplice esempio di codice; guarda altre risposte per esempio.
Itamar Mushkin,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.