Using ActionBar Up Navigation in master/detail fragments

后端 未结 4 1323
生来不讨喜
生来不讨喜 2020-12-30 03:07

I have an app with master/detail layout (1 activity, 1 ListView fragment and 1 detail fragment). When the user clicks an item in the ListView, a fragment transaction instan

相关标签:
4条回答
  • 2020-12-30 03:41

    If you look at the Navigation Design Pattern you will see that you want to return to the starting activity when the home button is hit.

    So say you have 2 Activities call them A1 and A2. Clicking on something in A1 takes you to A2. If the user hits the home button you should return them to A1 clearing the stack of everything up until that activity like this

    Intent intent = new Intent(this, A1.class);  
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    startActivity(intent);
    

    this is what the flag Intent.FLAG_ACTIVITY_CLEAR_TOP does

    If set, and the activity being launched is already running in the current task, then instead of launching a new instance of that activity, all of the other activities on top of it will be closed and this Intent will be delivered to the (now on top) old activity as a new Intent.

    For example, consider a task consisting of the activities: A, B, C, D. If D calls startActivity() with an Intent that resolves to the component of activity B, then C and D will be finished and B receive the given Intent, resulting in the stack now being: A, B.`

    The currently running instance of activity B in the above example will either receive the new intent you are starting here in its onNewIntent() method, or be itself finished and restarted with the new intent. If it has declared its launch mode to be "multiple" (the default) and you have not set FLAG_ACTIVITY_SINGLE_TOP in the same intent, then it will be finished and re-created; for all other launch modes or if FLAG_ACTIVITY_SINGLE_TOP is set then this Intent will be delivered to the current instance's onNewIntent().

    This launch mode can also be used to good effect in conjunction with FLAG_ACTIVITY_NEW_TASK: if used to start the root activity of a task, it will bring any currently running instance of that task to the foreground, and then clear it to its root state. This is especially useful, for example, when launching an activity from the notification manager.

    0 讨论(0)
  • 2020-12-30 03:44

    I think you should handle the Up button only inside the activity. If youre in a phone, the up button will be handled by activity that acts as a wrapper of that fragment, in tablet (master/detail pattern) you dont want it anyways

    0 讨论(0)
  • 2020-12-30 03:47

    After much research and poking around, turns out that only reason why my activity was restarting during "up navigation" for master/detail configuration was because I left some code in the ListView Fragment's onOptionsItemSelected that was creating an intent to start the main activity in addition to my full fragment transaction code elsewhere. Below is the final implementation with which I got "up navigation" to work properly on both phone (multiple activities) and tablet (single activity/multi-pane) configurations. Thanks to Wolfram Rittmeyer for a couple of hints in his code (link in the comment section) that help me pinpoint my problem!

    Main Activity: Hosts the fragments and performs some other app-specific operations

    ListView Fragment: Handles "up navigation in table configuration

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                if(mDualPane){
                    FragmentManager manager = getSherlockActivity().getSupportFragmentManager();
                    FragmentTransaction ft = manager.beginTransaction();
                    DetailFragment detailFragment = (DetailFragment)manager.findFragmentById(R.id.details);
                    ft.remove(detailFragment);
                    ft.commit();
                    manager.popBackStack();
                    getSherlockActivity().getSupportActionBar().setDisplayHomeAsUpEnabled(false);
                    getSherlockActivity().getSupportActionBar().setHomeButtonEnabled(false);
                }
                return true;
    
            // Other case statements...
    
            default:
                return super.onOptionsItemSelected(item);
        }
    }
    

    Details Fragment: Handles up navigation in phone configuration

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);
    
        // Sets "up navigation" for both phone/tablet configurations
        ActionBar actionBar = getSherlockActivity().getSupportActionBar();
        actionBar.setDisplayHomeAsUpEnabled(true);
    }
    
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
    
        switch (item.getItemId()) {
            case android.R.id.home:
                if(!mDualPane){
                    Intent parentActivityIntent = new Intent(getSherlockActivity(), MainActivity.class);
                    parentActivityIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
                    startActivity(parentActivityIntent);
                    getSherlockActivity().finish();
                }
                return true;
    
            // Other case statements...
    
            default:
                return super.onOptionsItemSelected(item);
        }
    
    }
    
    0 讨论(0)
  • 2020-12-30 04:08

    don't: break and then return super.onOptionsItemSelected(item), rather just: return true;

    UPDATE:

    So you're saying the Activity is "restarted" based on what you see happen with Views, but can you confirm what may or may not happen to the Activity (and Fragments for that matter) by using logging in the various lifecycle methods? That way you can be sure of what the current (erroneous) behaviour is before moving forward with diagnosis.

    UPDATE:

    OK, good to be sure about behaviour :) Now regarding your question "What is the correct way to implement "up navigation" for a master/detail layout (1 activity/2fragments)? ": The typical way is that the 2 Fragments got added within a single FragmentTransaction and you simply popBackStack to remove them and go back to whatever previous state was. I think you're doubling up by manually removing a Fragment within a FragmentTransaction and then popping backstack. Try just popBackStack. Oh and just to be sure and consistent, since you're using ActionBarSherlock and support.v4 are you using a FragmentActivity (rather than an Activity) and SherlockFragment?

    0 讨论(0)
提交回复
热议问题