Skip to content

Commit b3e2d2f

Browse files
committed
Added SectionIndicator for viewing section while fast scrolling
1 parent 8b47f10 commit b3e2d2f

30 files changed

+871
-186
lines changed

Application/src/main/java/com/example/recyclerviewfastscroller/MainActivity.java

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,14 @@
2525
import android.view.MenuItem;
2626

2727
import com.example.android.recyclerview.R;
28-
import com.example.recyclerviewfastscroller.fragment.RecyclerViewFragment;
29-
import com.example.recyclerviewfastscroller.fragment.RecyclerViewWithSectionsFragment;
28+
import com.example.recyclerviewfastscroller.fragment.RecyclerViewWithFastScrollerFragment;
29+
import com.example.recyclerviewfastscroller.fragment.RecyclerViewWithSectionIndicatorFragment;
30+
import com.example.recyclerviewfastscroller.ui.scroller.sectionindicator.title.SectionTitleIndicator;
31+
import com.example.recyclerviewfastscroller.ui.scroller.vertical.VerticalRecyclerViewFastScroller;
3032

3133
/**
32-
* Simple activity for displaying the {@link RecyclerViewFragment}
34+
* Simple activity for displaying an example of the {@link VerticalRecyclerViewFastScroller} as well as
35+
* {@link SectionTitleIndicator} usage paired with the fast scroller
3336
*/
3437
public class MainActivity extends FragmentActivity {
3538

@@ -39,7 +42,7 @@ protected void onCreate(Bundle savedInstanceState) {
3942
setContentView(R.layout.activity_main);
4043

4144
if (savedInstanceState == null) {
42-
RecyclerViewFragment fragment = new RecyclerViewFragment();
45+
RecyclerViewWithFastScrollerFragment fragment = new RecyclerViewWithFastScrollerFragment();
4346
replaceCurrentFragment(fragment);
4447
}
4548
}
@@ -61,11 +64,16 @@ public boolean onCreateOptionsMenu(Menu menu) {
6164
public boolean onOptionsItemSelected(MenuItem item) {
6265
// Handle item selection
6366
switch (item.getItemId()) {
67+
case R.id.menu_item_list_no_section_indicator:
68+
RecyclerViewWithFastScrollerFragment simpleFastScrollerFragment = new RecyclerViewWithFastScrollerFragment();
69+
replaceCurrentFragment(simpleFastScrollerFragment);
70+
return true;
6471
case R.id.menu_item_list_with_sections:
65-
RecyclerViewWithSectionsFragment sectionsFragment = new RecyclerViewWithSectionsFragment();
72+
RecyclerViewWithSectionIndicatorFragment sectionsFragment = new RecyclerViewWithSectionIndicatorFragment();
6673
replaceCurrentFragment(sectionsFragment);
6774
return true;
6875
default:
6976
return super.onOptionsItemSelected(item);
7077
}
71-
}}
78+
}
79+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package com.example.recyclerviewfastscroller.data;
2+
3+
import android.support.annotation.NonNull;
4+
5+
/**
6+
* Data object representing a color
7+
*/
8+
public class ColorData {
9+
10+
private final int mColorInt;
11+
private final ColorGroup mColorGroup;
12+
13+
public ColorData(int colorInt, @NonNull ColorGroup colorGroup) {
14+
mColorInt = colorInt;
15+
mColorGroup = colorGroup;
16+
}
17+
18+
public int getIntValue() {
19+
return mColorInt;
20+
}
21+
22+
public ColorGroup getColorGroup() {
23+
return mColorGroup;
24+
}
25+
26+
@Override
27+
public String toString() {
28+
return String.format("#%06X", (0xFFFFFF & mColorInt));
29+
}
30+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package com.example.recyclerviewfastscroller.data;
2+
3+
import android.graphics.Color;
4+
5+
/**
6+
* Dummy dataset of N {@link ColorData} objects
7+
*/
8+
public class ColorDataSet {
9+
10+
private static final int DATA_SET_SIZE = 100;
11+
private static final float NUM_HUES = 359;
12+
private static final ColorData[] mColors = new ColorData[DATA_SET_SIZE];
13+
14+
public ColorDataSet() {
15+
this(new ColorGroupCalculator());
16+
}
17+
18+
private ColorDataSet(ColorGroupCalculator colorGroupCalculator) {
19+
for (int i = 0; i < mColors.length; i++) {
20+
mColors[i] = generateNewColor(i, mColors.length, colorGroupCalculator);
21+
}
22+
}
23+
24+
private ColorData generateNewColor(int position, int numColors, ColorGroupCalculator colorGroupCalculator) {
25+
float positionBasedHue = position * (NUM_HUES / numColors);
26+
int color = Color.HSVToColor(new float[] {positionBasedHue, 1, 1});
27+
return new ColorData(color, colorGroupCalculator.getColorGroup(positionBasedHue));
28+
}
29+
30+
public int getSize() {
31+
return mColors.length;
32+
}
33+
34+
public ColorData get(int position) {
35+
return mColors[position];
36+
}
37+
38+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package com.example.recyclerviewfastscroller.data;
2+
3+
import android.graphics.Color;
4+
5+
/**
6+
* Coarse groupings of colors by hue
7+
*/
8+
public enum ColorGroup {
9+
RED_UPPER (345, 360, "Red"),
10+
PINK (300, RED_UPPER.mMinimumHue, "Pink"),
11+
PURPLE (260, PINK.mMinimumHue, "Purple"),
12+
BLUE (175, PURPLE.mMinimumHue, "Blue"),
13+
GREEN (70, BLUE.mMinimumHue, "Green"),
14+
YELLOW (50, GREEN.mMinimumHue, "Yellow"),
15+
ORANGE (25, YELLOW.mMinimumHue, "Orange"),
16+
RED_LOWER (0, ORANGE.mMinimumHue, "Red"),
17+
;
18+
19+
private final int mMinimumHue, mMaximumHue;
20+
private final int mIntegerRepresentation;
21+
private final String mName;
22+
23+
ColorGroup(int minimumHue, int maximumHue, String groupName) {
24+
mMinimumHue = minimumHue;
25+
mMaximumHue = maximumHue;
26+
mName = groupName;
27+
mIntegerRepresentation = Color.HSVToColor(new float[] { (maximumHue + minimumHue) / 2, 1, 1});
28+
}
29+
30+
public String getName() {
31+
return mName;
32+
}
33+
34+
public boolean containsHue(int hue) {
35+
return (hue >= mMinimumHue && hue < mMaximumHue);
36+
}
37+
38+
public int getAsColor() {
39+
return mIntegerRepresentation;
40+
}
41+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.example.recyclerviewfastscroller.data;
2+
3+
import android.support.annotation.NonNull;
4+
5+
/**
6+
* Allow for finding a color group based on a hue
7+
*/
8+
class ColorGroupCalculator {
9+
10+
@NonNull
11+
public ColorGroup getColorGroup(float hue) {
12+
for (ColorGroup group : ColorGroup.values()) {
13+
if (group.containsHue((int) hue)) {
14+
return group;
15+
}
16+
}
17+
18+
throw new NullPointerException("Could not classify hue into Color Group!");
19+
}
20+
}

Application/src/main/java/com/example/recyclerviewfastscroller/fragment/RecyclerViewFragment.java renamed to Application/src/main/java/com/example/recyclerviewfastscroller/fragment/RecyclerViewWithFastScrollerFragment.java

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,14 @@
2525
import android.view.ViewGroup;
2626

2727
import com.example.android.recyclerview.R;
28+
import com.example.recyclerviewfastscroller.data.ColorDataSet;
2829
import com.example.recyclerviewfastscroller.recyclerview.ColorfulAdapter;
2930
import com.example.recyclerviewfastscroller.ui.scroller.vertical.VerticalRecyclerViewFastScroller;
3031

3132
/**
3233
* Adapted from sample code that demonstrates the use of {@link RecyclerView} with a {@link LinearLayoutManager}
3334
*/
34-
public class RecyclerViewFragment extends Fragment {
35-
36-
private static final String TAG = "RecyclerViewFragment";
37-
private static final int DATASET_COUNT = 100;
35+
public class RecyclerViewWithFastScrollerFragment extends Fragment {
3836

3937
@Override
4038
public void onCreate(Bundle savedInstanceState) {
@@ -44,16 +42,16 @@ public void onCreate(Bundle savedInstanceState) {
4442
@Override
4543
public View onCreateView(LayoutInflater inflater, ViewGroup container,
4644
Bundle savedInstanceState) {
47-
View rootView = inflater.inflate(R.layout.recycler_view_frag, container, false);
45+
View rootView = inflater.inflate(R.layout.recycler_view_with_fast_scroller_fragment, container, false);
4846

49-
RecyclerView recyclerView = (RecyclerView) rootView.findViewById(R.id.recyclerView);
47+
RecyclerView recyclerView = (RecyclerView) rootView.findViewById(R.id.recycler_view);
5048
VerticalRecyclerViewFastScroller fastScroller = (VerticalRecyclerViewFastScroller) rootView.findViewById(R.id.fast_scroller);
5149
fastScroller.setRecyclerView(recyclerView);
5250
recyclerView.setOnScrollListener(fastScroller.getOnScrollListener());
5351

5452
setRecyclerViewLayoutManager(recyclerView);
5553

56-
RecyclerView.Adapter adapter = new ColorfulAdapter(getDummyDataSet());
54+
RecyclerView.Adapter adapter = new ColorfulAdapter(new ColorDataSet());
5755
recyclerView.setAdapter(adapter);
5856

5957
return rootView;
@@ -77,14 +75,4 @@ public void setRecyclerViewLayoutManager(RecyclerView recyclerView) {
7775
recyclerView.scrollToPosition(scrollPosition);
7876
}
7977

80-
/**
81-
* Generates Strings for RecyclerView's adapter. This data would usually come from somewhere...
82-
*/
83-
private String[] getDummyDataSet() {
84-
String[] data = new String[DATASET_COUNT];
85-
for (int i = 0; i < DATASET_COUNT; i++) {
86-
data[i] = "This is element #" + i;
87-
}
88-
return data;
89-
}
9078
}
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,3 @@
1-
/*
2-
* Copyright (C) 2014 The Android Open Source Project
3-
*
4-
* Licensed under the Apache License, Version 2.0 (the "License");
5-
* you may not use this file except in compliance with the License.
6-
* You may obtain a copy of the License at
7-
*
8-
* http://www.apache.org/licenses/LICENSE-2.0
9-
*
10-
* Unless required by applicable law or agreed to in writing, software
11-
* distributed under the License is distributed on an "AS IS" BASIS,
12-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13-
* See the License for the specific language governing permissions and
14-
* limitations under the License.
15-
*/
16-
171
package com.example.recyclerviewfastscroller.fragment;
182

193
import android.os.Bundle;
@@ -25,16 +9,15 @@
259
import android.view.ViewGroup;
2610

2711
import com.example.android.recyclerview.R;
12+
import com.example.recyclerviewfastscroller.data.ColorDataSet;
2813
import com.example.recyclerviewfastscroller.recyclerview.ColorfulAdapter;
14+
import com.example.recyclerviewfastscroller.ui.scroller.sectionindicator.title.SectionTitleIndicator;
2915
import com.example.recyclerviewfastscroller.ui.scroller.vertical.VerticalRecyclerViewFastScroller;
3016

3117
/**
3218
* Adapted from sample code that demonstrates the use of {@link RecyclerView} with a {@link LinearLayoutManager}
3319
*/
34-
public class RecyclerViewWithSectionsFragment extends Fragment {
35-
36-
private static final String TAG = "RecyclerViewFragment";
37-
private static final int DATASET_COUNT = 100;
20+
public class RecyclerViewWithSectionIndicatorFragment extends Fragment {
3821

3922
@Override
4023
public void onCreate(Bundle savedInstanceState) {
@@ -44,17 +27,23 @@ public void onCreate(Bundle savedInstanceState) {
4427
@Override
4528
public View onCreateView(LayoutInflater inflater, ViewGroup container,
4629
Bundle savedInstanceState) {
47-
View rootView = inflater.inflate(R.layout.recycler_view_frag, container, false);
30+
ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.recycler_view_with_fast_scroller_section_title_indicator_fragment, container, false);
31+
32+
RecyclerView recyclerView = (RecyclerView) rootView.findViewById(R.id.recycler_view);
33+
RecyclerView.Adapter adapter = new ColorfulAdapter(new ColorDataSet());
34+
recyclerView.setAdapter(adapter);
4835

49-
RecyclerView recyclerView = (RecyclerView) rootView.findViewById(R.id.recyclerView);
50-
VerticalRecyclerViewFastScroller fastScroller = (VerticalRecyclerViewFastScroller) rootView.findViewById(R.id.fast_scroller);
36+
VerticalRecyclerViewFastScroller fastScroller =
37+
(VerticalRecyclerViewFastScroller) rootView.findViewById(R.id.fast_scroller);
5138
fastScroller.setRecyclerView(recyclerView);
39+
5240
recyclerView.setOnScrollListener(fastScroller.getOnScrollListener());
5341

54-
setRecyclerViewLayoutManager(recyclerView);
42+
SectionTitleIndicator sectionTitleIndicator =
43+
(SectionTitleIndicator) rootView.findViewById(R.id.fast_scroller_section_title_popup);
44+
fastScroller.setSectionIndicator(sectionTitleIndicator);
5545

56-
RecyclerView.Adapter adapter = new ColorfulAdapter(getDummyDataSet());
57-
recyclerView.setAdapter(adapter);
46+
setRecyclerViewLayoutManager(recyclerView);
5847

5948
return rootView;
6049
}
@@ -77,14 +66,4 @@ public void setRecyclerViewLayoutManager(RecyclerView recyclerView) {
7766
recyclerView.scrollToPosition(scrollPosition);
7867
}
7968

80-
/**
81-
* Generates Strings for RecyclerView's adapter. This data would usually come from somewhere...
82-
*/
83-
private String[] getDummyDataSet() {
84-
String[] data = new String[DATASET_COUNT];
85-
for (int i = 0; i < DATASET_COUNT; i++) {
86-
data[i] = "This is element #" + i;
87-
}
88-
return data;
89-
}
9069
}

Application/src/main/java/com/example/recyclerviewfastscroller/recyclerview/ColorfulAdapter.java

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,20 @@
2121
import android.view.LayoutInflater;
2222
import android.view.View;
2323
import android.view.ViewGroup;
24+
import android.widget.SectionIndexer;
2425
import android.widget.TextView;
2526

2627
import com.example.android.recyclerview.R;
28+
import com.example.recyclerviewfastscroller.data.ColorData;
29+
import com.example.recyclerviewfastscroller.data.ColorDataSet;
30+
import com.example.recyclerviewfastscroller.data.ColorGroup;
2731

2832
/**
2933
* Provide views to RecyclerView with data from mDataSet.
3034
*/
31-
public class ColorfulAdapter extends RecyclerView.Adapter<ColorfulAdapter.ViewHolder> {
35+
public class ColorfulAdapter extends RecyclerView.Adapter<ColorfulAdapter.ViewHolder> implements SectionIndexer {
3236

33-
private static final float NUM_HUES = 359f;
34-
35-
private String[] mDataSet;
37+
private ColorDataSet mDataSet;
3638

3739
/**
3840
* Provide a reference to the type of views that you are using (custom ViewHolder)
@@ -60,10 +62,10 @@ public TextView getTextView() {
6062
/**
6163
* Initialize the dataset of the Adapter.
6264
*
63-
* @param dataSet String[] containing the data to populate views to be used by RecyclerView.
65+
* @param data String[] containing the data to populate views to be used by RecyclerView.
6466
*/
65-
public ColorfulAdapter(String[] dataSet) {
66-
mDataSet = dataSet;
67+
public ColorfulAdapter(ColorDataSet data) {
68+
mDataSet = data;
6769
}
6870

6971
// Create new views (invoked by the layout manager)
@@ -78,15 +80,35 @@ public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
7880
public void onBindViewHolder(ViewHolder viewHolder, final int position) {
7981
// Get element from your dataset at this position and replace the contents of the view
8082
// with that element
81-
float positionBasedHue = position * (NUM_HUES / mDataSet.length);
82-
viewHolder.itemView.setBackgroundColor(Color.HSVToColor(new float[] {positionBasedHue, 1, 1}));
83-
viewHolder.getTextView().setText(mDataSet[position]);
83+
ColorData color = mDataSet.get(position);
84+
viewHolder.itemView.setBackgroundColor(color.getIntValue());
85+
viewHolder.getTextView().setText(mDataSet.get(position).toString());
8486
}
8587

8688
// Return the size of your dataset (invoked by the layout manager)
8789
@Override
8890
public int getItemCount() {
89-
return mDataSet.length;
91+
return mDataSet.getSize();
92+
}
93+
94+
@Override
95+
public Object[] getSections() {
96+
return ColorGroup.values();
97+
}
98+
99+
@Override
100+
public int getPositionForSection(int sectionIndex) {
101+
return 0;
102+
}
103+
104+
@Override
105+
public int getSectionForPosition(int position) {
106+
if (position >= mDataSet.getSize()) {
107+
position = mDataSet.getSize() - 1;
108+
}
109+
110+
ColorData color = mDataSet.get(position);
111+
return color.getColorGroup().ordinal();
90112
}
91113

92114
}

0 commit comments

Comments
 (0)