diff options
author | Roman Nurik <romannurik@google.com> | 2012-08-10 14:48:22 -0700 |
---|---|---|
committer | Roman Nurik <romannurik@google.com> | 2012-08-22 08:05:28 -0700 |
commit | d80ee0201141613b1bb12b8e64b4efbe885fda0d (patch) | |
tree | e3ecdbb5c003408f061657963616e5502812460f /samples/training/EffectiveNavigation | |
parent | ef91cce81b6b89c5d47c6fbda9ea913a95fa7d46 (diff) | |
download | android_development-d80ee0201141613b1bb12b8e64b4efbe885fda0d.tar.gz android_development-d80ee0201141613b1bb12b8e64b4efbe885fda0d.tar.bz2 android_development-d80ee0201141613b1bb12b8e64b4efbe885fda0d.zip |
Retroactively add EffectiveNavigation and TabCompat sample code.
This sample code was launched with the Implementing Effective Navigation and
Creating Backward-Compatible UIs training classes, but the source was never
added to AOSP. This retroactively adds the source, unmodified.
Change-Id: If6face5a0548107f7fd273e466b1ced2790f4f3a
Diffstat (limited to 'samples/training/EffectiveNavigation')
13 files changed, 554 insertions, 0 deletions
diff --git a/samples/training/EffectiveNavigation/AndroidManifest.xml b/samples/training/EffectiveNavigation/AndroidManifest.xml new file mode 100755 index 000000000..b1e4e11f3 --- /dev/null +++ b/samples/training/EffectiveNavigation/AndroidManifest.xml @@ -0,0 +1,38 @@ +<!-- + Copyright 2012 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.example.android.effectivenavigation" + android:versionCode="1" + android:versionName="1.0"> + + <uses-sdk android:minSdkVersion="14" /> + + <application android:label="@string/app_name" + android:icon="@drawable/ic_launcher" + android:theme="@android:style/Theme.Holo.Light.DarkActionBar"> + + <activity android:name=".MainActivity" 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=".CollectionDemoActivity" android:label="@string/demo_collection" /> + + </application> +</manifest> diff --git a/samples/training/EffectiveNavigation/res/drawable-hdpi/ic_launcher.png b/samples/training/EffectiveNavigation/res/drawable-hdpi/ic_launcher.png Binary files differnew file mode 100644 index 000000000..d2dae4c48 --- /dev/null +++ b/samples/training/EffectiveNavigation/res/drawable-hdpi/ic_launcher.png diff --git a/samples/training/EffectiveNavigation/res/drawable-ldpi/ic_launcher.png b/samples/training/EffectiveNavigation/res/drawable-ldpi/ic_launcher.png Binary files differnew file mode 100644 index 000000000..d30b9651a --- /dev/null +++ b/samples/training/EffectiveNavigation/res/drawable-ldpi/ic_launcher.png diff --git a/samples/training/EffectiveNavigation/res/drawable-mdpi/ic_launcher.png b/samples/training/EffectiveNavigation/res/drawable-mdpi/ic_launcher.png Binary files differnew file mode 100644 index 000000000..66253457d --- /dev/null +++ b/samples/training/EffectiveNavigation/res/drawable-mdpi/ic_launcher.png diff --git a/samples/training/EffectiveNavigation/res/drawable-xhdpi/ic_launcher.png b/samples/training/EffectiveNavigation/res/drawable-xhdpi/ic_launcher.png Binary files differnew file mode 100644 index 000000000..67331ceb0 --- /dev/null +++ b/samples/training/EffectiveNavigation/res/drawable-xhdpi/ic_launcher.png diff --git a/samples/training/EffectiveNavigation/res/layout/activity_collection_demo.xml b/samples/training/EffectiveNavigation/res/layout/activity_collection_demo.xml new file mode 100755 index 000000000..e34f471ff --- /dev/null +++ b/samples/training/EffectiveNavigation/res/layout/activity_collection_demo.xml @@ -0,0 +1,35 @@ +<!-- + Copyright 2012 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/pager" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <!-- + This title strip will display the currently visible page title, as well as the page + titles for adjacent pages. + --> + <android.support.v4.view.PagerTitleStrip android:id="@+id/pager_title_strip" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="top" + android:background="#33b5e5" + android:textColor="#fff" + android:paddingTop="4dp" + android:paddingBottom="4dp" /> + +</android.support.v4.view.ViewPager> diff --git a/samples/training/EffectiveNavigation/res/layout/activity_main.xml b/samples/training/EffectiveNavigation/res/layout/activity_main.xml new file mode 100755 index 000000000..339b592d5 --- /dev/null +++ b/samples/training/EffectiveNavigation/res/layout/activity_main.xml @@ -0,0 +1,20 @@ +<!-- + Copyright 2012 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/pager" + android:layout_width="match_parent" + android:layout_height="match_parent" /> diff --git a/samples/training/EffectiveNavigation/res/layout/fragment_collection_object.xml b/samples/training/EffectiveNavigation/res/layout/fragment_collection_object.xml new file mode 100644 index 000000000..945bf066b --- /dev/null +++ b/samples/training/EffectiveNavigation/res/layout/fragment_collection_object.xml @@ -0,0 +1,23 @@ +<!-- + Copyright 2012 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<TextView xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@android:id/text1" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:gravity="center" + android:textSize="128sp" + android:padding="32dp" /> diff --git a/samples/training/EffectiveNavigation/res/layout/fragment_section_dummy.xml b/samples/training/EffectiveNavigation/res/layout/fragment_section_dummy.xml new file mode 100644 index 000000000..1c678859e --- /dev/null +++ b/samples/training/EffectiveNavigation/res/layout/fragment_section_dummy.xml @@ -0,0 +1,23 @@ +<!-- + Copyright 2012 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<TextView xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@android:id/text1" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:gravity="center" + android:textSize="24sp" + android:padding="32dp" /> diff --git a/samples/training/EffectiveNavigation/res/layout/fragment_section_launchpad.xml b/samples/training/EffectiveNavigation/res/layout/fragment_section_launchpad.xml new file mode 100644 index 000000000..186b2f2a9 --- /dev/null +++ b/samples/training/EffectiveNavigation/res/layout/fragment_section_launchpad.xml @@ -0,0 +1,39 @@ +<!-- + Copyright 2012 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <LinearLayout android:orientation="vertical" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center"> + + <Button android:id="@+id/demo_collection_button" + android:layout_width="300dp" + android:layout_height="wrap_content" + android:layout_marginBottom="16dp" + android:text="@string/demo_collection"/> + + <Button android:id="@+id/demo_external_activity" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/demo_external_activity" /> + + </LinearLayout> + +</FrameLayout> diff --git a/samples/training/EffectiveNavigation/res/values/strings.xml b/samples/training/EffectiveNavigation/res/values/strings.xml new file mode 100755 index 000000000..4ea2dbb3b --- /dev/null +++ b/samples/training/EffectiveNavigation/res/values/strings.xml @@ -0,0 +1,24 @@ +<!-- + Copyright 2012 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<resources> + <string name="app_name">Effective Navigation</string> + + <string name="dummy_section_text">Section %1d is just a dummy section.</string> + + <string name="demo_external_activity">Demo External Activity</string> + <string name="demo_collection">Demo Collection</string> +</resources> diff --git a/samples/training/EffectiveNavigation/src/com/example/android/effectivenavigation/CollectionDemoActivity.java b/samples/training/EffectiveNavigation/src/com/example/android/effectivenavigation/CollectionDemoActivity.java new file mode 100755 index 000000000..641d1a493 --- /dev/null +++ b/samples/training/EffectiveNavigation/src/com/example/android/effectivenavigation/CollectionDemoActivity.java @@ -0,0 +1,148 @@ +/* + * Copyright 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.android.effectivenavigation; + +import android.app.ActionBar; +import android.content.Intent; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentActivity; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentStatePagerAdapter; +import android.support.v4.app.NavUtils; +import android.support.v4.app.TaskStackBuilder; +import android.support.v4.view.ViewPager; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +public class CollectionDemoActivity extends FragmentActivity { + + /** + * The {@link android.support.v4.view.PagerAdapter} that will provide fragments representing + * each object in a collection. We use a {@link android.support.v4.app.FragmentStatePagerAdapter} + * derivative, which will destroy and re-create fragments as needed, saving and restoring their + * state in the process. This is important to conserve memory and is a best practice when + * allowing navigation between objects in a potentially large collection. + */ + DemoCollectionPagerAdapter mDemoCollectionPagerAdapter; + + /** + * The {@link android.support.v4.view.ViewPager} that will display the object collection. + */ + ViewPager mViewPager; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_collection_demo); + + // Create an adapter that when requested, will return a fragment representing an object in + // the collection. + // + // ViewPager and its adapters use support library fragments, so we must use + // getSupportFragmentManager. + mDemoCollectionPagerAdapter = new DemoCollectionPagerAdapter(getSupportFragmentManager()); + + // Set up action bar. + final ActionBar actionBar = getActionBar(); + + // Specify that the Home button should show an "Up" caret, indicating that touching the + // button will take the user one step up in the application's hierarchy. + actionBar.setDisplayHomeAsUpEnabled(true); + + // Set up the ViewPager, attaching the adapter. + mViewPager = (ViewPager) findViewById(R.id.pager); + mViewPager.setAdapter(mDemoCollectionPagerAdapter); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + // This is called when the Home (Up) button is pressed in the action bar. + // Create a simple intent that starts the hierarchical parent activity and + // use NavUtils in the Support Package to ensure proper handling of Up. + Intent upIntent = new Intent(this, MainActivity.class); + if (NavUtils.shouldUpRecreateTask(this, upIntent)) { + // This activity is not part of the application's task, so create a new task + // with a synthesized back stack. + TaskStackBuilder.from(this) + // If there are ancestor activities, they should be added here. + .addNextIntent(upIntent) + .startActivities(); + finish(); + } else { + // This activity is part of the application's task, so simply + // navigate up to the hierarchical parent activity. + NavUtils.navigateUpTo(this, upIntent); + } + return true; + } + return super.onOptionsItemSelected(item); + } + + /** + * A {@link android.support.v4.app.FragmentStatePagerAdapter} that returns a fragment + * representing an object in the collection. + */ + public static class DemoCollectionPagerAdapter extends FragmentStatePagerAdapter { + + public DemoCollectionPagerAdapter(FragmentManager fm) { + super(fm); + } + + @Override + public Fragment getItem(int i) { + Fragment fragment = new DemoObjectFragment(); + Bundle args = new Bundle(); + args.putInt(DemoObjectFragment.ARG_OBJECT, i + 1); // Our object is just an integer :-P + fragment.setArguments(args); + return fragment; + } + + @Override + public int getCount() { + // For this contrived example, we have a 100-object collection. + return 100; + } + + @Override + public CharSequence getPageTitle(int position) { + return "OBJECT " + (position + 1); + } + } + + /** + * A dummy fragment representing a section of the app, but that simply displays dummy text. + */ + public static class DemoObjectFragment extends Fragment { + + public static final String ARG_OBJECT = "object"; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View rootView = inflater.inflate(R.layout.fragment_collection_object, container, false); + Bundle args = getArguments(); + ((TextView) rootView.findViewById(android.R.id.text1)).setText( + Integer.toString(args.getInt(ARG_OBJECT))); + return rootView; + } + } +} diff --git a/samples/training/EffectiveNavigation/src/com/example/android/effectivenavigation/MainActivity.java b/samples/training/EffectiveNavigation/src/com/example/android/effectivenavigation/MainActivity.java new file mode 100755 index 000000000..a560ee4e4 --- /dev/null +++ b/samples/training/EffectiveNavigation/src/com/example/android/effectivenavigation/MainActivity.java @@ -0,0 +1,204 @@ +/* + * Copyright 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.android.effectivenavigation; + +import android.app.ActionBar; +import android.app.FragmentTransaction; +import android.content.Intent; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentActivity; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentPagerAdapter; +import android.support.v4.view.ViewPager; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +public class MainActivity extends FragmentActivity implements ActionBar.TabListener { + + /** + * The {@link android.support.v4.view.PagerAdapter} that will provide fragments for each of the + * three primary sections of the app. We use a {@link android.support.v4.app.FragmentPagerAdapter} + * derivative, which will keep every loaded fragment in memory. If this becomes too memory + * intensive, it may be best to switch to a {@link android.support.v4.app.FragmentStatePagerAdapter}. + */ + AppSectionsPagerAdapter mAppSectionsPagerAdapter; + + /** + * The {@link ViewPager} that will display the three primary sections of the app, one at a + * time. + */ + ViewPager mViewPager; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + // Create the adapter that will return a fragment for each of the three primary sections + // of the app. + mAppSectionsPagerAdapter = new AppSectionsPagerAdapter(getSupportFragmentManager()); + + // Set up the action bar. + final ActionBar actionBar = getActionBar(); + + // Specify that the Home/Up button should not be enabled, since there is no hierarchical + // parent. + actionBar.setHomeButtonEnabled(false); + + // Specify that we will be displaying tabs in the action bar. + actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); + + // Set up the ViewPager, attaching the adapter and setting up a listener for when the + // user swipes between sections. + mViewPager = (ViewPager) findViewById(R.id.pager); + mViewPager.setAdapter(mAppSectionsPagerAdapter); + mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { + @Override + public void onPageSelected(int position) { + // When swiping between different app sections, select the corresponding tab. + // We can also use ActionBar.Tab#select() to do this if we have a reference to the + // Tab. + actionBar.setSelectedNavigationItem(position); + } + }); + + // For each of the sections in the app, add a tab to the action bar. + for (int i = 0; i < mAppSectionsPagerAdapter.getCount(); i++) { + // Create a tab with text corresponding to the page title defined by the adapter. + // Also specify this Activity object, which implements the TabListener interface, as the + // listener for when this tab is selected. + actionBar.addTab( + actionBar.newTab() + .setText(mAppSectionsPagerAdapter.getPageTitle(i)) + .setTabListener(this)); + } + } + + @Override + public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) { + } + + @Override + public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) { + // When the given tab is selected, switch to the corresponding page in the ViewPager. + mViewPager.setCurrentItem(tab.getPosition()); + } + + @Override + public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) { + } + + /** + * A {@link FragmentPagerAdapter} that returns a fragment corresponding to one of the primary + * sections of the app. + */ + public static class AppSectionsPagerAdapter extends FragmentPagerAdapter { + + public AppSectionsPagerAdapter(FragmentManager fm) { + super(fm); + } + + @Override + public Fragment getItem(int i) { + switch (i) { + case 0: + // The first section of the app is the most interesting -- it offers + // a launchpad into the other demonstrations in this example application. + return new LaunchpadSectionFragment(); + + default: + // The other sections of the app are dummy placeholders. + Fragment fragment = new DummySectionFragment(); + Bundle args = new Bundle(); + args.putInt(DummySectionFragment.ARG_SECTION_NUMBER, i + 1); + fragment.setArguments(args); + return fragment; + } + } + + @Override + public int getCount() { + return 3; + } + + @Override + public CharSequence getPageTitle(int position) { + return "Section " + (position + 1); + } + } + + /** + * A fragment that launches other parts of the demo application. + */ + public static class LaunchpadSectionFragment extends Fragment { + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View rootView = inflater.inflate(R.layout.fragment_section_launchpad, container, false); + + // Demonstration of a collection-browsing activity. + rootView.findViewById(R.id.demo_collection_button) + .setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Intent intent = new Intent(getActivity(), CollectionDemoActivity.class); + startActivity(intent); + } + }); + + // Demonstration of navigating to external activities. + rootView.findViewById(R.id.demo_external_activity) + .setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + // Create an intent that asks the user to pick a photo, but using + // FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET, ensures that relaunching + // the application from the device home screen does not return + // to the external activity. + Intent externalActivityIntent = new Intent(Intent.ACTION_PICK); + externalActivityIntent.setType("image/*"); + externalActivityIntent.addFlags( + Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); + startActivity(externalActivityIntent); + } + }); + + return rootView; + } + } + + /** + * A dummy fragment representing a section of the app, but that simply displays dummy text. + */ + public static class DummySectionFragment extends Fragment { + + public static final String ARG_SECTION_NUMBER = "section_number"; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View rootView = inflater.inflate(R.layout.fragment_section_dummy, container, false); + Bundle args = getArguments(); + ((TextView) rootView.findViewById(android.R.id.text1)).setText( + getString(R.string.dummy_section_text, args.getInt(ARG_SECTION_NUMBER))); + return rootView; + } + } +} |