更改方向不起作用时的主细节片段

时间:2014-03-27 12:33:44

标签: android orientation tablet

我找到了关于主细节片段的android代码,我也将其转换为使用标签。当我在手机或桌面上以portait方向运行代码时应用程序正常工作但当我将方向更改为横向时,应用程序不会更改。代码如下:

 // This code has some modifications to the original 
 // See http://developer.android.com/guide/components/fragments.html
 // for a detailed discussion on the app
 // I don't recommend toast as debug for flow but why not do that to get started.
 // Better to use Log.d() which we introduced before. Toast is fleeting and logs 
 // will always in in the LogCat -- hence they are more useful and better practice;
 // but you can't see them on the phone. It is sort cool to see onCreate() toast
 // as you flip the phone's orientation. It reinforces the lifecycle and the 
 // automatic adjustment of the UI.
 //
 // ATC 2013

 package edu.dartmouth.cs;

 import java.util.ArrayList;
 import java.util.List;

 import android.app.ActionBar;
 import android.app.ActionBar.Tab;
 import android.app.ActionBar.TabListener;
 import android.app.Activity;
 import android.app.Fragment;
 import android.app.FragmentTransaction;
 import android.app.ListFragment;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
 import android.content.res.Configuration;
 import android.os.Bundle;
 import android.util.Log;
 import android.util.TypedValue;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.ArrayAdapter;
 import android.widget.ListView;
 import android.widget.ScrollView;
 import android.util.Log;
 import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;
import edu.dartmouth.cs.FragmentLayout.Titles2Fragment;
import edu.dartmouth.cs.FragmentLayout.TitlesFragment;
import edu.dartmouth.cs.apis.CopyOfShakespeare;
import edu.dartmouth.cs.apis.Shakespeare;`


 // Demonstration of using fragments to implement different activity layouts.
 // This sample provides a different layout (and activity flow) when run in
 // landscape.

`public class FragmentLayout extends Activity {

//List<Fragment> fragList = new ArrayList<Fragment>();

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    //tab
    final ActionBar actionBar = getActionBar();     

    // Specify that tabs should be displayed in the action bar.
    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);



    // Add 2 tabs, specifying the tab's text and TabListener

    Tab meinProfil = actionBar.newTab().setText("Mein Profil");
    TabListener<TitlesFragment> tabListenerMeinProfil = new TabListener<TitlesFragment>(this,"Mein Profil",TitlesFragment.class);
    meinProfil.setTabListener(tabListenerMeinProfil);
    actionBar.addTab(meinProfil);

    Tab mitglieder = actionBar.newTab().setText("Mitglieder");
    TabListener<Titles2Fragment> tabListenerMitglieder = new TabListener<Titles2Fragment>(this,"Mitglieder",Titles2Fragment.class);
    mitglieder.setTabListener(tabListenerMitglieder);
    actionBar.addTab(mitglieder);

    //
    Toast.makeText(this, "FragmentLayout: OnCreate()", Toast.LENGTH_SHORT)
            .show();

    // Sets the view. Depending on orientation it will select either
    // res/layout/fragment_layout.xml (portrait mode) or
    // res/layout-land/fragment_layout.xml (landscape mode). This is done
    // automatically by the system.
     if (savedInstanceState != null) {
         actionBar.setSelectedNavigationItem(savedInstanceState.getInt("tab", 0));
        }
    //setContentView(R.layout.fragment_layout);
}

 @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt("tab", getActionBar().getSelectedNavigationIndex());
    }

private class TabListener<T extends Fragment> implements
ActionBar.TabListener {
    private Fragment mFragment;
    private final Activity mActivity;
    private final String mTag;
    private final Class<T> mClass;
    private final Bundle mArgs;

     public TabListener(Activity activity, String tag, Class<T> clz) {
            this(activity, tag, clz, null);
        }

    /**
     * Constructor used each time a new tab is created.
     * 
     * @param activity
     *            The host Activity, used to instantiate the fragment
     * @param tag
     *            The identifier tag for the fragment
     * @param clz
     *            The fragment's Class, used to instantiate the fragment
     */
    public TabListener(Activity activity, String tag, Class<T> clz, Bundle args) {
        mActivity = activity;
        mTag = tag;
        mClass = clz;
        mArgs = args;
        // Check to see if we already have a fragment for this tab, probably
        // from a previously saved state.  If so, deactivate it, because our
        // initial state is that a tab isn't shown.
        Log.d("pas 111", mTag.toString());
        mFragment = mActivity.getFragmentManager().findFragmentByTag(mTag);
        if (mFragment != null && !mFragment.isDetached()) {
            Log.d("pas", mTag.toString());
            FragmentTransaction ft = mActivity.getFragmentManager().beginTransaction();
            ft.detach(mFragment);
            ft.commit();
        }
    }

    public void onTabSelected(Tab tab, FragmentTransaction ft) {
          Log.d("pas 111", mTag.toString());
           // mFragment = mActivity.getFragmentManager().findFragmentByTag(mTag);
         if (mFragment == null) {
                mFragment = Fragment.instantiate(mActivity, mClass.getName(), mArgs);
                ft.add(android.R.id.content, mFragment, mTag);
            } else {
                ft.attach(mFragment);
            }


    }

    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
        // mFragment = mActivity.getFragmentManager().findFragmentByTag(mTag);
         if (mFragment != null) {
             Log.d("pas unselected", mTag.toString());
                ft.detach(mFragment);
                //ft.commit();
            }

    }

    public void onTabReselected(Tab tab, FragmentTransaction ft) {
        // User selected the already selected tab. Usually do nothing.
         Toast.makeText(mActivity, "Reselected!", Toast.LENGTH_SHORT).show();
    }
}


// This is a secondary activity, to show what the user has selected when the
// screen is not large enough to show it all in one activity.

public static class DetailsActivity extends Activity {

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

        Toast.makeText(this, "DetailsActivity", Toast.LENGTH_SHORT).show();

        if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
            // If the screen is now in landscape mode, we can show the
            // dialog in-line with the list so we don't need this activity.
            finish();
            return;
        }

        if (savedInstanceState == null) {
            // During initial setup, plug in the details fragment.

            // create fragment
            DetailsFragment details = new DetailsFragment();

            // get and set the position input by user (i.e., "index")
            // which is the construction arguments for this fragment
            details.setArguments(getIntent().getExtras());

            //
            getFragmentManager().beginTransaction()
                    .add(android.R.id.content, details).commit();
        }
    }
}

// This is the "top-level" fragment, showing a list of items that the user
// can pick. Upon picking an item, it takes care of displaying the data to
// the user as appropriate based on the current UI layout.

// Displays a list of items that are managed by an adapter similar to
// ListActivity. It provides several methods for managing a list view, such
// as the onListItemClick() callback to handle click events.

public static class TitlesFragment extends ListFragment {
    boolean mDualPane;
    int mCurCheckPosition = 0;

    // onActivityCreated() is called when the activity's onCreate() method
    // has returned.

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);
        // You can use getActivity(), which returns the activity associated
        // with a fragment.
        // The activity is a context (since Activity extends Context) .

        Toast.makeText(getActivity(), "TitlesFragment:onActivityCreated",
                Toast.LENGTH_LONG).show();

        // Populate list with our static array of titles in list in the
        // Shakespeare class
        setListAdapter(new ArrayAdapter<String>(getActivity(),
                android.R.layout.simple_list_item_activated_1,
                Shakespeare.TITLES));

        // Check to see if we have a frame in which to embed the details
        // fragment directly in the containing UI.
        // R.id.details relates to the res/layout-land/fragment_layout.xml
        // This is first created when the phone is switched to landscape
        // mode

        View detailsFrame = getActivity().findViewById(R.id.details);

        Toast.makeText(getActivity(), "detailsFrame " + detailsFrame,
                Toast.LENGTH_LONG).show();

        // Check that a view exists and is visible
        // A view is visible (0) on the screen; the default value.
        // It can also be invisible and hidden, as if the view had not been
        // added.
        //
        mDualPane = detailsFrame != null
                && detailsFrame.getVisibility() == View.VISIBLE;
        //mDualPane=true;
        Toast.makeText(getActivity(), "mDualPane " + mDualPane,
                Toast.LENGTH_LONG).show();

        if (savedInstanceState != null) {
            // Restore last state for checked position.
            mCurCheckPosition = savedInstanceState.getInt("curChoice", 0);
        }

        if (mDualPane) {
            // In dual-pane mode, the list view highlights the selected
            // item.
            getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
            // Make sure our UI is in the correct state.
            showDetails(mCurCheckPosition);
        } else {
            // We also highlight in uni-pane just for fun
            getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
            getListView().setItemChecked(mCurCheckPosition, true);
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        Toast.makeText(getActivity(), "onSaveInstanceState",
                Toast.LENGTH_LONG).show();

        outState.putInt("curChoice", mCurCheckPosition);
    }

    // If the user clicks on an item in the list (e.g., Henry V then the
    // onListItemClick() method is called. It calls a helper function in
    // this case.

    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {

        Toast.makeText(getActivity(),
                "onListItemClick position is" + position, Toast.LENGTH_LONG)
                .show();

        showDetails(position);
    }

    // Helper function to show the details of a selected item, either by
    // displaying a fragment in-place in the current UI, or starting a whole
    // new activity in which it is displayed.

    void showDetails(int index) {
        mCurCheckPosition = index;

        // The basic design is mutli-pane (landscape on the phone) allows us
        // to display both fragments (titles and details) with in the same
        // activity; that is FragmentLayout -- one activity with two
        // fragments.
        // Else, it's single-pane (portrait on the phone) and we fire
        // another activity to render the details fragment - two activities
        // each with its own fragment .
        //
        if (mDualPane) {
            // We can display everything in-place with fragments, so update
            // the list to highlight the selected item and show the data.
            // We keep highlighted the current selection
            getListView().setItemChecked(index, true);

            // Check what fragment is currently shown, replace if needed.
            DetailsFragment details = (DetailsFragment) getFragmentManager()
                    .findFragmentById(R.id.details);
            if (details == null || details.getShownIndex() != index) {
                // Make new fragment to show this selection.

                details = DetailsFragment.newInstance(index);

                Toast.makeText(getActivity(),
                        "showDetails dual-pane: create and relplace fragment",
                        Toast.LENGTH_LONG).show();

                // Execute a transaction, replacing any existing fragment
                // with this one inside the frame.
                FragmentTransaction ft = getFragmentManager()
                        .beginTransaction();
                ft.replace(R.id.details, details);
                ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
                ft.commit();
            }

        } else {
            // Otherwise we need to launch a new activity to display
            // the dialog fragment with selected text.
            // That is: if this is a single-pane (e.g., portrait mode on a
            // phone) then fire DetailsActivity to display the details
            // fragment

            // Create an intent for starting the DetailsActivity
            Intent intent = new Intent();

            // explicitly set the activity context and class
            // associated with the intent (context, class)
            intent.setClass(getActivity(), DetailsActivity.class);

            // pass the current position
            intent.putExtra("index", index);

            startActivity(intent);
        }
    }
}

// This is the secondary fragment, displaying the details of a particular
// item.

public static class DetailsFragment extends Fragment {

    // Create a new instance of DetailsFragment, initialized to show the
    // text at 'index'.

    public static DetailsFragment newInstance(int index) {
        DetailsFragment f = new DetailsFragment();

        // Supply index input as an argument.
        Bundle args = new Bundle();
        args.putInt("index", index);
        f.setArguments(args);

        return f;   
    }

    public int getShownIndex() {
        return getArguments().getInt("index", 0);
    }

    // The system calls this when it's time for the fragment to draw its
    // user interface for the first time. To draw a UI for your fragment,
    // you must return a View from this method that is the root of your
    // fragment's layout. You can return null if the fragment does not
    // provide a UI.

    // We create the UI with a scrollview and text and return a reference to
    // the scoller which is then drawn to the screen

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);
        Toast.makeText(getActivity(), "DetailsFragment:onCreateView",
                Toast.LENGTH_LONG).show();
        //
        // if (container == null) {
        // // We have different layouts, and in one of them this
        // // fragment's containing frame doesn't exist. The fragment
        // // may still be created from its saved state, but there is
        // // no reason to try to create its view hierarchy because it
        // // won't be displayed. Note this is not needed -- we could
        // // just run the code below, where we would create and return
        // // the view hierarchy; it would just never be used.
        // return null;
        // }

        // If non-null, this is the parent view that the fragment's UI
        // should be attached to. The fragment should not add the view
        // itself, but this can be used to generate the LayoutParams of
        // the view.
        //

        // programmatically create a scrollview and texview for the text in
        // the container/fragment layout. Set up the properties and add the
        // view.

        ScrollView scroller = new ScrollView(getActivity());
        TextView text = new TextView(getActivity());
        int padding = (int) TypedValue.applyDimension(
                TypedValue.COMPLEX_UNIT_DIP, 4, getActivity()
                        .getResources().getDisplayMetrics());
        text.setPadding(padding, padding, padding, padding);
        scroller.addView(text);
        text.setText(Shakespeare.DIALOGUE[getShownIndex()]);
        return scroller;
    }
}
public static class Titles2Fragment extends ListFragment {
    boolean mDualPane;
    int mCurCheckPosition = 0;

    // onActivityCreated() is called when the activity's onCreate() method
    // has returned.

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);
        // You can use getActivity(), which returns the activity associated
        // with a fragment.
        // The activity is a context (since Activity extends Context) .

        Toast.makeText(getActivity(), "Titles2Fragment:onActivityCreated",
                Toast.LENGTH_LONG).show();

        // Populate list with our static array of titles in list in the
        // Shakespeare class
        setListAdapter(new ArrayAdapter<String>(getActivity(),
                android.R.layout.simple_list_item_activated_1,
                CopyOfShakespeare.TITLES2));

        // Check to see if we have a frame in which to embed the details
        // fragment directly in the containing UI.
        // R.id.details relates to the res/layout-land/fragment_layout.xml
        // This is first created when the phone is switched to landscape
        // mode

        View detailsFrame = getActivity().findViewById(R.id.details);

        Toast.makeText(getActivity(), "detailsFrame " + detailsFrame,
                Toast.LENGTH_LONG).show();

        // Check that a view exists and is visible
        // A view is visible (0) on the screen; the default value.
        // It can also be invisible and hidden, as if the view had not been
        // added.
        //
        mDualPane = detailsFrame != null
                && detailsFrame.getVisibility() == View.VISIBLE;
        //mDualPane=true;
        Toast.makeText(getActivity(), "mDualPane " + mDualPane,
                Toast.LENGTH_LONG).show();

        if (savedInstanceState != null) {
            // Restore last state for checked position.
            mCurCheckPosition = savedInstanceState.getInt("curChoice", 0);
        }

        if (mDualPane) {
            // In dual-pane mode, the list view highlights the selected
            // item.
            getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
            // Make sure our UI is in the correct state.
            showDetails(mCurCheckPosition);
        } else {
            // We also highlight in uni-pane just for fun
            getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
            getListView().setItemChecked(mCurCheckPosition, true);
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        Toast.makeText(getActivity(), "onSaveInstanceState",
                Toast.LENGTH_LONG).show();

        outState.putInt("curChoice", mCurCheckPosition);
    }

    // If the user clicks on an item in the list (e.g., Henry V then the
    // onListItemClick() method is called. It calls a helper function in
    // this case.

    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {

        Toast.makeText(getActivity(),
                "onListItemClick position is" + position, Toast.LENGTH_LONG)
                .show();

        showDetails(position);
    }

    // Helper function to show the details of a selected item, either by
    // displaying a fragment in-place in the current UI, or starting a whole
    // new activity in which it is displayed.

    void showDetails(int index) {
        mCurCheckPosition = index;

        // The basic design is mutli-pane (landscape on the phone) allows us
        // to display both fragments (titles and details) with in the same
        // activity; that is FragmentLayout -- one activity with two
        // fragments.
        // Else, it's single-pane (portrait on the phone) and we fire
        // another activity to render the details fragment - two activities
        // each with its own fragment .
        //
        if (mDualPane) {
            // We can display everything in-place with fragments, so update
            // the list to highlight the selected item and show the data.
            // We keep highlighted the current selection
            getListView().setItemChecked(index, true);

            // Check what fragment is currently shown, replace if needed.
            Details2Fragment details = (Details2Fragment) getFragmentManager()
                    .findFragmentById(R.id.details);
            if (details == null || details.getShownIndex() != index) {
                // Make new fragment to show this selection.

                details = Details2Fragment.newInstance(index);

                Toast.makeText(getActivity(),
                        "showDetails dual-pane: create and relplace fragment",
                        Toast.LENGTH_LONG).show();

                // Execute a transaction, replacing any existing fragment
                // with this one inside the frame.
                FragmentTransaction ft = getFragmentManager()
                        .beginTransaction();
                ft.replace(R.id.details, details);
                ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
                ft.commit();
            }

        } else {
            // Otherwise we need to launch a new activity to display
            // the dialog fragment with selected text.
            // That is: if this is a single-pane (e.g., portrait mode on a
            // phone) then fire DetailsActivity to display the details
            // fragment

            // Create an intent for starting the DetailsActivity
            Intent intent = new Intent();

            // explicitly set the activity context and class
            // associated with the intent (context, class)
            intent.setClass(getActivity(), Details2Activity.class);

            // pass the current position
            intent.putExtra("index", index);

            startActivity(intent);
        }
    }
}
public static class Details2Activity extends Activity {

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

        Toast.makeText(this, "Details2Activity", Toast.LENGTH_SHORT).show();

        if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
            // If the screen is now in landscape mode, we can show the
            // dialog in-line with the list so we don't need this activity.
            finish();
            return;
        }

        if (savedInstanceState == null) {
            // During initial setup, plug in the details fragment.

            // create fragment
            Details2Fragment details = new Details2Fragment();

            // get and set the position input by user (i.e., "index")
            // which is the construction arguments for this fragment
            details.setArguments(getIntent().getExtras());

            //
            getFragmentManager().beginTransaction()
                    .add(android.R.id.content, details).commit();
        }
    }
}
public static class Details2Fragment extends Fragment {

    // Create a new instance of DetailsFragment, initialized to show the
    // text at 'index'.

    public static Details2Fragment newInstance(int index) {
        Details2Fragment f = new Details2Fragment();

        // Supply index input as an argument.
        Bundle args = new Bundle();
        args.putInt("index", index);
        f.setArguments(args);

        return f;   
    }

    public int getShownIndex() {
        return getArguments().getInt("index", 0);
    }

    // The system calls this when it's time for the fragment to draw its
    // user interface for the first time. To draw a UI for your fragment,
    // you must return a View from this method that is the root of your
    // fragment's layout. You can return null if the fragment does not
    // provide a UI.

    // We create the UI with a scrollview and text and return a reference to
    // the scoller which is then drawn to the screen

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);
        Toast.makeText(getActivity(), "Details2Fragment:onCreateView",
                Toast.LENGTH_LONG).show();
        //
        // if (container == null) {
        // // We have different layouts, and in one of them this
        // // fragment's containing frame doesn't exist. The fragment
        // // may still be created from its saved state, but there is
        // // no reason to try to create its view hierarchy because it
        // // won't be displayed. Note this is not needed -- we could
        // // just run the code below, where we would create and return
        // // the view hierarchy; it would just never be used.
        // return null;
        // }

        // If non-null, this is the parent view that the fragment's UI
        // should be attached to. The fragment should not add the view
        // itself, but this can be used to generate the LayoutParams of
        // the view.
        //

        // programmatically create a scrollview and texview for the text in
        // the container/fragment layout. Set up the properties and add the
        // view.

        ScrollView scroller = new ScrollView(getActivity());
        TextView text = new TextView(getActivity());
        int padding = (int) TypedValue.applyDimension(
                TypedValue.COMPLEX_UNIT_DIP, 4, getActivity()
                        .getResources().getDisplayMetrics());
        text.setPadding(padding, padding, padding, padding);
        scroller.addView(text);
        text.setText(CopyOfShakespeare.DIALOGUE2[getShownIndex()]);
        return scroller;
    }
}

}`

我的清单文件:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="edu.dartmouth.cs"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk
    android:minSdkVersion="15"
    android:targetSdkVersion="17" />

<application
    android:allowBackup="true"
    android:icon="@drawable/ic_fragments"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name="edu.dartmouth.cs.FragmentLayout"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activity android:name="edu.dartmouth.cs.FragmentLayout$DetailsActivity" />
    <activity android:name="edu.dartmouth.cs.FragmentLayout$Details2Activity" />
</application>

知道它为什么不起作用? 还有一个问题。这种设计(带有主要细节片段的标签)是显示“主”表和“细节”表记录的正确方法吗?我的意思是,如果因为性能而有任何不利之处。 建议被接受 谢谢你的帮助

0 个答案:

没有答案