Como obter a Atividade de hospedagem de uma visualização?

186

Eu tenho um Activitycom 3 se EditTextuma exibição personalizada que atua como um teclado especializado para adicionar informações aos EditTexts.

Atualmente, estou passando a Activityvisualização para que eu possa obter o texto de edição atualmente focado e atualizar o conteúdo do teclado personalizado.

Existe uma maneira de fazer referência à atividade pai e obter o foco atual EditTextsem passar a atividade para a exibição?

mAndroid
fonte
7
A resposta correta é por gomino.
djunod 4/12/15

Respostas:

300

Eu apenas peguei esse código fonte do MediaRouter na biblioteca oficial de suporte e, até agora, ele funciona bem:

private Activity getActivity() {
    Context context = getContext();
    while (context instanceof ContextWrapper) {
        if (context instanceof Activity) {
            return (Activity)context;
        }
        context = ((ContextWrapper)context).getBaseContext();
    }
    return null;
}
Gomino
fonte
12
enquanto? por que enquanto?
Jakob Eriksson
9
É apenas uma maneira de exibir todo o contexto base, até que a atividade seja encontrada, ou sair do loop quando o contexto raiz for encontrado. Porque o contexto raiz terá um baseContext nulo, levando ao final do loop.
Gomino 5/05
1
Muito bom ! Troquei ((Activity) getContext ()) com getActivity () e ele funciona muito bem .... Obrigado
Christian
como foi dito, getContext () nem sempre pode representar um objeto Activity se sua View não for chamada de um contexto de Activity. Por exemplo, ele não funciona para visualizações personalizadas.
Tohid 03/08/19
@AbhinavSaxena Você poderia nos dar um exemplo em que esse código falharia? Mesmo que o método em si retorne nulo, ele nunca deve chegar lá.
Tiago
168

Os seguintes métodos podem ajudá-lo

  1. Activity host = (Activity) view.getContext(); e
  2. view.isFocused()
dira
fonte
34
Apenas não esqueça que getContext()nem sempre um objeto de Atividade pode retornar se sua Visualização não for chamada de um contexto de Atividade. Planeje isso com antecedência e forneça um retorno adequado.
Dzhuneyt
1
@WordPressDeveloper - Como uma exibição pode ser criada sem uma atividade? Você quer dizer visão remota? Existem outros casos de visualizações criados fora de uma atividade?
AlikElzin-Kilaka
1
Widgets, fragmentos, visualizações remotas e layoutInflaters do @kilaka são todos os casos em que você pode criar uma exibição que não está vinculada a uma atividade.
Dzhuneyt
4
@WordPressDeveloper - Quando você cria uma exibição em um fragmento, seu contexto ainda é a atividade. Fragmentos podem residir apenas em Atividades.
AlikElzin-Kilaka
24
Este é um elenco bastante perigoso de se fazer. Há uma boa chance (se você estiver usando o appcompat) de que o contexto que você possui seja agrupado, lançando algo como a ContextThemeWrapperpara Activitylançar a ClassCastException. Você precisaria de uma maneira de desembrulhar o contexto base (que deveria ser uma atividade), o que por si só é perigoso, pois há uma versão nativa e a v7 ContextThemeWrapper.
alex
9

Eu gosto desta solução escrita em Kotlin

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

Uso na Viewaula

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;
}
Vlad
fonte
obrigado, realmente aprecio por esta boa atividade de digitalização no kotlin
mochadwi
8

Tomei Gomino 's resposta e modificado para se encaixar perfeitamente na myUtils.java para que eu possa usá-lo onde e quando eu preciso. Espero que alguém ache ú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;
    }
}
brownieGirl
fonte
Essa não é a resposta efetiva, pois há chances de ser nulo quando retornado dessa função. Minha resposta é universalmente aplicável, embora através de algum trabalho duro e compreensão: stackoverflow.com/a/51077569/787399
Abhinav Saxena
-1

No Android 7+, a visualização não tem mais acesso à atividade anexa, portanto, view.getContext()não pode mais ser convertida em uma atividade.

Em vez disso, o código abaixo funciona no Android 7+ e 6:

private static Activity getActivity(final View view) {
    return (Activity) view.findViewById(android.R.id.content).getContext();
}
Sebas LG
fonte
6
"No Android 7+, a visualização não tem mais acesso à atividade anexa, portanto, view.getContext () não pode ser convertido em uma atividade" Alguma referência?
Companheiro Simples
O @SimpleFellow, como mencionado em outros comentários, getContextprovavelmente retornará um ContextThemeWrapperpara que o View não tenha mais acesso direto à Atividade. Em vez disso, você deve procurar recursivamente os contextos pai até encontrar a Atividade pai ou usar o método que forneci nesta resposta.
Sebas LG
-1

Propriedade de extensão Kotlin para o View para recuperar a atividade pai:

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
fonte
Você pode substituir os dois ifcom whene isInstance()com with !is ContextWrapperouis Activity
David Miguel
De acordo com @Gomino, o contexto raiz terá um baseContext nulo. Portanto, sua implementação pode gerar uma ClassCastException neste caso
David Miguel
Esta é uma solução antiga. Melhor usar a solução @Vlad
Fedir Tsapana 18/10/19
-1

@Override público booleano shouldOverrideUrlLoading (exibição na WebView, solicitação WebResourceRequest) {if (request.getUrl (). GetHost (). ()); view.getContext (). startActivity (intent); return true; } ... ...}

Tomcolins Cox Violeta CHilton c
fonte
1
Olá, e bem-vindo ao Stack Overflow. por favor, explique sua resposta mais do que apenas o exemplo de código; Veja outras respostas, por exemplo.
Itamar Mushkin