Динамически устанавливать родительскую активность

Таким образом, на данный момент у меня есть активность, которая может быть достигнута из двух разных действий, проблема в том, что я могу установить только одно действие как родительскую активность в файле манифеста XML. Очевидно, что это плохой дизайн UX / UI, потому что активность может отправить обратно пользователя к неправильному действию, которое они были ранее, и поэтому я пытаюсь динамически установить, какая активность является родительской.

Проблема в том, что я не совсем уверен, как это сделать, будь то в коде или XML, поэтому любые указатели оцениваются. 🙂

В игре есть две концепции: «Вверх» и «Назад». «Назад» – это очевидное: отвези меня туда, где я был незадолго до моего приезда сюда. Обычно вам не нужно беспокоиться о «Назад», так как система справится с этим просто отлично. «Вверх» не так очевидно – он аналогичен Zoom Out – от элемента до коллекции, от детали до более широкой картины.

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


В соответствии с комментарием ниже: кнопка «вверх» вытаскивает пункт назначения из манифеста Android, но его можно настроить программно .

Для будущих читателей здесь приведен пример того, как реально реализовать официальное / правильное решение в соответствии с руководствами разработчика (прокрутите до пункта, начинающегося с «Это подходит, когда родительская активность может быть другой … » ).

Обратите внимание, что в этом решении предполагается, что вы используете библиотеку поддержки для реализации своего ActionBar и что вы можете по крайней мере установить родительскую активность по умолчанию в вашем файле XML манифеста, чтобы вернуться к ней, если операция, в которой вы выполняете резервное копирование, находится в «задаче», Который не принадлежит вашему приложению (прочитайте связанные документы для уточнения).

 // Override BOTH getSupportParentActivityIntent() AND getParentActivityIntent() because // if your device is running on API 11+ it will call the native // getParentActivityIntent() method instead of the support version. // The docs do **NOT** make this part clear and it is important! @Override public Intent getSupportParentActivityIntent() { return getParentActivityIntentImpl(); } @Override public Intent getParentActivityIntent() { return getParentActivityIntentImpl(); } private Intent getParentActivityIntentImpl() { Intent i = null; // Here you need to do some logic to determine from which Activity you came. // example: you could pass a variable through your Intent extras and check that. if (parentIsActivityA) { i = new Intent(this, ActivityA.class); // set any flags or extras that you need. // If you are reusing the previous Activity (ie bringing it to the top // without re-creating a new instance) set these flags: i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); // if you are re-using the parent Activity you may not need to set any extras i.putExtra("someExtra", "whateverYouNeed"); } else { i = new Intent(this, ActivityB.class); // same comments as above i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); i.putExtra("someExtra", "whateverYouNeed"); } return i; } 

ПРИМЕЧАНИЕ. Если вы не установите родительскую активность по умолчанию в файле XML манифеста, вам также понадобится реализовать onCreateSupportNavigateUpTaskStack (), так как система не знает, как создать стоп-кадр для вашей задачи. Я не привел ни одного примера для этой части.

Мои мысли о решениях типа finish()

В поисках решения этой проблемы я наткнулся на несколько ответов, которые onOptionsItemSelected() стратегию переопределения onOptionsItemSelected() и перехватывают кнопку android.R.id.home , чтобы они могли просто finish() текущую Activity чтобы вернуться к предыдущей экран.

Во многих случаях это приведет к желаемому поведению, но я просто хочу указать, что это определенно не то же самое, что и правильная навигационная система. Если вы перешли к дочерней операции через один из родительских действий, то yes finish() вернет вас на предыдущий предыдущий экран, но что, если вы ввели дочернюю активность через уведомление? В этом случае finish() , нажав кнопку «ВВЕРХ», отбросит вас обратно на главный экран или любое другое приложение, которое вы просматривали, прежде чем ударить уведомление, а вместо этого оно должно было отправить вас в надлежащую родительскую активность в вашем приложении.

Таким образом, вы можете динамически перемещаться по родительской активности:

 getActionBar().setDisplayHomeAsUpEnabled(true); @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { // Respond to the action bar's Up/Home button case android.R.id.home: finish(); return true; } return super.onOptionsItemSelected(item); } 

ПРИМЕЧАНИЕ. Он перенаправляет вас на активность или фрагмент, откуда вы пришли, независимо от того, является ли это родителем или нет. Нажатие на панель действий Кнопка «Вверх» / «Начало» просто завершит текущую операцию.

Чтобы узнать, как правильно использовать Up Navigation, ознакомьтесь с этим руководством Android Dev.

Обратите внимание, что в вышеупомянутом руководстве Android Dev есть большой недостаток, поскольку функции NavUtils работают по-разному для ICS (и ниже) и JellyBean (и выше). Этот недостаток в NavUtils объясняется здесь красиво .

Метод переопределения – getParentActivityIntent.

Вот мой код и работает отлично.

 @Override public Intent getParentActivityIntent() { Intent parentIntent= getIntent(); String className = parentIntent.getStringExtra("ParentClassSource"); Intent newIntent=null; try { //you need to define the class with package name newIntent = new Intent(OnMap.this, Class.forName(className)); } catch (ClassNotFoundException e) { e.printStackTrace(); } return newIntent; } 

От родительской деятельности;

 Intent i = new Intent(DataDetailsItem.this, OnMap.class); i.putExtra("ParentClassSource", "com.package.example.YourParentActivity"); startActivity(i); 

Как правило, тип активности «подробно» должен обеспечивать навигацию «вверх», если она имеет вложенное / связанное содержимое. Система «назад» обрабатывается системой, поэтому вам не нужно беспокоиться об этом.

Теперь для дополнительных усилий по поддержке навигации «вверх» есть несколько способов сделать это:

  1. Активность, которая имеет родительскую активность, определенную в AndroidManifest.

     Your Android Manifest --------------------- <activity android:name="com.example.app.DetailActivity" android:parentActivityName="com.example.app.MainActivity" > <meta-data android:name="android.support.PARENT_ACTIVITY" android:value="com.example.app.MainActivity" /> </activity> Your Detail Activity -------------------- @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: NavUtils.navigateUpFromSameTask(this); return true; } return super.onOptionsItemSelected(item); } 

    Это хорошо работает, если есть только один родительский актив, означающий, что (DetailActivity) всегда запускается из (MainActivity). В противном случае это решение не будет работать, если (DetailActivity) запускается из разных мест. Подробнее здесь: http://developer.android.com/training/implementing-navigation/ancestral.html

  2. (Упрощенная и рекомендуемая) активность с фрагментами фрагментов и фрагментов:

     Your Detail Activity -------------------- protected void replaceFragment(Bundle fragmentArguments, boolean addToBackStack) { DetailFragment fragment = new DetailFragment(); fragment.setArguments(fragmentArguments); // get your fragment manager, native/support FragmentTransaction tr = fragmentManager.beginTransaction(); tr.replace(containerResId, fragment); if (addToBackStack) { tr.addToBackStack(null); } tr.commit(); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: finish(); return true; } return super.onOptionsItemSelected(item); } 

    В этом решении, если пользователь нажимает «назад», фрагмент будет выскользнут из фрагмента backstack, и пользователь будет возвращен к предыдущему фрагменту, оставаясь при этом в той же самой активности. Если пользователь нажимает «вверх», действие отклоняется, и пользователь возвращается к предыдущему действию (являющемуся родительской активностью). Ключевым моментом здесь является использование Фрагмента в качестве вашего пользовательского интерфейса и его действия в качестве хоста фрагмента.

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

Вам нужно будет отслеживать родительскую активность. Один из способов сделать это – сохранить его в качестве дополнительного в намерении, которое вы создаете для запуска дочерней активности). Например, если Activity A запускает Activity B, onOptionsItemSelected намерение A в намерении, созданном для B. Затем в B onOptionsItemSelected где вы обрабатываете навигацию вверх, извлекаете намерение A и начинаете с требуемых флагов намерения.

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

Android для навигации по активности с несколькими родителями