Skip to content

Commit

Permalink
[Carousel] Add Carousel Hero strategy demo
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 531612383
  • Loading branch information
imhappi committed May 15, 2023
1 parent 52a20a8 commit b57dae5
Show file tree
Hide file tree
Showing 5 changed files with 288 additions and 2 deletions.
Expand Up @@ -64,7 +64,13 @@ public List<Demo> getAdditionalDemos() {
new Demo(R.string.cat_carousel_multi_browse_demo_title) {
@Override
public Fragment createFragment() {
return new MultiBrowseDemoFragment();
return new MultiBrowseCarouselDemoFragment();
}
},
new Demo(R.string.cat_carousel_hero_demo_title) {
@Override
public Fragment createFragment() {
return new HeroCarouselDemoFragment();
}
},
new Demo(R.string.cat_carousel_default_list_demo_title) {
Expand Down
@@ -0,0 +1,155 @@
/*
* Copyright 2023 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
*
* https://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 io.material.catalog.carousel;

import io.material.catalog.R;

import android.os.Bundle;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.SnapHelper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AutoCompleteTextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.material.carousel.CarouselLayoutManager;
import com.google.android.material.carousel.CarouselSnapHelper;
import com.google.android.material.carousel.HeroCarouselStrategy;
import com.google.android.material.divider.MaterialDividerItemDecoration;
import com.google.android.material.materialswitch.MaterialSwitch;
import com.google.android.material.slider.Slider;
import com.google.android.material.slider.Slider.OnSliderTouchListener;
import io.material.catalog.feature.DemoFragment;

/** A fragment that displays the hero variant of the Carousel. */
public class HeroCarouselDemoFragment extends DemoFragment {

private MaterialDividerItemDecoration horizontalDivider;

@NonNull
@Override
public View onCreateDemoView(
@NonNull LayoutInflater layoutInflater,
@Nullable ViewGroup viewGroup,
@Nullable Bundle bundle) {
return layoutInflater.inflate(
R.layout.cat_carousel_hero_fragment, viewGroup, false /* attachToRoot */);
}

@Override
@SuppressWarnings("RestrictTo")
public void onViewCreated(@NonNull View view, @Nullable Bundle bundle) {
super.onViewCreated(view, bundle);

horizontalDivider =
new MaterialDividerItemDecoration(
requireContext(), MaterialDividerItemDecoration.HORIZONTAL);

MaterialSwitch debugSwitch = view.findViewById(R.id.debug_switch);
MaterialSwitch drawDividers = view.findViewById(R.id.draw_dividers_switch);
MaterialSwitch enableFlingSwitch = view.findViewById(R.id.enable_fling_switch);
AutoCompleteTextView itemCountDropdown = view.findViewById(R.id.item_count_dropdown);
Slider positionSlider = view.findViewById(R.id.position_slider);

// A start-aligned hero carousel
RecyclerView heroStartRecyclerView =
view.findViewById(R.id.hero_start_carousel_recycler_view);
CarouselLayoutManager heroStartCarouselLayoutManager =
new CarouselLayoutManager(new HeroCarouselStrategy());
heroStartCarouselLayoutManager.setDebuggingEnabled(
heroStartRecyclerView, debugSwitch.isChecked());
heroStartRecyclerView.setLayoutManager(heroStartCarouselLayoutManager);
heroStartRecyclerView.setNestedScrollingEnabled(false);

debugSwitch.setOnCheckedChangeListener(
(buttonView, isChecked) -> {
heroStartRecyclerView.setBackgroundResource(
isChecked ? R.drawable.dashed_outline_rectangle : 0);
heroStartCarouselLayoutManager.setDebuggingEnabled(
heroStartRecyclerView, isChecked);
});

drawDividers.setOnCheckedChangeListener(
(buttonView, isChecked) -> {
if (isChecked) {
heroStartRecyclerView.addItemDecoration(horizontalDivider);
} else {
heroStartRecyclerView.removeItemDecoration(horizontalDivider);
}
});

CarouselAdapter adapter =
new CarouselAdapter(
(item, position) -> heroStartRecyclerView.scrollToPosition(position),
R.layout.cat_carousel_item);

SnapHelper disableFlingSnapHelper = new CarouselSnapHelper();
SnapHelper enableFlingSnapHelper = new CarouselSnapHelper(false);

if (enableFlingSwitch.isChecked()) {
enableFlingSnapHelper.attachToRecyclerView(heroStartRecyclerView);
} else {
disableFlingSnapHelper.attachToRecyclerView(heroStartRecyclerView);
}

enableFlingSwitch.setOnCheckedChangeListener(
(buttonView, isChecked) -> {
if (isChecked) {
disableFlingSnapHelper.attachToRecyclerView(null);
enableFlingSnapHelper.attachToRecyclerView(heroStartRecyclerView);
} else {
enableFlingSnapHelper.attachToRecyclerView(null);
disableFlingSnapHelper.attachToRecyclerView(heroStartRecyclerView);
}
});

itemCountDropdown.setOnItemClickListener(
(parent, view1, position, id) ->
adapter.submitList(
CarouselData.createItems().subList(0, position),
updateSliderRange(positionSlider, adapter)));

positionSlider.addOnSliderTouchListener(
new OnSliderTouchListener() {
@Override
public void onStartTrackingTouch(@NonNull Slider slider) {}

@Override
public void onStopTrackingTouch(@NonNull Slider slider) {
heroStartRecyclerView.smoothScrollToPosition((int) slider.getValue() - 1);
}
});

heroStartRecyclerView.setAdapter(adapter);
adapter.submitList(CarouselData.createItems(), updateSliderRange(positionSlider, adapter));
}

private static Runnable updateSliderRange(Slider slider, CarouselAdapter adapter) {
return () -> {
if (adapter.getItemCount() <= 1) {
slider.setEnabled(false);
return;
}

slider.setValueFrom(1);
slider.setValue(1);
slider.setValueTo(adapter.getItemCount());
slider.setEnabled(true);
};
}
}
Expand Up @@ -36,7 +36,7 @@
import io.material.catalog.feature.DemoFragment;

/** A fragment that displays the multi-browse variants of the Carousel. */
public class MultiBrowseDemoFragment extends DemoFragment {
public class MultiBrowseCarouselDemoFragment extends DemoFragment {

private MaterialDividerItemDecoration horizontalDivider;

Expand Down
@@ -0,0 +1,119 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2023 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
https://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.
-->
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/container"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:orientation="vertical">

<TextView
android:id="@+id/hero_title_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginVertical="4dp"
android:text="@string/cat_carousel_hero_title"
android:textAppearance="?attr/textAppearanceTitleMedium" />

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginVertical="4dp"
android:text="@string/cat_carousel_hero_desc"
android:textAppearance="?attr/textAppearanceBodyMedium" />

<com.google.android.material.materialswitch.MaterialSwitch
android:id="@+id/debug_switch"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:checked="false"
android:layout_marginHorizontal="16dp"
android:layout_marginVertical="8dp"
android:textAppearance="?attr/textAppearanceBodyLarge"
android:text="@string/cat_carousel_debug_mode_label"/>

<com.google.android.material.materialswitch.MaterialSwitch
android:id="@+id/draw_dividers_switch"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:checked="false"
android:layout_marginHorizontal="16dp"
android:layout_marginVertical="8dp"
android:textAppearance="?attr/textAppearanceBodyLarge"
android:text="@string/cat_carousel_draw_dividers_label"/>

<com.google.android.material.materialswitch.MaterialSwitch
android:id="@+id/enable_fling_switch"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:checked="false"
android:layout_marginHorizontal="16dp"
android:layout_marginVertical="8dp"
android:textAppearance="?attr/textAppearanceBodyLarge"
android:text="@string/cat_carousel_enable_fling_label"/>

<com.google.android.material.textfield.TextInputLayout
style="?attr/textInputFilledExposedDropdownMenuStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginHorizontal="16dp"
android:layout_marginVertical="8dp"
app:helperTextEnabled="false">

<AutoCompleteTextView
android:id="@+id/item_count_dropdown"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="none"
android:hint="@string/cat_carousel_adapter_item_count_hint_label"
app:simpleItems="@array/cat_carousel_adapter_count_content"/>

</com.google.android.material.textfield.TextInputLayout>

<TextView
android:id="@+id/position_slider_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="16dp"
android:labelFor="@id/position_slider"
android:text="@string/cat_carousel_position_slider_label"
android:textAppearance="?attr/textAppearanceBodyLarge"/>

<com.google.android.material.slider.Slider
android:id="@+id/position_slider"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginBottom="8dp"
android:contentDescription="@string/cat_carousel_position_slider_content_description"
android:stepSize="1.0"/>

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/hero_start_carousel_recycler_view"
android:layout_width="match_parent"
android:layout_height="196dp"
android:layout_marginHorizontal="16dp"
android:layout_marginVertical="16dp"
android:clipChildren="false"
android:clipToPadding="false" />

</LinearLayout>
</androidx.core.widget.NestedScrollView>
Expand Up @@ -20,6 +20,8 @@
<string name="cat_carousel_force_compact_arrangement_label" translatable="false">Force compact arrangement</string>
<string name="cat_carousel_draw_dividers_label" translatable="false">Draw dividers</string>
<string name="cat_carousel_enable_snap_label" description="The title of a switch to enable snapping to carousel items.[CHAR_LIMIT=NONE]">Enable Snap</string>
<string name="cat_carousel_enable_fling_label" description="The title of a switch to enable the flinging gesture.[CHAR_LIMIT=NONE]">Enable fling</string>

<string name="cat_carousel_adapter_item_count_hint_label" translatable="false">Item count</string>
<string name="cat_carousel_position_slider_label" translatable="false">Scroll position</string>
<string name="cat_carousel_snap_switch_description" description="Content description of a switch to enable snapping.[CHAR_LIMIT=NONE]">Enable snapping to carousel items</string>
Expand All @@ -44,11 +46,15 @@
<string name="cat_carousel_description" translatable="false">Carousels are stylized versions of lists that provide a unique viewing and behavior that suit large imagery and other visually rich content.</string>

<string name="cat_carousel_multi_browse_demo_title" translatable="false">Multi-browse Carousel</string>
<string name="cat_carousel_hero_demo_title" description="Name of the hero variant demo. [CHAR_LIMIT=NONE]">Hero Carousel</string>
<string name="cat_carousel_default_list_demo_title" translatable="false">Default List</string>

<string name="cat_carousel_multi_browse_title" translatable="false">Multi-browse</string>
<string name="cat_carousel_multi_browse_desc" translatable="false">Multi-browse carousels allow quick browsing of many small items, like a photo thumbnail gallery.</string>

<string name="cat_carousel_hero_title" description="Title of the hero variant demo. [CHAR_LIMIT=NONE]">Hero</string>
<string name="cat_carousel_hero_desc" description="Description of the hero variant demo.[CHAR_LIMIT=NONE]">Hero carousels allow browsing with a focus on one main item at a time.</string>

<string name="cat_carousel_default_title" translatable="false">Default</string>
<string name="cat_carousel_default_desc" translatable="false">A default horizontal list.</string>

Expand Down

0 comments on commit b57dae5

Please sign in to comment.