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

时间:2011-11-26 05:58:00

标签: android android-activity android-edittext android-view

我有一个Activity,其中包含3 EditText个自定义视图,该视图用作专用键盘,可将信息添加到EditText中。

目前我正在将Activity传递到视图中,以便我可以获取当前关注的编辑文本并更新自定义键盘中的内容。

有没有办法引用父活动并获取当前关注的EditText而不将活动传递到视图中?

10 个答案:

答案 0 :(得分:256)

我刚刚从official support library的MediaRouter中提取了该源代码,到目前为止它工作正常:

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

答案 1 :(得分:167)

以下方法可以帮助您

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

答案 2 :(得分:4)

我带了Gomino' answer并对其进行了修改以完全适合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;
    }
}

答案 3 :(得分:2)

我喜欢用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;
}

答案 4 :(得分:0)

在Android 7+中,视图无法再访问封闭活动,因此view.getContext()无法再投射到活动中。

相反,下面的代码适用于Android 7+和6:

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

答案 5 :(得分:0)

[注意:看到此答案后,请参阅我的其他文章: https://stackoverflow.com/a/51100507/787399 ]

我对此有不同的处理方法,并且可行。

我要做的是创建一个自定义应用程序扩展类,并将其标记在清单中:-

public class MyApplication extends Application {

    private AppCompatActivity currentActivity;

    @Override
    public void onCreate() {
        super.onCreate();
    }

    public void setCurrentActivity(AppCompatActivity _activity){
        this.currentActivity = _activity;
    }

    public AppCompatActivity getCurrentActivity() {
        return currentActivity;
    }
}

清单中的MyApplication:-

...
<application
        android:name=".core.MyApplication"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
...

然后在我的BaseActivity(扩展AppCompatActivity的抽象类,意味着所有活动都将其扩展, 具有共同的功能,可以委托要在所有组件,片段,适配器等中访问的类。):-

...
@Override
    protected void onResume() {
        super.onResume();
        ((MyApplication) getApplicationContext()).setCurrentActivity(this);
    }
...

然后在我的customViews中(扩展视图,TextViews以应用语言环境设置和字体):-

...
private void setFontFromAsset(Context context, AttributeSet attrs, int defStyle) {
        BaseActivity activity = (BaseActivity)((MyApplication) context.getApplicationContext()).getCurrentActivity();
        FontAndLocaleManager fontAndLocaleManager = activity.getFontAndLocaleManager();
        fontAndLocaleManager.setFontFromAsset(this, R.styleable.FontButton, R.styleable.FontButton_btFontFace, attrs, defStyle);
    }
...

此解决方案使用继承,委托类的概念以及可以在任何地方访问应用程序上下文的知识(可在清单中用您自己的应用程序扩展类替换,以及活动的生命周期,在恢复时您可以告诉应用程序(MyApplication)这是您当前的活动。

现在,就像您要更改应用程序的语言环境一样,更改它的最佳位置就是在setContentView(layout_id)方法中调用activity的{​​{1}}之前。因此,一旦更改onCreate(Bundle restoreState),就必须将控件发送回locale屏幕,以便立即看到效果。

您还可以刷新dashboard/home,因为您知道activitygetCurrentActivity()中的哪个是最新的。

要设置应用程序的语言环境,请参阅Set Locale programmatically

快乐编码...:-)

答案 6 :(得分:0)

用于查看父活动的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
    }
}

答案 7 :(得分:0)

只是想注意,如果您知道您的视图在 Fragment 内,您可以这样做:

FragmentManager.findFragment(this).getActivity();

从您的 onAttachedToWindowonDraw 调用它,您不能提前调用它(例如 onFinishInflate),否则您会收到异常。

如果您不确定您的视图是否在 Fragment 内,请参考其他答案,例如Gomino,只是想把它扔在那里。

答案 8 :(得分:-1)

对我来说这很有效:

Context context = SdkUtils.getRootViewContext(getRootView());

然后按照(Activity) context

进行投射

答案 9 :(得分:-1)

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