am e7df2e3f: am f6457d05: Merge "Retroactively add EffectiveNavigation and TabCompat sample code." into jb-dev
* commit 'e7df2e3f6eb1f847cc362f70b062fc76e7825d30': Retroactively add EffectiveNavigation and TabCompat sample code.
38
samples/training/EffectiveNavigation/AndroidManifest.xml
Executable file
@@ -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>
|
||||
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 5.7 KiB |
35
samples/training/EffectiveNavigation/res/layout/activity_collection_demo.xml
Executable file
@@ -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>
|
||||
20
samples/training/EffectiveNavigation/res/layout/activity_main.xml
Executable file
@@ -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" />
|
||||
@@ -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" />
|
||||
@@ -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" />
|
||||
@@ -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>
|
||||
24
samples/training/EffectiveNavigation/res/values/strings.xml
Executable file
@@ -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>
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
32
samples/training/TabCompat/AndroidManifest.xml
Normal file
@@ -0,0 +1,32 @@
|
||||
<!--
|
||||
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.tabcompat"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0">
|
||||
|
||||
<uses-sdk android:minSdkVersion="5" android:targetSdkVersion="14" />
|
||||
|
||||
<application android:label="@string/app_name" android:icon="@drawable/ic_launcher">
|
||||
<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>
|
||||
</application>
|
||||
</manifest>
|
||||
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
BIN
samples/training/TabCompat/res/drawable-hdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
BIN
samples/training/TabCompat/res/drawable-hdpi/ic_tab_photos_selected.png
Executable file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
samples/training/TabCompat/res/drawable-hdpi/ic_tab_photos_unselected.png
Executable file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
samples/training/TabCompat/res/drawable-hdpi/ic_tab_videos_selected.png
Executable file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
samples/training/TabCompat/res/drawable-hdpi/ic_tab_videos_unselected.png
Executable file
|
After Width: | Height: | Size: 676 B |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
BIN
samples/training/TabCompat/res/drawable-mdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
BIN
samples/training/TabCompat/res/drawable-mdpi/ic_tab_photos_selected.png
Executable file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
samples/training/TabCompat/res/drawable-mdpi/ic_tab_photos_unselected.png
Executable file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
samples/training/TabCompat/res/drawable-mdpi/ic_tab_videos_selected.png
Executable file
|
After Width: | Height: | Size: 824 B |
BIN
samples/training/TabCompat/res/drawable-mdpi/ic_tab_videos_unselected.png
Executable file
|
After Width: | Height: | Size: 513 B |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
BIN
samples/training/TabCompat/res/drawable-xhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
BIN
samples/training/TabCompat/res/drawable-xhdpi/ic_tab_photos_selected.png
Executable file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
samples/training/TabCompat/res/drawable-xhdpi/ic_tab_photos_unselected.png
Executable file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
samples/training/TabCompat/res/drawable-xhdpi/ic_tab_videos_selected.png
Executable file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
samples/training/TabCompat/res/drawable-xhdpi/ic_tab_videos_unselected.png
Executable file
|
After Width: | Height: | Size: 853 B |
22
samples/training/TabCompat/res/drawable/ic_tab_photos.xml
Executable file
@@ -0,0 +1,22 @@
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/ic_tab_photos_selected"
|
||||
android:state_selected="true"
|
||||
android:state_pressed="false" />
|
||||
<item android:drawable="@drawable/ic_tab_photos_unselected" />
|
||||
</selector>
|
||||
22
samples/training/TabCompat/res/drawable/ic_tab_videos.xml
Executable file
@@ -0,0 +1,22 @@
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/ic_tab_videos_selected"
|
||||
android:state_selected="true"
|
||||
android:state_pressed="false" />
|
||||
<item android:drawable="@drawable/ic_tab_videos_unselected" />
|
||||
</selector>
|
||||
21
samples/training/TabCompat/res/layout-v11/main.xml
Normal file
@@ -0,0 +1,21 @@
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
<!-- API level 11+ only needs the container for tab content. -->
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@android:id/tabcontent"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
40
samples/training/TabCompat/res/layout/main.xml
Normal file
@@ -0,0 +1,40 @@
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
<!-- This layout is for API level 5-10 only. -->
|
||||
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@android:id/tabhost"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<TabWidget
|
||||
android:id="@android:id/tabs"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@android:id/tabcontent"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
</LinearLayout>
|
||||
</TabHost>
|
||||
22
samples/training/TabCompat/res/values/strings.xml
Normal file
@@ -0,0 +1,22 @@
|
||||
<!--
|
||||
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">Tab Demo</string>
|
||||
|
||||
<string name="tab_photos">Photos</string>
|
||||
<string name="tab_videos">Videos</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* 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.tabcompat;
|
||||
|
||||
import com.example.android.tabcompat.lib.CompatTab;
|
||||
import com.example.android.tabcompat.lib.CompatTabListener;
|
||||
import com.example.android.tabcompat.lib.TabCompatActivity;
|
||||
import com.example.android.tabcompat.lib.TabHelper;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentTransaction;
|
||||
import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class MainActivity extends TabCompatActivity {
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.main);
|
||||
|
||||
TabHelper tabHelper = getTabHelper();
|
||||
|
||||
CompatTab photosTab = tabHelper.newTab("photos")
|
||||
.setText(R.string.tab_photos)
|
||||
.setIcon(R.drawable.ic_tab_photos)
|
||||
.setTabListener(new InstantiatingTabListener(this, PhotosFragment.class));
|
||||
tabHelper.addTab(photosTab);
|
||||
|
||||
CompatTab videosTab = tabHelper.newTab("videos")
|
||||
.setText(R.string.tab_videos)
|
||||
.setIcon(R.drawable.ic_tab_videos)
|
||||
.setTabListener(new InstantiatingTabListener(this, VideosFragment.class));
|
||||
tabHelper.addTab(videosTab);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of {@link CompatTabListener} to handle tab change events. This implementation
|
||||
* instantiates the specified fragment class with no arguments when its tab is selected.
|
||||
*/
|
||||
public static class InstantiatingTabListener implements CompatTabListener {
|
||||
|
||||
private final TabCompatActivity mActivity;
|
||||
private final Class mClass;
|
||||
|
||||
/**
|
||||
* Constructor used each time a new tab is created.
|
||||
*
|
||||
* @param activity The host Activity, used to instantiate the fragment
|
||||
* @param cls The class representing the fragment to instantiate
|
||||
*/
|
||||
public InstantiatingTabListener(TabCompatActivity activity, Class<? extends Fragment> cls) {
|
||||
mActivity = activity;
|
||||
mClass = cls;
|
||||
}
|
||||
|
||||
/* The following are each of the ActionBar.TabListener callbacks */
|
||||
@Override
|
||||
public void onTabSelected(CompatTab tab, FragmentTransaction ft) {
|
||||
// Check if the fragment is already initialized
|
||||
Fragment fragment = tab.getFragment();
|
||||
if (fragment == null) {
|
||||
// If not, instantiate and add it to the activity
|
||||
fragment = Fragment.instantiate(mActivity, mClass.getName());
|
||||
tab.setFragment(fragment);
|
||||
ft.add(android.R.id.tabcontent, fragment, tab.getTag());
|
||||
} else {
|
||||
// If it exists, simply attach it in order to show it
|
||||
ft.attach(fragment);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabUnselected(CompatTab tab, FragmentTransaction ft) {
|
||||
Fragment fragment = tab.getFragment();
|
||||
if (fragment != null) {
|
||||
// Detach the fragment, because another one is being attached
|
||||
ft.detach(fragment);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabReselected(CompatTab tab, FragmentTransaction ft) {
|
||||
// User selected the already selected tab. Do nothing.
|
||||
}
|
||||
}
|
||||
|
||||
public static class PhotosFragment extends Fragment {
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
TextView textView = new TextView(getActivity());
|
||||
textView.setGravity(Gravity.CENTER);
|
||||
textView.setText(R.string.tab_photos);
|
||||
return textView;
|
||||
}
|
||||
}
|
||||
|
||||
public static class VideosFragment extends Fragment {
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
TextView textView = new TextView(getActivity());
|
||||
textView.setGravity(Gravity.CENTER);
|
||||
textView.setText(R.string.tab_videos);
|
||||
return textView;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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.tabcompat.lib;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
|
||||
/**
|
||||
* Represents a single tab.
|
||||
* The {@link TabHelper} initializes one of the subclasses of this based
|
||||
* on the current platform version, upon call to {@link TabHelper#newTab(String)}()
|
||||
*/
|
||||
public abstract class CompatTab {
|
||||
final FragmentActivity mActivity;
|
||||
final String mTag;
|
||||
|
||||
protected CompatTab(FragmentActivity activity, String tag) {
|
||||
mActivity = activity;
|
||||
mTag = tag;
|
||||
}
|
||||
|
||||
public abstract CompatTab setText(int resId);
|
||||
public abstract CompatTab setIcon(int resId);
|
||||
public abstract CompatTab setTabListener(CompatTabListener callback);
|
||||
public abstract CompatTab setFragment(Fragment fragment);
|
||||
|
||||
public abstract CharSequence getText();
|
||||
public abstract Drawable getIcon();
|
||||
public abstract CompatTabListener getCallback();
|
||||
public abstract Fragment getFragment();
|
||||
|
||||
public abstract Object getTab();
|
||||
|
||||
public String getTag() {
|
||||
return mTag;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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.tabcompat.lib;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
|
||||
/**
|
||||
* A base implementation of the {@link CompatTab} interface.
|
||||
*/
|
||||
public class CompatTabEclair extends CompatTab {
|
||||
private CompatTabListener mCallback;
|
||||
private CharSequence mText;
|
||||
private Drawable mIcon;
|
||||
private Fragment mFragment;
|
||||
|
||||
protected CompatTabEclair(FragmentActivity activity, String tag) {
|
||||
super(activity, tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompatTab setText(int resId) {
|
||||
mText = mActivity.getResources().getText(resId);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompatTab setIcon(int resId) {
|
||||
mIcon = mActivity.getResources().getDrawable(resId);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompatTab setTabListener(CompatTabListener callback) {
|
||||
mCallback = callback;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompatTab setFragment(Fragment fragment) {
|
||||
mFragment = fragment;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fragment getFragment() {
|
||||
return mFragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getText() {
|
||||
return mText;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Drawable getIcon() {
|
||||
return mIcon;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getTab() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompatTabListener getCallback() {
|
||||
return mCallback;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* 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.tabcompat.lib;
|
||||
|
||||
import android.app.ActionBar;
|
||||
import android.app.ActionBar.Tab;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.support.v4.app.FragmentTransaction;
|
||||
|
||||
/**
|
||||
* An implementation of the {@link CompatTab} interface that relies on API 11 APIs.
|
||||
*/
|
||||
public class CompatTabHoneycomb extends CompatTab implements ActionBar.TabListener {
|
||||
|
||||
/**
|
||||
* The native tab object that this {@link CompatTab} acts as a proxy for.
|
||||
*/
|
||||
ActionBar.Tab mTab;
|
||||
CompatTabListener mCallback;
|
||||
Fragment mFragment;
|
||||
|
||||
protected CompatTabHoneycomb(FragmentActivity activity, String tag) {
|
||||
super(activity, tag);
|
||||
mTab = activity.getActionBar().newTab();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompatTab setText(int resId) {
|
||||
mTab.setText(resId);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompatTab setIcon(int resId) {
|
||||
mTab.setIcon(resId);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompatTab setTabListener(CompatTabListener callback) {
|
||||
mCallback = callback;
|
||||
mTab.setTabListener(this);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getText() {
|
||||
return mTab.getText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Drawable getIcon() {
|
||||
return mTab.getIcon();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getTab() {
|
||||
return mTab;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompatTabListener getCallback() {
|
||||
return mCallback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabReselected(Tab tab, android.app.FragmentTransaction f) {
|
||||
FragmentTransaction ft = mActivity.getSupportFragmentManager().beginTransaction();
|
||||
ft.disallowAddToBackStack();
|
||||
mCallback.onTabReselected(this, ft);
|
||||
ft.commit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabSelected(Tab tab, android.app.FragmentTransaction f) {
|
||||
FragmentTransaction ft = mActivity.getSupportFragmentManager().beginTransaction();
|
||||
ft.disallowAddToBackStack();
|
||||
mCallback.onTabSelected(this, ft);
|
||||
ft.commit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabUnselected(Tab arg0, android.app.FragmentTransaction f) {
|
||||
FragmentTransaction ft = mActivity.getSupportFragmentManager().beginTransaction();
|
||||
ft.disallowAddToBackStack();
|
||||
mCallback.onTabUnselected(this, ft);
|
||||
ft.commit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompatTab setFragment(Fragment fragment) {
|
||||
mFragment = fragment;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fragment getFragment() {
|
||||
return mFragment;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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.tabcompat.lib;
|
||||
|
||||
import android.support.v4.app.FragmentTransaction;
|
||||
|
||||
/**
|
||||
* @see android.app.ActionBar.TabListener
|
||||
*/
|
||||
public interface CompatTabListener {
|
||||
/**
|
||||
* @see android.app.ActionBar.TabListener#onTabSelected(
|
||||
*android.app.ActionBar.Tab, android.app.FragmentTransaction)
|
||||
*/
|
||||
public void onTabSelected(CompatTab tab, FragmentTransaction ft);
|
||||
|
||||
/**
|
||||
* @see android.app.ActionBar.TabListener#onTabUnselected(
|
||||
*android.app.ActionBar.Tab, android.app.FragmentTransaction)
|
||||
*/
|
||||
public void onTabUnselected(CompatTab tab, FragmentTransaction ft);
|
||||
|
||||
/**
|
||||
* @see android.app.ActionBar.TabListener#onTabReselected(
|
||||
*android.app.ActionBar.Tab, android.app.FragmentTransaction)
|
||||
*/
|
||||
public void onTabReselected(CompatTab tab, FragmentTransaction ft);
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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.tabcompat.lib;
|
||||
|
||||
import com.example.android.tabcompat.lib.TabHelper;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
|
||||
/**
|
||||
* A base activity that defers tab functionality to a {@link TabHelper}.
|
||||
*
|
||||
* When building an activity with tabs, extend this class in order to provide compatibility with API
|
||||
* level 5 and above. Using this class along with the {@link TabHelper} and {@link com.example.android.tabcompat.lib.CompatTab}
|
||||
* classes, you can build a tab UI that's built using the {@link android.app.ActionBar} on
|
||||
* Honeycomb+ and the {@link android.widget.TabWidget} on all older versions.
|
||||
*
|
||||
* The {@link TabHelper} APIs obfuscate all the compatibility work for you.
|
||||
*/
|
||||
public abstract class TabCompatActivity extends FragmentActivity {
|
||||
|
||||
TabHelper mTabHelper;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mTabHelper = TabHelper.createInstance(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mTabHelper.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestoreInstanceState(Bundle savedInstanceState) {
|
||||
super.onRestoreInstanceState(savedInstanceState);
|
||||
mTabHelper.onRestoreInstanceState(savedInstanceState);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link TabHelper} for this activity.
|
||||
*/
|
||||
protected TabHelper getTabHelper() {
|
||||
mTabHelper.setUp();
|
||||
return mTabHelper;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* 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.tabcompat.lib;
|
||||
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
|
||||
/**
|
||||
* Convenience helper to build a set of tabs for a {@link TabCompatActivity}. To use this class,
|
||||
* extend {@link TabCompatActivity} and:
|
||||
*
|
||||
* Call {@link TabCompatActivity#getTabHelper()}, returning a {@link TabHelper}.
|
||||
*
|
||||
* Create a {@link CompatTabListener}.
|
||||
*
|
||||
* Call {@link TabHelper#newTab(String)} to create each tab.
|
||||
*
|
||||
* Call CompatTab.setText().setIcon().setTabListener() to set up your tabs.
|
||||
*
|
||||
* Call {@link TabHelper#addTab(CompatTab)} for each tab, and you're done.
|
||||
*/
|
||||
public abstract class TabHelper {
|
||||
|
||||
protected FragmentActivity mActivity;
|
||||
|
||||
protected TabHelper(FragmentActivity activity) {
|
||||
mActivity = activity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method for creating TabHelper objects for a given activity. Depending on which device
|
||||
* the app is running, either a basic helper or Honeycomb-specific helper will be returned.
|
||||
* Don't call this yourself; the TabCompatActivity instantiates one. Instead call
|
||||
* TabCompatActivity.getTabHelper().
|
||||
*/
|
||||
public static TabHelper createInstance(FragmentActivity activity) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
|
||||
return new TabHelperHoneycomb(activity);
|
||||
} else {
|
||||
return new TabHelperEclair(activity);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new tab.
|
||||
*
|
||||
* @param tag A unique tag to associate with the tab and associated fragment
|
||||
* @return CompatTab for the appropriate android version
|
||||
*/
|
||||
public CompatTab newTab(String tag) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
|
||||
return new CompatTabHoneycomb(mActivity, tag);
|
||||
} else {
|
||||
return new CompatTabEclair(mActivity, tag);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void addTab(CompatTab tab);
|
||||
|
||||
protected abstract void onSaveInstanceState(Bundle outState);
|
||||
|
||||
protected abstract void onRestoreInstanceState(Bundle savedInstanceState);
|
||||
|
||||
protected abstract void setUp();
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* 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.tabcompat.lib;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.support.v4.app.FragmentTransaction;
|
||||
import android.view.View;
|
||||
import android.widget.TabHost;
|
||||
import android.widget.TabHost.TabSpec;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* This is a helper class to build tabs on pre-Honeycomb. Call {@link
|
||||
* TabCompatActivity#getTabHelper()} to get the generic instance for
|
||||
* compatibility with other versions.
|
||||
*
|
||||
* It implements a generic mechanism for associating fragments with the tabs in a tab host. It
|
||||
* relies on a trick: Normally a tab host has a simple API for supplying a View or Intent that each
|
||||
* tab will show. This is not sufficient for switching between fragments. So instead we make the
|
||||
* content part of the tab host 0dp high (it is not shown) and this supplies its own dummy view to
|
||||
* show as the tab content. It listens to changes in tabs, then passes the event back to the tab's
|
||||
* callback interface so the activity can take care of switching to the correct fragment.
|
||||
*/
|
||||
public class TabHelperEclair extends TabHelper implements TabHost.OnTabChangeListener {
|
||||
|
||||
private final HashMap<String, CompatTab> mTabs = new HashMap<String, CompatTab>();
|
||||
private TabHost mTabHost;
|
||||
CompatTabListener mCallback;
|
||||
CompatTab mLastTab;
|
||||
|
||||
protected TabHelperEclair(FragmentActivity activity) {
|
||||
super(activity);
|
||||
mActivity = activity;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() {
|
||||
if (mTabHost == null) {
|
||||
mTabHost = (TabHost) mActivity.findViewById(android.R.id.tabhost);
|
||||
mTabHost.setup();
|
||||
mTabHost.setOnTabChangedListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTab(CompatTab tab) {
|
||||
String tag = tab.getTag();
|
||||
TabSpec spec;
|
||||
|
||||
if (tab.getIcon() != null) {
|
||||
spec = mTabHost.newTabSpec(tag).setIndicator(tab.getText(), tab.getIcon());
|
||||
} else {
|
||||
spec = mTabHost.newTabSpec(tag).setIndicator(tab.getText());
|
||||
}
|
||||
|
||||
spec.setContent(new DummyTabFactory(mActivity));
|
||||
|
||||
// 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.
|
||||
|
||||
Fragment fragment = mActivity.getSupportFragmentManager().findFragmentByTag(tag);
|
||||
tab.setFragment(fragment);
|
||||
|
||||
if (fragment != null && !fragment.isDetached()) {
|
||||
FragmentTransaction ft = mActivity.getSupportFragmentManager().beginTransaction();
|
||||
ft.detach(fragment);
|
||||
ft.commit();
|
||||
}
|
||||
|
||||
mTabs.put(tag, tab);
|
||||
mTabHost.addTab(spec);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the basic "tab changed" event for TabWidget into the three possible events for
|
||||
* CompatTabListener: selected, unselected, reselected.
|
||||
*/
|
||||
@Override
|
||||
public void onTabChanged(String tabId) {
|
||||
CompatTab newTab = mTabs.get(tabId);
|
||||
FragmentTransaction ft = mActivity.getSupportFragmentManager().beginTransaction();
|
||||
|
||||
if (mLastTab != newTab) {
|
||||
if (mLastTab != null) {
|
||||
if (mLastTab.getFragment() != null) {
|
||||
// Pass the unselected event back to the tab's CompatTabListener
|
||||
mLastTab.getCallback().onTabUnselected(mLastTab, ft);
|
||||
}
|
||||
}
|
||||
if (newTab != null) {
|
||||
// Pass the selected event back to the tab's CompatTabListener
|
||||
newTab.getCallback().onTabSelected(newTab, ft);
|
||||
}
|
||||
|
||||
mLastTab = newTab;
|
||||
} else {
|
||||
// Pass the re-selected event back to the tab's CompatTabListener
|
||||
newTab.getCallback().onTabReselected(newTab, ft);
|
||||
}
|
||||
|
||||
ft.commit();
|
||||
mActivity.getSupportFragmentManager().executePendingTransactions();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
// Save and restore the selected tab for rotations/restarts.
|
||||
outState.putString("tab", mTabHost.getCurrentTabTag());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestoreInstanceState(Bundle savedInstanceState) {
|
||||
if (savedInstanceState != null) {
|
||||
mTabHost.setCurrentTabByTag(savedInstanceState.getString("tab"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Backwards-compatibility mumbo jumbo
|
||||
*/
|
||||
static class DummyTabFactory implements TabHost.TabContentFactory {
|
||||
|
||||
private final Context mContext;
|
||||
|
||||
public DummyTabFactory(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View createTabContent(String tag) {
|
||||
View v = new View(mContext);
|
||||
v.setMinimumWidth(0);
|
||||
v.setMinimumHeight(0);
|
||||
return v;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* 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.tabcompat.lib;
|
||||
|
||||
import android.app.ActionBar;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.support.v4.app.FragmentTransaction;
|
||||
|
||||
/**
|
||||
* Helper class to build tabs on Honeycomb. Call {@link TabCompatActivity#getTabHelper()}
|
||||
* to get the generic instance for compatibility with older versions.
|
||||
*/
|
||||
public class TabHelperHoneycomb extends TabHelper {
|
||||
|
||||
ActionBar mActionBar;
|
||||
|
||||
protected TabHelperHoneycomb(FragmentActivity activity) {
|
||||
super(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() {
|
||||
if (mActionBar == null) {
|
||||
mActionBar = mActivity.getActionBar();
|
||||
mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTab(CompatTab tab) {
|
||||
String tag = tab.getTag();
|
||||
|
||||
// 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.
|
||||
|
||||
Fragment fragment = mActivity.getSupportFragmentManager().findFragmentByTag(tag);
|
||||
tab.setFragment(fragment);
|
||||
|
||||
if (fragment != null && !fragment.isDetached()) {
|
||||
FragmentTransaction ft = mActivity.getSupportFragmentManager().beginTransaction();
|
||||
ft.detach(fragment);
|
||||
ft.commit();
|
||||
}
|
||||
|
||||
if (tab.getCallback() == null) {
|
||||
throw new IllegalStateException("CompatTab must have a CompatTabListener");
|
||||
}
|
||||
|
||||
// We know tab is a CompatTabHoneycomb instance, so its
|
||||
// native tab object is an ActionBar.Tab.
|
||||
mActionBar.addTab((ActionBar.Tab) tab.getTab());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
int position = mActionBar.getSelectedTab().getPosition();
|
||||
outState.putInt("tab_position", position);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestoreInstanceState(Bundle savedInstanceState) {
|
||||
int position = savedInstanceState.getInt("tab_position");
|
||||
mActionBar.setSelectedNavigationItem(position);
|
||||
}
|
||||
}
|
||||