现在的位置: 首页 > 综合 > 正文

49_Fragment的用法(实例)

2013年05月16日 ⁄ 综合 ⁄ 共 12022字 ⁄ 字号 评论关闭

Fragment的用法(实例)

例 1 (来自Android官方文档)

  here's an example of an activity using two fragments to create a two-pane layout. The activity below includes one fragment to show a list of Shakespeare play titles and another to show a summary of the play
when selected from the list. It alsodemonstrates how to provide different configurations of the fragments, based onthe screen configuration.(此段大致意思:本例将使用两个fragments来创建一个有两个独立pane的Activity,其中一个fragment
用于显示《莎士比亚》剧本的目录,另一个fragment 用于显示相应目录的内容

  The main activity applies a layout in theusual way, during onCreate():

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

    setContentView(R.layout.fragment_layout);
}

The layoutapplied is fragment_layout.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent" android:layout_height="match_parent">

    <fragment class="com.example.android.apis.app.FragmentLayout$TitlesFragment"
            android:id="@+id/titles" android:layout_weight="1"
            android:layout_width="0px" android:layout_height="match_parent" />

    <FrameLayout android:id="@+id/details" android:layout_weight="1"
            android:layout_width="0px" android:layout_height="match_parent"
            android:background="?android:attr/detailsElementBackground" />

</LinearLayout>

  Using this layout, the system instantiatesthe TitlesFragment (which
lists the play titles) as soon as the activity loadsthe layout, while the 
FrameLayout (where
the fragment for showing the play summary will go)consumes space on the right side of the screen, but remains empty at first. Asyou'll see below, it's not until the user selects an item from the list that afragment is placed into the 
FrameLayout.

However, not all screen configurations arewide enough to show both the list of plays and the summary, side by side. So,the layout above is used only for the landscape screen configuration, by savingit at res/layout-land/fragment_layout.xml.

Thus, when the screen is in portrait orientation, the systemapplies the following layout, which is saved atres/layout/fragment_layout.xml:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent" android:layout_height="match_parent">
    <fragment class="com.example.android.apis.app.FragmentLayout$TitlesFragment"
            android:id="@+id/titles"
            android:layout_width="match_parent" android:layout_height="match_parent" />
</FrameLayout>

  This layout includes only TitlesFragment.This means that, when the device is in portrait orientation, only the list
ofplay titles is visible. So, when the user clicks a list item in thisconfiguration, the application will start a new activity to show the summary,instead of loading a second fragment.

下面是该程序源码:

1. ActivityFragmentLayout.java

import com.example.android.apis.R;
import com.example.android.apis.Shakespeare;

import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.app.ListFragment;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
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;

/**
 * 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 {


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        setContentView(R.layout.fragment_layout);
    }


    /**
     * 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);

            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.
                DetailsFragment details = new DetailsFragment();
                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 currrent UI layout.
     */

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

        @Override
        public void onActivityCreated(Bundle savedInstanceState) {
            super.onActivityCreated(savedInstanceState);

            // Populate list with our static array of titles.
            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.
            View detailsFrame = getActivity().findViewById(R.id.details);
            mDualPane = detailsFrame != null && detailsFrame.getVisibility() == View.VISIBLE;

            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);
            }
        }

        @Override
        public void onSaveInstanceState(Bundle outState) {
            super.onSaveInstanceState(outState);
            outState.putInt("curChoice", mCurCheckPosition);
        }

        @Override
        public void onListItemClick(ListView l, View v, int position, long id) {
            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;

            if (mDualPane) {
                // We can display everything in-place with fragments, so update
                // the list to highlight the selected item and show the data.
                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);

                    // Execute a transaction, replacing any existing fragment
                    // with this one inside the frame.
                    FragmentTransaction ft = getFragmentManager().beginTransaction();
                    if (index == 0) {
                        ft.replace(R.id.details, details);
                    } else {
                        ft.replace(R.id.a_item, 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.
                Intent intent = new Intent();
                intent.setClass(getActivity(), DetailsActivity.class);
                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);
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
            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;
            }

            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;
        }
    }

}

2. 存放FragmentLayout程序将要读取的数据的类Shakespeare.java

public final class Shakespeare {

    public static final String[] TITLES = 
    {
            "Henry IV (1)",   
            "Henry V",
            "Henry VIII",       
            "Richard II",
            "Richard III",
            "Merchant of Venice",  
            "Othello",
            "King Lear"
    };
    public static final String[] DIALOGUE = 
    {
            //数据太多,部分数据已省略
            "What yesternight our council did decree" +
            "In forwarding this dear expedience.",            
          
            "Any retirement, any sequestration" + 
            "From open haunts and popularity.",
            
            "And, if you can be merry then, I'll say" +
            "A man may weep upon his wedding-day.",            
            
            "And wish, so please my sovereign, ere I move," + 
            "What my tongue speaks my right drawn sword may prove.",             
           
            "Dive, thoughts, down to my soul: here" + 
            "Clarence comes.",            
            
            "teach me, I will execute, and it shall go hard but I" + 
            "will better the instruction.",            
           
            "stings, our unbitted lusts, whereof I take this that" + 
            "you call love to be a sect or scion.",
            
            "Crack nature's moulds, an germens spill at once," + 
            "That make ingrateful man!"
    };
}

3. fragment_layout.xml布局管理器

<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent" 
    android:layout_height="match_parent">

    <fragment 
        android:name="org.lion.fragmenttest.FragmentLayout$TitlesFragment"
        android:id="@+id/titles" 
        android:layout_weight="1"
        android:layout_width="0px" 
        android:layout_height="match_parent" />

    <FrameLayout 
        android:id="@+id/details" 
        android:layout_weight="1"
        android:layout_width="0px" 
        android:layout_height="match_parent"
        android:background="?android:attr/detailsElementBackground" />

</LinearLayout>

下面是程序运行效果截图

  注:官网上写的实例代码非常严谨,在程序中做了很多操作合法性判断等,以提高程序的健壮性和通用性。但是这样并不方便我们这些初学者理解,所以为了方便理解,下面我对其中的FragmentLayout.java做一下修改(去掉部分与Fragment无多大关联的代码),使我们更容易从中看到Fragment的用法。(其它部分不变)

修改后的FragmentLayout.java

package org.lion.fragmenttest;

import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.app.ListFragment;
import android.os.Bundle;
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;

public class FragmentLayout extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);        
        setContentView(R.layout.fragment_layout);
    }

    //显示剧本目录的Fragment
    public static class TitlesFragment extends ListFragment {  
    	  
        int mCurCheckPosition = 0;  
        int mShownCheckPosition = -1;  
      
        @Override  
        public void onActivityCreated(Bundle savedInstanceState) {  
            super.onActivityCreated(savedInstanceState);   
                                                              
            setListAdapter(new ArrayAdapter<String>(getActivity(),  
                    android.R.layout.simple_list_item_activated_1,  
                    Shakespeare.TITLES)); //使用静态数组填充列表  
            if (savedInstanceState != null) {   
                mCurCheckPosition = savedInstanceState.getInt("curChoice", 0);  
                mShownCheckPosition = savedInstanceState.getInt("shownChoice", -1);  
            }   
                getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);   
                showDetails(mCurCheckPosition);  
        }  
      
        @Override  
        public void onSaveInstanceState(Bundle outState) {  
            super.onSaveInstanceState(outState);  
      
            outState.putInt("curChoice", mCurCheckPosition);  
            outState.putInt("shownChoice", mShownCheckPosition);  
        }  
      
        @Override  
        public void onListItemClick(ListView l, View v, int position, long id) {  
            showDetails(position);  
        }  
      
        /** 
         *显示listview item 详情 
         */  
        void showDetails(int index) {  
            mCurCheckPosition = index;  
                getListView().setItemChecked(index, true);  
      
                if (mShownCheckPosition != mCurCheckPosition) {  
      
                    DetailsFragment df = DetailsFragment.newInstance(index);  
                    FragmentTransaction ft = getFragmentManager()  
                            .beginTransaction();  
                    ft.replace(R.id.details, df);  
                    ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);  
                    ft.commit();  
                    mShownCheckPosition = index;  
                }     
        }  
      
    }  

    //显示相应目录详细内容的Fragment
    public static class DetailsFragment extends Fragment {      	  
        
        public static DetailsFragment newInstance(int index) {  
            DetailsFragment f = new DetailsFragment();           
            Bundle args = new Bundle();  
            args.putInt("index", index);  
            f.setArguments(args);  
            return f;  
        }  
      
        @Override  
        public View onCreateView(LayoutInflater inflater, ViewGroup container,  
                Bundle savedInstanceState) {  
            if (container == null) {              
                return null;  
            }  
            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[getArguments().getInt("index", 0)]);  
            return scroller;  
        }  
    }  
}

抱歉!评论已关闭.