Перезагрузка активности при ротации Android

В моем приложении для Android, когда я поворачиваю устройство (выдвигаю клавиатуру), мой Activity перезапускается (вызывается onCreate). Теперь это, вероятно, так, как должно быть, но я много начинаю в методе onCreate, поэтому мне нужно:

  • Поместите всю начальную настройку в другую функцию, чтобы она не потерялась при вращении устройства или
  • Сделать так, чтобы onCreate не вызывался снова и макет просто настраивался или
  • Ограничьте приложение только портретом, чтобы onCreate не вызывался.
1208
задан 19 янв. '09 в 3:28
источник поделиться
29 ответов

Использование класса приложения

В зависимости от того, что вы делаете при инициализации, вы можете рассмотреть возможность создания нового класса, который расширяет Application и переносит ваш код инициализации на переопределенный метод onCreate в этом классе.

public class MyApplicationClass extends Application {
  @Override
  public void onCreate() {
    super.onCreate();
    // TODO Put your application initialization code here.
  }
}

onCreate в классе приложения вызывается только при создании всего приложения, так что активность перезапускает изменения ориентации или изменения видимости клавиатуры, не вызывает его.

Хорошая практика - разоблачить экземпляр этого класса как одноэлементный и подвергнуть переменные приложения, которые вы инициализируете, используя геттеры и сеттеры.

ПРИМЕЧАНИЕ. Вам нужно будет указать имя вашего нового класса Application в манифесте для его регистрации и использования:

<application
    android:name="com.you.yourapp.MyApplicationClass"

Реагирование на изменения конфигурации. [UPDATE: это устарело с API 13; см. рекомендуемую альтернативу]

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

Начните с добавления android:configChanges node к манифесту активности node

android:configChanges="keyboardHidden|orientation"

или для Android 3.2 (уровень API 13) и более новый:

android:configChanges="keyboardHidden|orientation|screenSize"

Затем в рамках Activity переопределите метод onConfigurationChanged и вызовите setContentView, чтобы заставить макет графического интерфейса быть переделанным в новой ориентации.

@Override
public void onConfigurationChanged(Configuration newConfig) {
  super.onConfigurationChanged(newConfig);
  setContentView(R.layout.myLayout);
}
889
ответ дан 19 янв. '09 в 11:47
источник

Обновление для Android 3.2 и выше:

Предостережение. Начиная с Android 3.2 (уровень API 13), размер экрана также изменяется, когда устройство переключается между портретной и альбомной ориентацией. Таким образом, если вы хотите предотвратить перезапуск во время изменения ориентации при разработке для уровня API 13 или выше (как указано атрибутами minSdkVersion и targetSdkVersion), вы должны добавить значение "screenSize" в дополнение к значению "orientation". То есть, вы должны объявить android:configChanges="orientation|screenSize". Однако, если ваше приложение нацелено на уровень API 12 или ниже, ваша деятельность всегда обрабатывает это изменение самой конфигурации (это изменение конфигурации не перезапускает вашу активность даже при работе на устройстве Android 3.2 или более поздней версии).

173
ответ дан 04 марта '12 в 0:56
источник

Вместо того, чтобы пытаться полностью отключить onCreate(), возможно, попробуйте передать Bundle savedInstanceState в событие, чтобы узнать, является ли оно нулевым или нет.

Например, если у меня есть некоторая логика, которая должна выполняться, когда Activity действительно создан, а не при каждом изменении ориентации, я запускаю эту логику только в onCreate(), только если savedInstanceState имеет значение null.

В противном случае, я все еще хочу, чтобы макет правильно перерисовывал ориентацию.

public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_game_list);

        if(savedInstanceState == null){
            setupCloudMessaging();
        }
}

не уверен, что это окончательный ответ, но он работает для меня.

109
ответ дан 05 авг. '12 в 0:04
источник

что я сделал...

в манифесте, в раздел активности, добавлено:

android:configChanges="keyboardHidden|orientation"

в коде для операции, реализованной:

//used in onCreate() and onConfigurationChanged() to set up the UI elements
public void InitializeUI()
{
    //get views from ID's
    this.textViewHeaderMainMessage = (TextView) this.findViewById(R.id.TextViewHeaderMainMessage);

    //etc... hook up click listeners, whatever you need from the Views
}

//Called when the activity is first created.
@Override
public void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    InitializeUI();
}

//this is called when the screen rotates.
// (onCreate is no longer called when screen rotates due to manifest, see: android:configChanges)
@Override
public void onConfigurationChanged(Configuration newConfig)
{
    super.onConfigurationChanged(newConfig);
    setContentView(R.layout.main);

    InitializeUI();
}
93
ответ дан 04 янв. '11 в 4:26
источник

То, что вы описываете, - это поведение по умолчанию. Вы должны сами определять и обрабатывать эти события, добавляя:

android:configChanges

в ваш манифест, а затем изменения, которые вы хотите обработать. Поэтому для ориентации вы будете использовать:

android:configChanges="orientation"

а для открытой или закрытой клавиатуры вы будете использовать:

android:configChanges="keyboardHidden"

Если вы хотите обрабатывать оба, вы можете просто отделить их командой pipe, например:

android:configChanges="keyboardHidden|orientation"

Это вызовет метод onConfigurationChanged во всех действиях, которые вы вызываете. Если вы переопределите метод, который вы можете передать в новых значениях.

Надеюсь, что это поможет.

57
ответ дан 19 янв. '09 в 5:28
источник

Я только что открыл эти знания:

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

android:configChanges="keyboardHidden|orientation"

который имеет дополнительное преимущество, которое он всегда работает.

Знание бонуса заключается в том, что опускание keyboardHidden может показаться логичным, но оно вызывает сбои в эмуляторе (по крайней мере, для Android 2.1): указание только orientation сделает вызов эмулятора как OnCreate, так и onConfigurationChanged иногда и только OnCreate в другое время.

Я не видел сбоя на устройстве, но я слышал об отсутствии эмулятора для других. Поэтому стоит документировать.

39
ответ дан 23 дек. '10 в 0:50
источник

Вы также можете рассмотреть возможность использования платформы Android для хранения данных в разных изменениях ориентации: onRetainNonConfigurationInstance() и getLastNonConfigurationInstance().

Это позволяет вам сохранять данные в конфигурационных изменениях, таких как информация, которую вы, возможно, получили из выборки сервера, или что-то еще, которое было вычислено в onCreate, или с тех пор, а также позволяет Android повторно развернуть ваш Activity, используя xml файл для используемой ориентации.

См. здесь или здесь.

Следует отметить, что эти методы теперь устаревают (хотя и более гибкие, чем обработка ориентации, меняют сами, как предлагают большинство из вышеперечисленных решений) с рекомендацией, что все переключаются на Fragments и вместо этого используют setRetainInstance(true) для каждого Fragment, который вы хотите сохранить.

33
ответ дан 22 сент. '11 в 6:03
источник

Подход полезен, но является неполным при использовании фрагментов.

Фрагменты обычно воссоздаются при изменении конфигурации. Если вы этого не хотите, используйте

setRetainInstance(true); в конструкторе (-ях) фрагмента

Это приведет к сохранению фрагментов во время изменения конфигурации.

http://developer.android.com/reference/android/app/Fragment.html#setRetainInstance (boolean)

28
ответ дан 21 сент. '12 в 12:09
источник

Я просто добавил

     android:configChanges="keyboard|keyboardHidden|orientation"

в файле манифеста и не добавил любой метод onConfigurationChanged в мою активность.

Итак, каждый раз, когда клавиатура открывается или ничего не происходит.

21
ответ дан 09 авг. '12 в 12:58
источник
 onConfigurationChanged is called when the screen rotates. 
 (onCreate is no longer called when screen rotates due to manifest, see:  
 android:configChanges)

В какой части манифеста говорится, что "не называть onCreate()"?

Кроме того, Документы Google говорят, чтобы избежать использования android:configChanges (кроме как в крайнем случае).... Но тогда альтернативные методы, которые они предлагают всем DO, используют android:configChanges.

По моему опыту, эмулятор ВСЕГДА называет onCreate() при вращении.
Но на 1-2 устройствах, на которых я запускаю один и тот же код, нет. (Не знаю, почему будет какая-то разница.)

13
ответ дан 01 февр. '12 в 18:55
источник

Добавьте эту строку в свой манифест: -

android:configChanges="orientation|keyboard|keyboardHidden|screenSize|screenLayout|uiMode"

и этот фрагмент к активности: -

@Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
    }
13
ответ дан 23 июля '14 в 13:00
источник

Изменения в манифесте Android:

android:configChanges="keyboardHidden|orientation" 

Дополнения, которые должны быть сделаны внутри действия:

public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    // Checks the orientation of the screen
    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
    } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
        Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
    }
}
12
ответ дан 11 нояб. '11 в 15:20
источник

Существует несколько способов сделать это:

Сохранить состояние активности

Состояние активности можно сохранить в onSaveInstanceState.

@Override
public void onSaveInstanceState(Bundle outState) {
    /*Save your data to be restored here
    Example : outState.putLong("time_state", time); , time is a long variable*/
    super.onSaveInstanceState(outState);
}

а затем используйте bundle для восстановления состояния.

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    if(savedInstanceState!= null){
       /*When rotation occurs
        Example : time = savedInstanceState.getLong("time_state", 0); */
    } else {
      //When onCreate is called for the first time
    }
}

Изменение ориентации рукоятки самостоятельно

Другой альтернативой является управление изменениями ориентации самостоятельно. Но это не считается хорошей практикой.

Добавьте это в файл манифеста.

android:configChanges="keyboardHidden|orientation"

для Android 3.2 и более поздних версий:

android:configChanges="keyboardHidden|orientation|screenSize"

@Override
public void onConfigurationChanged(Configuration config) {
    super.onConfigurationChanged(config);

if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
        //Handle rotation from landscape to portarit mode here
    } else if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE){
        //Handle rotation from portrait to landscape mode here
    }
}

Ограничить вращение

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

Добавьте это в тег активности в файле манифеста:

        android:screenOrientation="portrait"

Или реализуйте это программно в своей деятельности:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
11
ответ дан 07 янв. '16 в 21:55
источник

Метод onCreate по-прежнему вызывается даже при изменении orientation андроида. Поэтому перемещение всех тяжелых функций этого метода не поможет вам

11
ответ дан 21 янв. '10 в 13:40
источник

Как я нашел это, используйте события onRestoreInstanceState и onSaveInstanceState, чтобы сохранить что-то в Bundle (даже если вам не нужны какие-либо переменные, просто поместите что-то там, чтобы Bundle не пусто). Затем, по методу onCreate, проверьте, является ли Bundle пустым, а если это так, выполните инициализацию, если нет, тогда сделайте это.

10
ответ дан 21 дек. '12 в 23:15
источник

Поместите код ниже в свой тег <activity> в Manifest.xml:

android:configChanges="screenLayout|screenSize|orientation"
10
ответ дан 21 авг. '14 в 14:55
источник

Несмотря на то, что это не "способ Android", я получил очень хорошие результаты, самостоятельно обработав изменения ориентации и просто переставив виджеты в представление, чтобы учитывать измененную ориентацию. Это быстрее, чем любой другой подход, потому что ваши взгляды не нужно сохранять и восстанавливать. Он также предоставляет пользователям более бесшовные впечатления, потому что смещенные виджеты - это точно такие же виджеты, просто перемещенные и/или измененные. Таким образом можно сохранить не только состояние модели, но и состояние отображения.

RelativeLayout иногда может быть хорошим выбором для представления, которое время от времени должно переориентироваться. Вы просто предоставляете набор параметров макета портрета и набор параметров ландшафтного макета с разными правилами относительного позиционирования для каждого из них для каждого дочернего виджета. Затем в вашем методе onConfigurationChanged() вы передаете соответствующий вызов setLayoutParams() для каждого дочернего элемента. Если какой-либо дочерний элемент управления сам должен переориентироваться на внутреннем уровне, вы просто вызываете метод для этого ребенка для выполнения переориентации. Этот ребенок аналогичным образом называет методы любого из своих дочерних элементов управления, которые нуждаются в внутренней переориентации и т.д.

9
ответ дан 16 марта '12 в 12:13
источник

Очень просто выполнить следующие действия:

<activity
    android:name=".Test"
    android:configChanges="orientation|screenSize"
    android:screenOrientation="landscape" >
</activity>

Это работает для меня:

Примечание: ориентация зависит от вашего удовлетворения

8
ответ дан 14 дек. '15 в 9:39
источник

Примечание: Я отправляю этот ответ, если кто-то в будущем сталкивается с той же проблемой, что и я. Для меня следующая строка не была достаточной:

android:configChanges="orientation"

Когда я поворачивал экран, метод `onConfigurationChanged (Configuration newConfig) не вызывался.

Решение: Мне также пришлось добавить "screenSize", даже если проблема была связана с ориентацией. Поэтому в файле AndroidManifest.xml добавьте следующее:

android:configChanges="keyboardHidden|orientation|screenSize"

Затем реализуем метод onConfigurationChanged(Configuration newConfig)

6
ответ дан 24 апр. '14 в 17:40
источник

вам нужно использовать метод onSavedInstanceState для хранения всего значения в его параметре, это пакет bundle

@Override
    public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
        super.onSaveInstanceState(outState, outPersistentState);
        outPersistentState.putBoolean("key",value);
    }

и используйте

@Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        savedInstanceState.getBoolean("key");
    } 

для извлечения и установки значения для просмотра объектов он будет обрабатывать вращения экрана

5
ответ дан 07 дек. '16 в 13:23
источник

Каждый раз, когда экран поворачивается, открытая активность завершается, а функция onCreate() вызывается снова.

1. Вы можете сделать одну вещь, чтобы сохранить состояние активности, когда экран повернут так, что вы можете восстановить все старые вещи, когда снова будет вызвана операция onCreate().   Обратитесь к этой ссылке

2. Если вы хотите предотвратить перезапуск активности, просто поместите следующие строки в файл manifest.xml.

  <activity android:name=".Youractivity"
  android:configChanges="orientation|screenSize"/>
4
ответ дан 03 февр. '17 в 13:47
источник

Исправить ориентацию экрана (пейзаж или портрет) в AndroidManifest.xml

android:screenOrientation="portrait" или android:screenOrientation="landscape"

для этого ваш метод onResume() не вызывается.

2
ответ дан 15 февр. '13 в 14:14
источник

В разделе активности manifest добавьте:

android:configChanges="keyboardHidden|orientation"
2
ответ дан 10 марта '17 в 11:14
источник

Поместите этот ниже код в Activity в Android Manifest.

android:configChanges="orientation"

Это не приведет к перезапуску вашей активности, когда вы измените ориентацию.

2
ответ дан 29 июля '13 в 10:09
источник

Используйте orientation прослушиватель для выполнения различных задач с различной ориентацией.

@Override
public void onConfigurationChanged(Configuration myConfig) 
{
    super.onConfigurationChanged(myConfig);
    int orient = getResources().getConfiguration().orientation; 
    switch(orient) 
    {
       case Configuration.ORIENTATION_LANDSCAPE:
          setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
                    break;
       case Configuration.ORIENTATION_PORTRAIT:
          setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
                    break;
       default:
          setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
    }
}
2
ответ дан 04 февр. '15 в 9:58
источник

Через некоторое время проб и ошибок я нашел решение, которое соответствует моим потребностям в большинстве ситуаций. Вот код:

Конфигурация манифеста:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.pepperonas.myapplication">

    <application
        android:name=".App"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".MainActivity"
            android:configChanges="orientation|keyboardHidden|screenSize">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>

</manifest>

MainActivity:

import android.content.res.Configuration;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private static final String TAG = "MainActivity";

    private Fragment mFragment;

    private int mSelected = -1;


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "onCreate  " + "");

        // null check not realy needed - but just in case...
        if (savedInstanceState == null) {

            initUi();

            // get an instance of FragmentTransaction from your Activity
            FragmentManager fragmentManager = getSupportFragmentManager();
            FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

            /*IMPORTANT: Do the INITIAL(!) transaction only once!
            * If we call this everytime the layout changes orientation,
            * we will end with a messy, half-working UI.
            * */
            mFragment = FragmentOne.newInstance(mSelected = 0);
            fragmentTransaction.add(R.id.frame, mFragment);
            fragmentTransaction.commit();
        }
    }


    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        Log.d(TAG, "onConfigurationChanged  " +
                   (newConfig.orientation
                    == Configuration.ORIENTATION_LANDSCAPE
                    ? "landscape" : "portrait"));

        initUi();

        Log.i(TAG, "onConfigurationChanged - last selected: " + mSelected);
        makeFragmentTransaction(mSelected);
    }


    /**
     * Called from {@link #onCreate} and {@link #onConfigurationChanged}
     */
    private void initUi() {
        setContentView(R.layout.activity_main);
        Log.d(TAG, "onCreate  instanceState == null / reinitializing..." + "");
        Button btnFragmentOne = (Button) findViewById(R.id.btn_fragment_one);
        Button btnFragmentTwo = (Button) findViewById(R.id.btn_fragment_two);
        btnFragmentOne.setOnClickListener(this);
        btnFragmentTwo.setOnClickListener(this);
    }


    /**
     * Not invoked (just for testing)...
     */
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        Log.d(TAG, "onSaveInstanceState  " + "YOU WON'T SEE ME!!!");
    }


    /**
     * Not invoked (just for testing)...
     */
    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        Log.d(TAG, "onSaveInstanceState  " + "YOU WON'T SEE ME, AS WELL!!!");
    }


    @Override
    protected void onResume() {
        super.onResume();
        Log.d(TAG, "onResume  " + "");
    }


    @Override
    protected void onPause() {
        super.onPause();
        Log.d(TAG, "onPause  " + "");
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy  " + "");
    }


    @Override
    public void onClick(View v) {

        switch (v.getId()) {
            case R.id.btn_fragment_one:
                Log.d(TAG, "onClick btn_fragment_one " + "");
                makeFragmentTransaction(0);
                break;

            case R.id.btn_fragment_two:
                Log.d(TAG, "onClick btn_fragment_two " + "");
                makeFragmentTransaction(1);
                break;

            default:
                Log.d(TAG, "onClick  null - wtf?!" + "");
        }
    }


    /**
     * We replace the current Fragment with the selected one.
     * Note: It called from {@link #onConfigurationChanged} as well.
     */
    private void makeFragmentTransaction(int selection) {

        switch (selection) {
            case 0:
                mFragment = FragmentOne.newInstance(mSelected = 0);
                break;
            case 1:
                mFragment = FragmentTwo.newInstance(mSelected = 1);
                break;
        }

        // Create new transaction
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();

        // Replace whatever is in the fragment_container view with this fragment,
        // and add the transaction to the back stack
        transaction.replace(R.id.frame, mFragment);

        /*This would add the Fragment to the backstack...
        * But right now we comment it out.*/
        //        transaction.addToBackStack(null);

        // Commit the transaction
        transaction.commit();
    }

}

И пример фрагмента:

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

/**
 * @author Martin Pfeffer (pepperonas)
 */
public class FragmentOne extends Fragment {

    private static final String TAG = "FragmentOne";


    public static Fragment newInstance(int i) {
        Fragment fragment = new FragmentOne();
        Bundle args = new Bundle();
        args.putInt("the_id", i);
        fragment.setArguments(args);
        return fragment;
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        Log.d(TAG, "onCreateView  " + "");
        return inflater.inflate(R.layout.fragment_one, container, false);
    }

}

Можно найти на github.

2
ответ дан 30 окт. '15 в 6:53
источник

Добавьте эту строку android: configChanges = "orientation | screenSize" в манифесте

1
ответ дан 28 нояб. '17 в 15:42
источник

Люди говорят, что вы должны использовать

android:configChanges="keyboardHidden|orientation"

Но лучший и самый профессиональный способ обработки вращения в Android - использовать класс Loader. Это не знаменитый класс (я не знаю почему), но это намного лучше, чем AsyncTask. Я использовал его для завершения программы Popular-Movies-Part-1 с курса Nano degree Android.

Популярные части фильма 1

Конечно, вы можете хранить значения или представления с помощью onSaveInstanceState и читать их с помощью onRestoreInstanceState. Это вам действительно.

1
ответ дан 09 янв. '18 в 13:03
источник

Вы можете заблокировать текущую ориентацию экрана с помощью этого кода...

int currentOrientation =context.getResources().getConfiguration().orientation;
        if (currentOrientation == Configuration.ORIENTATION_PORTRAIT) {
            ((Activity) context).setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        } else {
            ((Activity) context). setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        }
0
ответ дан 06 мая '14 в 9:23
источник

Другие вопросы по меткам или Задайте вопрос