Как получить активность хостинга из вида?

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

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

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

Ответ 1

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

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

Ответ 2

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

  • Activity host = (Activity) view.getContext(); и
  • view.isFocused()

Ответ 3

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

Ответ 4

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

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

Использование в классе View

context.activity()

Ответ 5

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

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

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

Ответ 6

[Примечание: увидев этот ответ, посмотрите мой другой пост: fooobar.com/questions/61418/... ]

Теперь у вас есть компоненты LiveData и LifeCycleAware, чтобы вы могли избежать исключения IllegalStateException, вызванного недействительным контекстом. Вы можете использовать ViewModel (MVVM), хранящую ваши данные между воссозданиями, например, из-за смены ориентации.

Но если для вас жизненно важно знать, какая деятельность находится на переднем плане, вот решение ниже:

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

Что я делаю, я создаю собственный расширенный класс 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.

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

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

Ответ 7

Свойство расширения 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
    }
}

Ответ 8

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

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

а затем приведение, как этот (Activity) context