diff options
author | Yuichi Araki <yaraki@google.com> | 2017-01-27 03:38:11 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2017-01-27 03:38:11 +0000 |
commit | ff97ffea300b8561268d0d5f7ee05aadd3854c19 (patch) | |
tree | 17dc6486e8b5f7a01688c8c66da26c33423bef13 /ui/views | |
parent | a517b250d04b3772ad2408a460668cd65c6019c7 (diff) | |
parent | 71bf6ed9e33077216838953706ad3cadb002cce4 (diff) | |
download | android-ff97ffea300b8561268d0d5f7ee05aadd3854c19.tar.gz |
EffectiveNavigation: Revive an old sample am: 559783ec49 am: cd20fac4b6 am: 412540d443
am: 71bf6ed9e3
Change-Id: I2c173a1b7d07bc549d68272d5694b05c6bfdaa14
Diffstat (limited to 'ui/views')
29 files changed, 1149 insertions, 0 deletions
diff --git a/ui/views/EffectiveNavigation/app/build.gradle b/ui/views/EffectiveNavigation/app/build.gradle new file mode 100644 index 00000000..641e9989 --- /dev/null +++ b/ui/views/EffectiveNavigation/app/build.gradle @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2017 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. + */ + +apply plugin: 'com.android.application' + +ext { + supportLibraryVersion = '25.1.0' +} + +android { + compileSdkVersion 25 + buildToolsVersion '25.0.2' + + defaultConfig { + applicationId 'com.example.android.effectivenavigation' + minSdkVersion 9 + targetSdkVersion 25 + versionCode 2 + versionName '2.0' + testInstrumentationRunner 'android.support.test.runner.AndroidJUnitRunner' + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' + } + } + + configurations.all { + resolutionStrategy.force "com.android.support:support-annotations:$supportLibraryVersion" + } +} + +dependencies { + compile "com.android.support:design:$supportLibraryVersion" + androidTestCompile 'junit:junit:4.12' + androidTestCompile 'com.android.support.test:runner:0.5' + androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2' +} diff --git a/ui/views/EffectiveNavigation/app/src/androidTest/java/com/example/android/effectivenavigation/CollectionDemoActivityTest.java b/ui/views/EffectiveNavigation/app/src/androidTest/java/com/example/android/effectivenavigation/CollectionDemoActivityTest.java new file mode 100644 index 00000000..a0a1620a --- /dev/null +++ b/ui/views/EffectiveNavigation/app/src/androidTest/java/com/example/android/effectivenavigation/CollectionDemoActivityTest.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2017 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 static android.support.test.espresso.Espresso.onView; +import static android.support.test.espresso.action.ViewActions.click; +import static android.support.test.espresso.action.ViewActions.swipeLeft; +import static android.support.test.espresso.assertion.ViewAssertions.matches; +import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; +import static android.support.test.espresso.matcher.ViewMatchers.isSelected; +import static android.support.test.espresso.matcher.ViewMatchers.withId; +import static android.support.test.espresso.matcher.ViewMatchers.withText; + +import static org.hamcrest.Matchers.not; + +import android.support.test.rule.ActivityTestRule; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +public class CollectionDemoActivityTest { + + @Rule + public final ActivityTestRule<CollectionDemoActivity> rule = + new ActivityTestRule<>(CollectionDemoActivity.class); + + @Test + public void clickTabToChangeSection() { + onView(withText("2")).check(matches(not(isDisplayed()))); + onView(withText("Page 2")).perform(click()).check(matches(isSelected())); + onView(withText("2")).check(matches(isDisplayed())); + } + + @Test + public void swipeToChangeSection() { + onView(withText("1")).check(matches(isDisplayed())); + onView(withId(R.id.pager)).perform(swipeLeft()); + onView(withText("2")).check(matches(isDisplayed())); + onView(withText("Page 2")).check(matches(isSelected())); + } + +} diff --git a/ui/views/EffectiveNavigation/app/src/androidTest/java/com/example/android/effectivenavigation/MainActivityTest.java b/ui/views/EffectiveNavigation/app/src/androidTest/java/com/example/android/effectivenavigation/MainActivityTest.java new file mode 100644 index 00000000..b6f442c5 --- /dev/null +++ b/ui/views/EffectiveNavigation/app/src/androidTest/java/com/example/android/effectivenavigation/MainActivityTest.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2017 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 static android.support.test.espresso.Espresso.onView; +import static android.support.test.espresso.action.ViewActions.click; +import static android.support.test.espresso.action.ViewActions.swipeLeft; +import static android.support.test.espresso.assertion.ViewAssertions.matches; +import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; +import static android.support.test.espresso.matcher.ViewMatchers.isSelected; +import static android.support.test.espresso.matcher.ViewMatchers.withContentDescription; +import static android.support.test.espresso.matcher.ViewMatchers.withId; +import static android.support.test.espresso.matcher.ViewMatchers.withText; + +import static org.hamcrest.Matchers.not; + +import android.support.test.rule.ActivityTestRule; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +public class MainActivityTest { + + @Rule + public final ActivityTestRule<MainActivity> rule = new ActivityTestRule<>(MainActivity.class); + + @Test + public void checkPreconditions() { + onView(withId(R.id.toolbar)).check(matches(isDisplayed())); + onView(withId(R.id.pager)).check(matches(isDisplayed())); + onView(withId(R.id.tabs)).check(matches(isDisplayed())); + onView(withId(R.id.demo_collection_button)).check(matches(isDisplayed())); + onView(withId(R.id.demo_external_activity)).check(matches(isDisplayed())); + } + + @Test + public void clickTabToChangeSection() { + onView(withText("Section 2 is just a dummy section.")).check(matches(not(isDisplayed()))); + onView(withText("Section 2")).perform(click()).check(matches(isSelected())); + onView(withText("Section 2 is just a dummy section.")).check(matches(isDisplayed())); + } + + @Test + public void swipeToChangeSection() { + onView(withText("Section 2 is just a dummy section.")).check(matches(not(isDisplayed()))); + onView(withId(R.id.pager)).perform(swipeLeft()); + onView(withText("Section 2 is just a dummy section.")).check(matches(isDisplayed())); + onView(withText("Section 2")).check(matches(isSelected())); + } + + @Test + public void openAndCloseCollection() { + onView(withId(R.id.demo_collection_button)).perform(click()); + // We should be in CollectionDemoActivity now + onView(withText("Demo Collection")).check(matches(isDisplayed())); + onView(withContentDescription("Navigate up")).perform(click()); + // We should be back in MainActivity now + onView(withText("Effective Navigation")).check(matches(isDisplayed())); + } + +} diff --git a/ui/views/EffectiveNavigation/app/src/main/AndroidManifest.xml b/ui/views/EffectiveNavigation/app/src/main/AndroidManifest.xml new file mode 100644 index 00000000..5b8c9b24 --- /dev/null +++ b/ui/views/EffectiveNavigation/app/src/main/AndroidManifest.xml @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright 2017 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" + xmlns:tools="http://schemas.android.com/tools" + package="com.example.android.effectivenavigation"> + + <application + android:allowBackup="true" + android:icon="@mipmap/ic_launcher" + android:label="@string/app_name" + android:theme="@style/Theme.EffectiveNavigation" + tools:ignore="AllowBackup,GoogleAppIndexingWarning"> + + <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" + android:parentActivityName=".MainActivity" + tools:ignore="UnusedAttribute"> + <meta-data + android:name="android.support.PARENT_ACTIVITY" + android:value=".MainActivity"/> + </activity> + + </application> + +</manifest> diff --git a/ui/views/EffectiveNavigation/app/src/main/java/com/example/android/effectivenavigation/CollectionDemoActivity.java b/ui/views/EffectiveNavigation/app/src/main/java/com/example/android/effectivenavigation/CollectionDemoActivity.java new file mode 100644 index 00000000..3f5ebdc1 --- /dev/null +++ b/ui/views/EffectiveNavigation/app/src/main/java/com/example/android/effectivenavigation/CollectionDemoActivity.java @@ -0,0 +1,117 @@ +/* + * Copyright 2017 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.os.Bundle; +import android.support.design.widget.TabLayout; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentStatePagerAdapter; +import android.support.v4.view.ViewPager; +import android.support.v7.app.ActionBar; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.Toolbar; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import java.util.Locale; + +public class CollectionDemoActivity extends AppCompatActivity { + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_collection_demo); + + // Set up the app bar + final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); + setSupportActionBar(toolbar); + ActionBar actionBar = getSupportActionBar(); + if (actionBar != null) { + actionBar.setDisplayHomeAsUpEnabled(true); + } + + // 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. + final DemoCollectionPagerAdapter adapter = + new DemoCollectionPagerAdapter(getSupportFragmentManager()); + + // Set up the ViewPager, attaching the adapter. + final ViewPager viewPager = (ViewPager) findViewById(R.id.pager); + viewPager.setAdapter(adapter); + + final TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs); + tabLayout.setupWithViewPager(viewPager); + } + + /** + * 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. + */ + private static class DemoCollectionPagerAdapter extends FragmentStatePagerAdapter { + + 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 "Page " + (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( + String.format(Locale.US, "%d", args.getInt(ARG_OBJECT))); + return rootView; + } + } +} diff --git a/ui/views/EffectiveNavigation/app/src/main/java/com/example/android/effectivenavigation/MainActivity.java b/ui/views/EffectiveNavigation/app/src/main/java/com/example/android/effectivenavigation/MainActivity.java new file mode 100644 index 00000000..5efc2371 --- /dev/null +++ b/ui/views/EffectiveNavigation/app/src/main/java/com/example/android/effectivenavigation/MainActivity.java @@ -0,0 +1,177 @@ +/* + * Copyright 2017 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.content.Intent; +import android.os.Build; +import android.os.Bundle; +import android.support.design.widget.TabLayout; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentPagerAdapter; +import android.support.v4.view.ViewPager; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.Toolbar; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +public class MainActivity extends AppCompatActivity { + + /** + * An {@link Intent} flag to be used for launching an external activity. This ensures that + * relaunching the application from device home screen does not return to the external + * activity. We can use {@link Intent#FLAG_ACTIVITY_NEW_DOCUMENT} or + * {@link Intent#FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET} depending on the API level. + */ + private static final int INTENT_FLAG_ACTIVITY_NEW_DOCUMENT; + + static { + if (Build.VERSION.SDK_INT >= 21) { + INTENT_FLAG_ACTIVITY_NEW_DOCUMENT = Intent.FLAG_ACTIVITY_NEW_DOCUMENT; + } else { + //noinspection deprecation + INTENT_FLAG_ACTIVITY_NEW_DOCUMENT = Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET; + } + } + + 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. + AppSectionsPagerAdapter appSectionsPagerAdapter = new AppSectionsPagerAdapter( + getSupportFragmentManager()); + + // Set up the app bar. + final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); + setSupportActionBar(toolbar); + + // Set up the ViewPager, attaching the adapter and setting up a listener for when the + // user swipes between sections. + final ViewPager viewPager = (ViewPager) findViewById(R.id.pager); + viewPager.setAdapter(appSectionsPagerAdapter); + + // Set up the TabLayout, making it sync with the ViewPager. + final TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs); + tabLayout.setupWithViewPager(viewPager); + } + + /** + * A {@link FragmentPagerAdapter} that returns a fragment corresponding to one of the primary + * sections of the app. + */ + private static class AppSectionsPagerAdapter extends FragmentPagerAdapter { + + 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_NEW_DOCUMENT, 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_NEW_DOCUMENT); + 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; + } + + } + +} diff --git a/ui/views/EffectiveNavigation/app/src/main/res/layout/activity_collection_demo.xml b/ui/views/EffectiveNavigation/app/src/main/res/layout/activity_collection_demo.xml new file mode 100644 index 00000000..f84161ec --- /dev/null +++ b/ui/views/EffectiveNavigation/app/src/main/res/layout/activity_collection_demo.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright 2017 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.design.widget.CoordinatorLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + android:id="@+id/coordinator" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <android.support.design.widget.AppBarLayout + android:id="@+id/appbar" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:background="?attr/colorPrimary" + android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"> + + <android.support.v7.widget.Toolbar + android:id="@+id/toolbar" + android:layout_width="match_parent" + android:layout_height="?attr/actionBarSize" + app:layout_collapseMode="pin" + app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/> + + <android.support.design.widget.TabLayout + android:id="@+id/tabs" + android:layout_width="match_parent" + android:layout_height="wrap_content" + app:tabMode="scrollable"/> + + </android.support.design.widget.AppBarLayout> + + <android.support.v4.view.ViewPager + android:id="@+id/pager" + android:layout_width="match_parent" + android:layout_height="match_parent" + app:layout_behavior="@string/appbar_scrolling_view_behavior"/> + +</android.support.design.widget.CoordinatorLayout> diff --git a/ui/views/EffectiveNavigation/app/src/main/res/layout/activity_main.xml b/ui/views/EffectiveNavigation/app/src/main/res/layout/activity_main.xml new file mode 100644 index 00000000..6b3cefc5 --- /dev/null +++ b/ui/views/EffectiveNavigation/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright 2017 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.design.widget.CoordinatorLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + android:id="@+id/coordinator" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <android.support.design.widget.AppBarLayout + android:id="@+id/appbar" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:background="?attr/colorPrimary" + android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"> + + <android.support.v7.widget.Toolbar + android:id="@+id/toolbar" + android:layout_width="match_parent" + android:layout_height="?attr/actionBarSize" + app:layout_collapseMode="pin" + app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/> + + <android.support.design.widget.TabLayout + android:id="@+id/tabs" + android:layout_width="match_parent" + android:layout_height="wrap_content"/> + + </android.support.design.widget.AppBarLayout> + + <android.support.v4.view.ViewPager + android:id="@+id/pager" + android:layout_width="match_parent" + android:layout_height="match_parent" + app:layout_behavior="@string/appbar_scrolling_view_behavior"/> + +</android.support.design.widget.CoordinatorLayout> diff --git a/ui/views/EffectiveNavigation/app/src/main/res/layout/fragment_collection_object.xml b/ui/views/EffectiveNavigation/app/src/main/res/layout/fragment_collection_object.xml new file mode 100644 index 00000000..25946919 --- /dev/null +++ b/ui/views/EffectiveNavigation/app/src/main/res/layout/fragment_collection_object.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright 2017 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/ui/views/EffectiveNavigation/app/src/main/res/layout/fragment_section_dummy.xml b/ui/views/EffectiveNavigation/app/src/main/res/layout/fragment_section_dummy.xml new file mode 100644 index 00000000..0fa29dab --- /dev/null +++ b/ui/views/EffectiveNavigation/app/src/main/res/layout/fragment_section_dummy.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright 2017 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/ui/views/EffectiveNavigation/app/src/main/res/layout/fragment_section_launchpad.xml b/ui/views/EffectiveNavigation/app/src/main/res/layout/fragment_section_launchpad.xml new file mode 100644 index 00000000..b1fba9d0 --- /dev/null +++ b/ui/views/EffectiveNavigation/app/src/main/res/layout/fragment_section_launchpad.xml @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright 2017 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. +--> +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:gravity="center" + android:orientation="vertical"> + + <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="300dp" + android:layout_height="wrap_content" + android:text="@string/demo_external_activity"/> + +</LinearLayout> diff --git a/ui/views/EffectiveNavigation/app/src/main/res/mipmap-hdpi/ic_launcher.png b/ui/views/EffectiveNavigation/app/src/main/res/mipmap-hdpi/ic_launcher.png Binary files differnew file mode 100644 index 00000000..70577563 --- /dev/null +++ b/ui/views/EffectiveNavigation/app/src/main/res/mipmap-hdpi/ic_launcher.png diff --git a/ui/views/EffectiveNavigation/app/src/main/res/mipmap-mdpi/ic_launcher.png b/ui/views/EffectiveNavigation/app/src/main/res/mipmap-mdpi/ic_launcher.png Binary files differnew file mode 100644 index 00000000..108a8688 --- /dev/null +++ b/ui/views/EffectiveNavigation/app/src/main/res/mipmap-mdpi/ic_launcher.png diff --git a/ui/views/EffectiveNavigation/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/ui/views/EffectiveNavigation/app/src/main/res/mipmap-xhdpi/ic_launcher.png Binary files differnew file mode 100644 index 00000000..e02ddf36 --- /dev/null +++ b/ui/views/EffectiveNavigation/app/src/main/res/mipmap-xhdpi/ic_launcher.png diff --git a/ui/views/EffectiveNavigation/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/ui/views/EffectiveNavigation/app/src/main/res/mipmap-xxhdpi/ic_launcher.png Binary files differnew file mode 100644 index 00000000..b1c1f0b5 --- /dev/null +++ b/ui/views/EffectiveNavigation/app/src/main/res/mipmap-xxhdpi/ic_launcher.png diff --git a/ui/views/EffectiveNavigation/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/ui/views/EffectiveNavigation/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png Binary files differnew file mode 100644 index 00000000..3563d335 --- /dev/null +++ b/ui/views/EffectiveNavigation/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png diff --git a/ui/views/EffectiveNavigation/app/src/main/res/values/colors.xml b/ui/views/EffectiveNavigation/app/src/main/res/values/colors.xml new file mode 100644 index 00000000..c9b72ff2 --- /dev/null +++ b/ui/views/EffectiveNavigation/app/src/main/res/values/colors.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright 2017 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> + <color name="primary">#4CAF50</color> + <color name="primary_dark">#388E3C</color> + <color name="accent">#E040FB</color> +</resources> diff --git a/ui/views/EffectiveNavigation/app/src/main/res/values/strings.xml b/ui/views/EffectiveNavigation/app/src/main/res/values/strings.xml new file mode 100644 index 00000000..201deb76 --- /dev/null +++ b/ui/views/EffectiveNavigation/app/src/main/res/values/strings.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright 2017 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/ui/views/EffectiveNavigation/app/src/main/res/values/styles.xml b/ui/views/EffectiveNavigation/app/src/main/res/values/styles.xml new file mode 100644 index 00000000..42dcf178 --- /dev/null +++ b/ui/views/EffectiveNavigation/app/src/main/res/values/styles.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright 2017 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> + + <style name="Theme.EffectiveNavigation" parent="Theme.AppCompat.Light.NoActionBar"> + <item name="colorPrimary">@color/primary</item> + <item name="colorPrimaryDark">@color/primary_dark</item> + <item name="colorAccent">@color/accent</item> + </style> + +</resources> diff --git a/ui/views/EffectiveNavigation/build.gradle b/ui/views/EffectiveNavigation/build.gradle new file mode 100644 index 00000000..2e369803 --- /dev/null +++ b/ui/views/EffectiveNavigation/build.gradle @@ -0,0 +1,15 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:2.2.3' + } +} + +allprojects { + repositories { + jcenter() + } +} diff --git a/ui/views/EffectiveNavigation/gradle/wrapper/gradle-wrapper.jar b/ui/views/EffectiveNavigation/gradle/wrapper/gradle-wrapper.jar Binary files differnew file mode 100644 index 00000000..13372aef --- /dev/null +++ b/ui/views/EffectiveNavigation/gradle/wrapper/gradle-wrapper.jar diff --git a/ui/views/EffectiveNavigation/gradle/wrapper/gradle-wrapper.properties b/ui/views/EffectiveNavigation/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..04e285f3 --- /dev/null +++ b/ui/views/EffectiveNavigation/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Mon Dec 28 10:00:20 PST 2015 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip diff --git a/ui/views/EffectiveNavigation/gradlew b/ui/views/EffectiveNavigation/gradlew new file mode 100755 index 00000000..9d82f789 --- /dev/null +++ b/ui/views/EffectiveNavigation/gradlew @@ -0,0 +1,160 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/ui/views/EffectiveNavigation/gradlew.bat b/ui/views/EffectiveNavigation/gradlew.bat new file mode 100644 index 00000000..aec99730 --- /dev/null +++ b/ui/views/EffectiveNavigation/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/ui/views/EffectiveNavigation/screenshots/1-main.png b/ui/views/EffectiveNavigation/screenshots/1-main.png Binary files differnew file mode 100644 index 00000000..94647bdd --- /dev/null +++ b/ui/views/EffectiveNavigation/screenshots/1-main.png diff --git a/ui/views/EffectiveNavigation/screenshots/2-collection.png b/ui/views/EffectiveNavigation/screenshots/2-collection.png Binary files differnew file mode 100644 index 00000000..61c93e4c --- /dev/null +++ b/ui/views/EffectiveNavigation/screenshots/2-collection.png diff --git a/ui/views/EffectiveNavigation/screenshots/icon-web.png b/ui/views/EffectiveNavigation/screenshots/icon-web.png Binary files differnew file mode 100644 index 00000000..bfc21f08 --- /dev/null +++ b/ui/views/EffectiveNavigation/screenshots/icon-web.png diff --git a/ui/views/EffectiveNavigation/settings.gradle b/ui/views/EffectiveNavigation/settings.gradle new file mode 100644 index 00000000..e7b4def4 --- /dev/null +++ b/ui/views/EffectiveNavigation/settings.gradle @@ -0,0 +1 @@ +include ':app' diff --git a/ui/views/EffectiveNavigation/template-params.xml b/ui/views/EffectiveNavigation/template-params.xml new file mode 100644 index 00000000..3c87a17f --- /dev/null +++ b/ui/views/EffectiveNavigation/template-params.xml @@ -0,0 +1,88 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Copyright 2017 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. +--> +<sample> + <name>EffectiveNavigation</name> + <group>UI</group> + <package>com.example.android.effectivenavigation</package> + + <!-- change minSdk if needed--> + <minSdk>9</minSdk> + + <strings> + <intro> + <![CDATA[ +This sample demonstrates how to create swipe views with tabs. Users can swipe +between tabs, or click on a tab title to jump to the section. Some tabs are +scrollable, meaning that users can scroll horizontally through the tab strip and +select a tab. +]]> + </intro> + <sample_action>Effective Navigation</sample_action> + </strings> + + <metadata> + <status>PUBLISHED</status> + <categories>UI</categories> + <technologies>Android</technologies> + <languages>Java</languages> + <solutions>Mobile</solutions> + <level>BEGINNER</level> + <icon>screenshots/icon-web.png</icon> + <screenshots> + <img>screenshots/1-main.png</img> + <img>screenshots/2-collection.png</img> + </screenshots> + <api_refs> + <android>android.support.v4.view.ViewPager</android> + <android>android.support.design.widget.TabLayout</android> + <android>android.support.v4.app.NavUtils</android> + </api_refs> + <description> + <![CDATA[ +This sample demonstrates how to create swipe views with tabs. Users can swipe +between tabs, or click on a tab title to jump to the section. Some tabs are +scrollable, meaning that users can scroll horizontally through the tab strip and +select a tab. +]]> + </description> + <intro> + <![CDATA[ +This sample use combination of [ViewPager][1] and [TabLayout][2] to create swipe +views with tabs. + +In order to use ViewPager, you first need to implement a PagerAdapter to feed +its content. In this sample, we use [FragmentPagerAdapter][3] and +[FragmentStatePagerAdapter][4]. FragmentPagerAdapter is useful when you have a +limited number of fixed pages. FragmentStatePagerAdapter can be used for +ViewPager with a lot of pages as it can save and restore state of Fragments +inside of it in a memory-efficient way. + +Using TabLayout with ViewPager is simple. Just call the method +[setupWithViewPager(ViewPager)][5], and the TabLayout generates corresponding +tabs for the ViewPager. The titles are populated from [getPageTitle(int)][6] +method of your ViewPager adapter. + +[1]: https://developer.android.com/reference/android/support/v4/view/ViewPager.html +[2]: https://developer.android.com/reference/android/support/design/widget/TabLayout.html +[3]: https://developer.android.com/reference/android/support/v4/app/FragmentPagerAdapter.html +[4]: https://developer.android.com/reference/android/support/v4/app/FragmentStatePagerAdapter.html +[5]: https://developer.android.com/reference/android/support/design/widget/TabLayout.html#setupWithViewPager(android.support.v4.view.ViewPager) +[6]: https://developer.android.com/reference/android/support/v4/view/PagerAdapter.html#getPageTitle(int) +]]> + </intro> + </metadata> +</sample> |