如何从视图获取托管活动?


186

我有一个Activity带有3的EditTexts和一个自定义视图,该视图充当专用键盘向EditTexts 添加信息。

目前,我正在将传递给Activity视图,以便可以获取当前焦点对准的编辑文本并通过自定义键盘更新内容。

有没有一种方法可以引用父活动并获得当前的焦点EditText而不将活动传递到视图中?


7
正确的答案是通过gomino。
djunod 2015年

Answers:


302

我只是从官方支持库中的MediaRouter中提取了源代码,到目前为止,它可以正常工作:

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

13
而?为什么呢?
雅各布·埃里克森

9
这只是使所有基本上下文冒泡的方法,直到找到活动为止,或者在找到根上下文时退出循环。因为根上下文将具有一个空的baseContext,导致循环结束。
Gomino

1
很好 !我用getActivity()替换了((Activity)getContext()),并且效果很好....谢谢
Christian

如前所述,如果未从Activity上下文调用View,则getContext()可能并不总是表示Activity对象。例如,它不适用于自定义视图。
Tohid

@AbhinavSaxena您能否举个例子说明此代码将失败?即使方法本身返回null,也永远不要到达那里。
Tiago19年

168

以下方法可能对您有帮助

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

34
只是不要忘记,getContext()如果未从Activity上下文中调用View ,则不一定会返回Activity对象。确保事先计划并提供适当的后备。
Dzhuneyt

1
@WordPressDeveloper-如何在没有活动的情况下创建视图?你是说远景?在“活动”之外创建视图的其他情况吗?
AlikElzin-kilaka 2014年

1
@kilaka窗口小部件,片段,RemoteViews和LayoutInflaters都是您可以创建与活动无关的视图的所有情况。
Dzhuneyt 2014年

4
@WordPressDeveloper-在片段中创建视图时,上下文仍然是活动。片段只能驻留在“活动”中。
2014年

24
这很危险。(如果您使用的是appcompat)很有可能打包了您所拥有的上下文,将诸如a转换ContextThemeWrapperActivity会抛出a ClassCastException。您需要一种方法来解开基本上下文(应该是一个Activity),这本身是很危险的,因为存在本机版本和v7版本ContextThemeWrapper
Alex 2015年

9

我喜欢用Kotlin编写的解决方案

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

View课堂用法

context.activity()

反编译的代码:

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

谢谢,非常感谢您在kotlin上进行的出色扫描活动
mochadwi

8

我接受了Gomino答案,并对其进行了修改,使其完全适合myUtils.java,因此我可以在任何地方,任何地方使用它。希望有人觉得有用:)

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

这不是有效的答案,因为有可能从此函数返回空值。尽管经过一些努力和理解,我的回答还是普遍适用的:stackoverflow.com/a/51077569/787399
Abhinav Saxena

-1

在Android 7+中,视图不再具有访问封闭活动的权限,因此view.getContext()无法再强制转换为活动。

相反,以下代码可在Android 7+和6中运行:

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

6
“在Android 7+中,视图不再有权访问封闭的活动,因此无法将view.getContext()强制转换为活动”
资深会员,

其他注释中提到的@SimpleFellow getContext可能会返回a,ContextThemeWrapper因此View不再具有直接访问Activity的权限。相反,您必须递归搜索父上下文,直到找到父Activity或使用我在此答案中提供的方法。
塞巴LG

-1

View的Kotlin扩展属性以检索父活动:

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

你可以代替两个ifwhenisInstance()!is ContextWrapperis Activity
大卫·米格尔

根据@Gomino,根上下文将具有空的baseContext。因此,在这种情况下,您的实现可能会引发ClassCastException
David Miguel

这是旧的解决方案。更好使用@Vlad的解决方案
Fedir Tsapana

-1

@Override public boolean shouldOverrideUrlLoading(WebView视图,WebResourceRequest请求){if(request.getUrl()。getHost()。startsWith(“ pay.google.com”)){ ());view.getContext()。startActivity(intent); 返回true;} ... ...}


1
嗨,欢迎来到Stack Overflow。请解释您的答案,而不仅仅是代码示例;例如看其他答案。
Itamar Mushkin
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.