diff --git a/catalog/java/io/material/catalog/carousel/CarouselDemoUtils.java b/catalog/java/io/material/catalog/carousel/CarouselDemoUtils.java new file mode 100644 index 000000000..3b6e44f6d --- /dev/null +++ b/catalog/java/io/material/catalog/carousel/CarouselDemoUtils.java @@ -0,0 +1,64 @@ +/* + * 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 androidx.recyclerview.widget.RecyclerView; +import androidx.annotation.NonNull; +import com.google.android.material.slider.Slider; +import com.google.android.material.slider.Slider.OnSliderTouchListener; + +/** Utilities for setting up carousel catalog demos. */ +class CarouselDemoUtils { + + private CarouselDemoUtils() {} + + static RecyclerView.OnScrollListener createUpdateSliderOnScrollListener( + Slider slider, CarouselAdapter adapter) { + return new RecyclerView.OnScrollListener() { + private boolean dragged = false; + + @Override + public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) { + if (newState == RecyclerView.SCROLL_STATE_DRAGGING) { + dragged = true; + } else if (dragged && newState == RecyclerView.SCROLL_STATE_IDLE) { + if (recyclerView.computeHorizontalScrollRange() != 0) { + slider.setValue( + (adapter.getItemCount() - 1) + * Math.abs(recyclerView.computeHorizontalScrollOffset()) + / recyclerView.computeHorizontalScrollRange() + + 1); + } + dragged = false; + } + } + }; + } + + static OnSliderTouchListener createScrollToPositionSliderTouchListener( + RecyclerView recyclerView) { + return new OnSliderTouchListener() { + @Override + public void onStartTrackingTouch(@NonNull Slider slider) {} + + @Override + public void onStopTrackingTouch(@NonNull Slider slider) { + recyclerView.smoothScrollToPosition(((int) slider.getValue()) - 1); + } + }; + } +} diff --git a/catalog/java/io/material/catalog/carousel/HeroCarouselDemoFragment.java b/catalog/java/io/material/catalog/carousel/HeroCarouselDemoFragment.java index f4c55eee6..eafedaafc 100644 --- a/catalog/java/io/material/catalog/carousel/HeroCarouselDemoFragment.java +++ b/catalog/java/io/material/catalog/carousel/HeroCarouselDemoFragment.java @@ -37,7 +37,6 @@ 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. */ @@ -73,8 +72,7 @@ public class HeroCarouselDemoFragment extends DemoFragment { RadioButton centerAlignButton = view.findViewById(R.id.center_align); // A hero carousel - RecyclerView heroStartRecyclerView = - view.findViewById(R.id.hero_start_carousel_recycler_view); + RecyclerView heroStartRecyclerView = view.findViewById(R.id.hero_start_carousel_recycler_view); CarouselLayoutManager heroStartCarouselLayoutManager = new CarouselLayoutManager(new HeroCarouselStrategy()); heroStartCarouselLayoutManager.setDebuggingEnabled( @@ -86,8 +84,7 @@ public class HeroCarouselDemoFragment extends DemoFragment { (buttonView, isChecked) -> { heroStartRecyclerView.setBackgroundResource( isChecked ? R.drawable.dashed_outline_rectangle : 0); - heroStartCarouselLayoutManager.setDebuggingEnabled( - heroStartRecyclerView, isChecked); + heroStartCarouselLayoutManager.setDebuggingEnabled(heroStartRecyclerView, isChecked); }); drawDividers.setOnCheckedChangeListener( @@ -107,25 +104,7 @@ public class HeroCarouselDemoFragment extends DemoFragment { }, R.layout.cat_carousel_item); heroStartRecyclerView.addOnScrollListener( - new RecyclerView.OnScrollListener() { - private boolean dragged = false; - - @Override - public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) { - if (newState == RecyclerView.SCROLL_STATE_DRAGGING) { - dragged = true; - } else if (dragged && newState == RecyclerView.SCROLL_STATE_IDLE) { - if (recyclerView.computeHorizontalScrollRange() != 0) { - positionSlider.setValue( - (adapter.getItemCount() - 1) - * recyclerView.computeHorizontalScrollOffset() - / recyclerView.computeHorizontalScrollRange() - + 1); - } - dragged = false; - } - } - }); + CarouselDemoUtils.createUpdateSliderOnScrollListener(positionSlider, adapter)); SnapHelper disableFlingSnapHelper = new CarouselSnapHelper(); SnapHelper enableFlingSnapHelper = new CarouselSnapHelper(false); @@ -154,15 +133,7 @@ public class HeroCarouselDemoFragment extends DemoFragment { 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); - } - }); + CarouselDemoUtils.createScrollToPositionSliderTouchListener(heroStartRecyclerView)); startAlignButton.setOnClickListener( v -> heroStartCarouselLayoutManager.setCarouselAlignment(ALIGNMENT_START)); diff --git a/catalog/java/io/material/catalog/carousel/MultiBrowseCarouselDemoFragment.java b/catalog/java/io/material/catalog/carousel/MultiBrowseCarouselDemoFragment.java index 4b9375abf..b6192abcf 100644 --- a/catalog/java/io/material/catalog/carousel/MultiBrowseCarouselDemoFragment.java +++ b/catalog/java/io/material/catalog/carousel/MultiBrowseCarouselDemoFragment.java @@ -32,7 +32,6 @@ import com.google.android.material.carousel.MultiBrowseCarouselStrategy; 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 multi-browse variants of the Carousel. */ @@ -115,25 +114,7 @@ public class MultiBrowseCarouselDemoFragment extends DemoFragment { }, R.layout.cat_carousel_item_narrow); multiBrowseStartRecyclerView.addOnScrollListener( - new RecyclerView.OnScrollListener() { - private boolean dragged = false; - - @Override - public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) { - if (newState == RecyclerView.SCROLL_STATE_DRAGGING) { - dragged = true; - } else if (dragged && newState == RecyclerView.SCROLL_STATE_IDLE) { - if (recyclerView.computeHorizontalScrollRange() != 0) { - positionSlider.setValue( - (adapter.getItemCount() - 1) - * recyclerView.computeHorizontalScrollOffset() - / recyclerView.computeHorizontalScrollRange() - + 1); - } - dragged = false; - } - } - }); + CarouselDemoUtils.createUpdateSliderOnScrollListener(positionSlider, adapter)); itemCountDropdown.setOnItemClickListener( (parent, view1, position, id) -> { @@ -143,15 +124,7 @@ public class MultiBrowseCarouselDemoFragment extends DemoFragment { }); positionSlider.addOnSliderTouchListener( - new OnSliderTouchListener() { - @Override - public void onStartTrackingTouch(@NonNull Slider slider) {} - - @Override - public void onStopTrackingTouch(@NonNull Slider slider) { - multiBrowseStartRecyclerView.smoothScrollToPosition(((int) slider.getValue()) - 1); - } - }); + CarouselDemoUtils.createScrollToPositionSliderTouchListener(multiBrowseStartRecyclerView)); multiBrowseStartRecyclerView.setAdapter(adapter); adapter.submitList(CarouselData.createItems(), updateSliderRange(positionSlider, adapter)); diff --git a/catalog/java/io/material/catalog/carousel/UncontainedCarouselDemoFragment.java b/catalog/java/io/material/catalog/carousel/UncontainedCarouselDemoFragment.java index 7883a021d..d1093d301 100644 --- a/catalog/java/io/material/catalog/carousel/UncontainedCarouselDemoFragment.java +++ b/catalog/java/io/material/catalog/carousel/UncontainedCarouselDemoFragment.java @@ -32,7 +32,6 @@ import com.google.android.material.carousel.UncontainedCarouselStrategy; 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 uncontained variant of the Carousel. */ @@ -78,8 +77,7 @@ public class UncontainedCarouselDemoFragment extends DemoFragment { (buttonView, isChecked) -> { uncontainedRecyclerView.setBackgroundResource( isChecked ? R.drawable.dashed_outline_rectangle : 0); - uncontainedCarouselLayoutManager.setDebuggingEnabled( - uncontainedRecyclerView, isChecked); + uncontainedCarouselLayoutManager.setDebuggingEnabled(uncontainedRecyclerView, isChecked); }); drawDividers.setOnCheckedChangeListener( @@ -109,25 +107,7 @@ public class UncontainedCarouselDemoFragment extends DemoFragment { }, R.layout.cat_carousel_item_narrow); uncontainedRecyclerView.addOnScrollListener( - new RecyclerView.OnScrollListener() { - private boolean dragged = false; - - @Override - public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) { - if (newState == RecyclerView.SCROLL_STATE_DRAGGING) { - dragged = true; - } else if (dragged && newState == RecyclerView.SCROLL_STATE_IDLE) { - if (recyclerView.computeHorizontalScrollRange() != 0) { - positionSlider.setValue( - (adapter.getItemCount() - 1) - * recyclerView.computeHorizontalScrollOffset() - / recyclerView.computeHorizontalScrollRange() - + 1); - } - dragged = false; - } - } - }); + CarouselDemoUtils.createUpdateSliderOnScrollListener(positionSlider, adapter)); itemCountDropdown.setOnItemClickListener( (parent, view1, position, id) -> @@ -136,15 +116,7 @@ public class UncontainedCarouselDemoFragment extends DemoFragment { updateSliderRange(positionSlider, adapter))); positionSlider.addOnSliderTouchListener( - new OnSliderTouchListener() { - @Override - public void onStartTrackingTouch(@NonNull Slider slider) {} - - @Override - public void onStopTrackingTouch(@NonNull Slider slider) { - uncontainedRecyclerView.smoothScrollToPosition(((int) slider.getValue()) - 1); - } - }); + CarouselDemoUtils.createScrollToPositionSliderTouchListener(uncontainedRecyclerView)); uncontainedRecyclerView.setAdapter(adapter); adapter.submitList(CarouselData.createItems(), updateSliderRange(positionSlider, adapter));