1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.example.android.apis.app;
18 
19 import com.example.android.apis.R;
20 import com.example.android.apis.Shakespeare;
21 
22 import android.app.Activity;
23 import android.app.Fragment;
24 import android.app.FragmentTransaction;
25 import android.app.ListFragment;
26 import android.content.Intent;
27 import android.content.res.Configuration;
28 import android.os.Bundle;
29 import android.util.TypedValue;
30 import android.view.LayoutInflater;
31 import android.view.View;
32 import android.view.ViewGroup;
33 import android.widget.ArrayAdapter;
34 import android.widget.ListView;
35 import android.widget.ScrollView;
36 import android.widget.TextView;
37 
38 /**
39  * Demonstration of using fragments to implement different activity layouts.
40  * This sample provides a different layout (and activity flow) when run in
41  * landscape.
42  */
43 public class FragmentLayout extends Activity {
44 
45 //BEGIN_INCLUDE(main)
46     @Override
onCreate(Bundle savedInstanceState)47     protected void onCreate(Bundle savedInstanceState) {
48         super.onCreate(savedInstanceState);
49 
50         setContentView(R.layout.fragment_layout);
51     }
52 //END_INCLUDE(main)
53 
54     /**
55      * This is a secondary activity, to show what the user has selected
56      * when the screen is not large enough to show it all in one activity.
57      */
58 //BEGIN_INCLUDE(details_activity)
59     public static class DetailsActivity extends Activity {
60 
61         @Override
onCreate(Bundle savedInstanceState)62         protected void onCreate(Bundle savedInstanceState) {
63             super.onCreate(savedInstanceState);
64 
65             if (getResources().getConfiguration().orientation
66                     == Configuration.ORIENTATION_LANDSCAPE) {
67                 // If the screen is now in landscape mode, we can show the
68                 // dialog in-line with the list so we don't need this activity.
69                 finish();
70                 return;
71             }
72 
73             if (savedInstanceState == null) {
74                 // During initial setup, plug in the details fragment.
75                 DetailsFragment details = new DetailsFragment();
76                 details.setArguments(getIntent().getExtras());
77                 getFragmentManager().beginTransaction().add(android.R.id.content, details).commit();
78             }
79         }
80     }
81 //END_INCLUDE(details_activity)
82 
83     /**
84      * This is the "top-level" fragment, showing a list of items that the
85      * user can pick.  Upon picking an item, it takes care of displaying the
86      * data to the user as appropriate based on the currrent UI layout.
87      */
88 //BEGIN_INCLUDE(titles)
89     public static class TitlesFragment extends ListFragment {
90         boolean mDualPane;
91         int mCurCheckPosition = 0;
92 
93         @Override
onActivityCreated(Bundle savedInstanceState)94         public void onActivityCreated(Bundle savedInstanceState) {
95             super.onActivityCreated(savedInstanceState);
96 
97             // Populate list with our static array of titles.
98             setListAdapter(new ArrayAdapter<String>(getActivity(),
99                     android.R.layout.simple_list_item_activated_1, Shakespeare.TITLES));
100 
101             // Check to see if we have a frame in which to embed the details
102             // fragment directly in the containing UI.
103             View detailsFrame = getActivity().findViewById(R.id.details);
104             mDualPane = detailsFrame != null && detailsFrame.getVisibility() == View.VISIBLE;
105 
106             if (savedInstanceState != null) {
107                 // Restore last state for checked position.
108                 mCurCheckPosition = savedInstanceState.getInt("curChoice", 0);
109             }
110 
111             if (mDualPane) {
112                 // In dual-pane mode, the list view highlights the selected item.
113                 getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
114                 // Make sure our UI is in the correct state.
115                 showDetails(mCurCheckPosition);
116             }
117         }
118 
119         @Override
onSaveInstanceState(Bundle outState)120         public void onSaveInstanceState(Bundle outState) {
121             super.onSaveInstanceState(outState);
122             outState.putInt("curChoice", mCurCheckPosition);
123         }
124 
125         @Override
onListItemClick(ListView l, View v, int position, long id)126         public void onListItemClick(ListView l, View v, int position, long id) {
127             showDetails(position);
128         }
129 
130         /**
131          * Helper function to show the details of a selected item, either by
132          * displaying a fragment in-place in the current UI, or starting a
133          * whole new activity in which it is displayed.
134          */
showDetails(int index)135         void showDetails(int index) {
136             mCurCheckPosition = index;
137 
138             if (mDualPane) {
139                 // We can display everything in-place with fragments, so update
140                 // the list to highlight the selected item and show the data.
141                 getListView().setItemChecked(index, true);
142 
143                 // Check what fragment is currently shown, replace if needed.
144                 DetailsFragment details = (DetailsFragment)
145                         getFragmentManager().findFragmentById(R.id.details);
146                 if (details == null || details.getShownIndex() != index) {
147                     // Make new fragment to show this selection.
148                     details = DetailsFragment.newInstance(index);
149 
150                     // Execute a transaction, replacing any existing fragment
151                     // with this one inside the frame.
152                     FragmentTransaction ft = getFragmentManager().beginTransaction();
153                     if (index == 0) {
154                         ft.replace(R.id.details, details);
155                     } else {
156                         ft.replace(R.id.a_item, details);
157                     }
158                     ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
159                     ft.commit();
160                 }
161 
162             } else {
163                 // Otherwise we need to launch a new activity to display
164                 // the dialog fragment with selected text.
165                 Intent intent = new Intent();
166                 intent.setClass(getActivity(), DetailsActivity.class);
167                 intent.putExtra("index", index);
168                 startActivity(intent);
169             }
170         }
171     }
172 //END_INCLUDE(titles)
173 
174     /**
175      * This is the secondary fragment, displaying the details of a particular
176      * item.
177      */
178 //BEGIN_INCLUDE(details)
179     public static class DetailsFragment extends Fragment {
180         /**
181          * Create a new instance of DetailsFragment, initialized to
182          * show the text at 'index'.
183          */
newInstance(int index)184         public static DetailsFragment newInstance(int index) {
185             DetailsFragment f = new DetailsFragment();
186 
187             // Supply index input as an argument.
188             Bundle args = new Bundle();
189             args.putInt("index", index);
190             f.setArguments(args);
191 
192             return f;
193         }
194 
getShownIndex()195         public int getShownIndex() {
196             return getArguments().getInt("index", 0);
197         }
198 
199         @Override
onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)200         public View onCreateView(LayoutInflater inflater, ViewGroup container,
201                 Bundle savedInstanceState) {
202             if (container == null) {
203                 // We have different layouts, and in one of them this
204                 // fragment's containing frame doesn't exist.  The fragment
205                 // may still be created from its saved state, but there is
206                 // no reason to try to create its view hierarchy because it
207                 // won't be displayed.  Note this is not needed -- we could
208                 // just run the code below, where we would create and return
209                 // the view hierarchy; it would just never be used.
210                 return null;
211             }
212 
213             ScrollView scroller = new ScrollView(getActivity());
214             TextView text = new TextView(getActivity());
215             int padding = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
216                     4, getActivity().getResources().getDisplayMetrics());
217             text.setPadding(padding, padding, padding, padding);
218             scroller.addView(text);
219             text.setText(Shakespeare.DIALOGUE[getShownIndex()]);
220             return scroller;
221         }
222     }
223 //END_INCLUDE(details)
224 }
225