¿Cómo obtener actividad de hosting desde una vista?


187

Tengo un Activitycon 3 EditTextsy una vista personalizada que actúa un teclado especializado para agregar información en el EditTexts.

Actualmente estoy pasando la Activityvista a la vista para poder obtener el texto de edición actualmente enfocado y actualizar los contenidos desde el teclado personalizado.

¿Hay alguna manera de hacer referencia a la actividad principal y obtener el foco actual EditTextsin pasar la actividad a la vista?


77
La respuesta correcta es por gomino.
djunod

Respuestas:


305

Acabo de extraer ese código fuente del MediaRouter en el biblioteca de soporte oficial y hasta ahora funciona bien:

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

13
¿mientras? porque mientras
Jakob Eriksson

9
Es solo una forma de burbujear a través de todo el contexto base, hasta que se encuentra la actividad, o salir del ciclo cuando se encuentra el contexto raíz. Porque el contexto raíz tendrá un contexto de base nulo, que conducirá al final del ciclo.
Gomino

1
Muy bien ! Reemplacé ((Activity) getContext ()) con getActivity () y funciona bien ... Gracias
Christian

como se ha dicho, getContext () puede no representar siempre un objeto Activity si su Vista no se llama desde un contexto Activity. Por ejemplo, no funciona para vistas personalizadas.
Tohid

@AbhinavSaxena ¿Podría darnos un ejemplo en el que este código podría fallar? Aunque el método en sí mismo devuelve nulo, nunca debería llegar allí.
Tiago el

168

los siguientes métodos pueden ayudarlo

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

35
Simplemente no olvide que getContext()puede que no siempre devuelva un objeto Actividad si su Vista no se llama desde un contexto Actividad. Asegúrese de planificar esto con anticipación y proporcionar una alternativa adecuada.
Dzhuneyt

1
@WordPressDeveloper - ¿Cómo se puede crear una vista sin una actividad? ¿Te refieres a la vista remota? ¿Hay otros casos de vistas que se crean fuera de una Actividad?
AlikElzin-kilaka

1
@kilaka Widgets, Fragments, RemoteViews, LayoutInflaters son todos los casos en los que puede crear una vista que no está vinculada a una Actividad.
Dzhuneyt

44
@WordPressDeveloper: cuando crea una vista en un fragmento, su contexto sigue siendo la actividad. Los fragmentos solo pueden residir en actividades.
AlikElzin-kilaka

24
Este es un elenco bastante peligroso para hacer. Existe una buena posibilidad (si está usando appcompat) de que el contexto que tiene esté envuelto, arrojando algo así como un ContextThemeWrapperto Activityarrojará un ClassCastException. Necesitaría una forma de desenvolver el contexto base (que debería ser una Actividad), que en sí mismo es peligroso ya que hay una versión nativa y v7 de ContextThemeWrapper.
alex

12

Me gusta esta solución escrita en Kotlin.

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

Uso en Viewclase

context.activity()

Código descompilado:

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
gracias, realmente lo aprecio por esta agradable actividad de escaneo en kotlin
mochadwi

8

Tomé Gomino 's respuesta y lo modificó para encajar perfectamente en myUtils.java para que pueda utilizarlo en cualquier lugar y siempre que necesito. Espero que alguien lo encuentre útil :)

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

Esta no es la respuesta efectiva, ya que hay posibilidades de obtener un valor nulo según lo devuelto por esta función. Mi respuesta es universalmente aplicable, aunque a través de un arduo trabajo y comprensión: stackoverflow.com/a/51077569/787399
Abhinav Saxena

-1

En Android 7+, la vista ya no tiene acceso a la actividad adjunta, por lo que view.getContext()ya no se puede transmitir a una Actividad.

En cambio, el siguiente código funciona en Android 7+ y 6:

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

66
"En Android 7+, la vista ya no tiene acceso a la actividad adjunta, por lo que view.getContext () no se puede transmitir a una Actividad" ¿ Alguna referencia?
Simple Fellow

@SimpleFellow, como se menciona en otros comentarios, getContextprobablemente devolverá un mensaje ContextThemeWrapperpara que la Vista ya no tenga acceso directo a la Actividad. En su lugar, debe buscar recursivamente los contextos principales hasta encontrar la Actividad principal o utilizar el método que proporcioné en esta respuesta.
Sebas LG

-1

Propiedad de extensión de Kotlin para Ver para recuperar la actividad principal:

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

Podrías reemplazar los dos ifcon wheny isInstance()con !is ContextWrapperois Activity
David Miguel

Según @Gomino, el contexto raíz tendrá un contexto base nulo. Por lo tanto, su implementación puede arrojar una ClassCastException en este caso
David Miguel

Esta es una solución vieja. Mejor solución de uso por @Vlad
Fedir Tsapana

-1

@Override public boolean shouldOverrideUrlLoading (vista WebView, solicitud WebResourceRequest) {if (request.getUrl (). GetHost (). ComienzaWith ("pay.google.com")) {Intención de intención = nueva Intención (Intent.ACTION_VIEW, request.getUrl ()); view.getContext (). startActivity (intento); volver verdadero; } ... ...}


1
Hola, y bienvenido a Stack Overflow. explique su respuesta más que solo el ejemplo de código; mira otras respuestas por ejemplo.
Itamar Mushkin
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.