Подтвердить что ты не робот

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

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

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

4b9b3361

Ответ 1

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

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


В соответствии с комментарием ниже: кнопка "вверх" вытаскивает адресат из манифеста Android, но может быть настроена программно.

Ответ 2

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

Обратите внимание, что это решение предполагает, что вы используете Библиотека поддержки для реализации своего 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 (i.e. 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() и перехвата кнопки android.R.id.home, чтобы они могли просто finish() текущего Activity вернуться к предыдущий экран.

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

Ответ 3

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

getActionBar().setDisplayHomeAsUpEnabled(true);

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

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

Ответ 4

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

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

Ответ 5

Метод переопределения - 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);

Ответ 6

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

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

  • Действие, которое имеет родительскую активность, определенную в 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

  • (Простая и рекомендуемая) активность с фрагментами фрагментов и фрагментов:

    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, и пользователь будет возвращен к предыдущему фрагменту, оставаясь при этом в той же самой активности. Если пользователь нажимает "вверх" , действие отклоняется, и пользователь возвращается к предыдущему действию (являясь родительским действием). Ключевым моментом здесь является использование Фрагмента как вашего пользовательского интерфейса и активности в качестве хоста фрагмента.

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

Ответ 7

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

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

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