Android получить хостинг активность с точки зрения

У меня есть Activity с 3 EditTexts и пользовательский вид, который действует как специализированная клавиатура для добавления информации в EditTexts.

В настоящее время я прохожу Activity в вид, чтобы я мог получить фокусированный в данный момент текст редактирования и обновить содержимое с пользовательской клавиатуры.

Есть ли способ ссылки на родительскую активность и получить в настоящее время сосредоточены EditText не передавая активность в поле зрения?

11 ответов

Решение

Следующие методы могут помочь вам

  1. Activity host = (Activity) view.getContext(); а также
  2. view.isFocused()

Я только что вытащил этот исходный код из MediaRouter в официальную библиотеку поддержки, и пока он работает нормально:

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

Мне нравится это решение, написанное на Котлине

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

Я взял 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;
    }
}

Просто хочу отметить, что если вы знаете, что ваше представление находится внутри, вы можете просто сделать:

      FragmentManager.findFragment(this).getActivity();

Если вы не уверены, что ваш вид находится внутри Fragment затем обратитесь к другим ответам, например, Гомино, просто хотел выбросить его там.

Ответ Котлина на основе @gomino

      fun View?.getActivitySafely():Activity?{

    var context: Context = this!!.context
    while (context is ContextWrapper) {
        if (context is Activity) {
            return context
        }
        context = context.baseContext
    }
    return null
}

[Примечание: увидев этот ответ, посмотрите мой другой пост: /questions/21973257/kak-programmno-ustanovit-shrift-dlya-shrifta-spinner/21973261#21973261]

У меня другой подход к этому, и это работает.

Что я делаю, я создаю собственный расширенный класс Application и помечаю его в манифесте:

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

Затем в моих пользовательских представлениях (расширяет представления, текстовые представления для применения настроек языка и шрифтов):-

...
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 называется в onCreate(Bundle restoreState) метод. Поэтому, как только locale изменен, вы должны отправить управление обратно dashboard/home экран, чтобы сразу увидеть эффект.

Вы также можете обновить свой activity как вы знаете, какой из тока getCurrentActivity() вашей MyApplication,

Чтобы установить языковой стандарт вашего приложения, см. Раздел "Программный набор языковых стандартов".

Удачного кодирования...:-)

@Override public boolean shouldOverrideUrlLoading(представление WebView, запрос WebResourceRequest) { if(request.getUrl(). GetHost(). StartWith("pay.google.com")) { Intent intent = new Intent(Intent.ACTION_VIEW, request.getUrl()); view.getContext().startActivity(намерение); вернуть истину; } ... ... }

Для меня это сработало:

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

а затем кастинг, как это (Activity) context

Свойство расширения Kotlin для View для извлечения родительской активности:

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

В Android 7+ представление больше не имеет доступа к вложенным действиям, поэтому view.getContext() больше не может быть приведен к Деятельности.

Вместо этого приведенный ниже код работает в Android 7+ и 6:

private static Activity getActivity(final View view) {
    return (Activity) view.findViewById(android.R.id.content).getContext();
}
Другие вопросы по тегам