Skip to content

Commit ee544b5

Browse files
committed
Rework tutorial by using ViewPager2
Add tutorial utils. Add page indicator for ViewPager2. Add dynamic fragment state adapter. Update simple tutorial and its fragment. Update tutorial activity and its layout.
1 parent d8db1c9 commit ee544b5

File tree

13 files changed

+1478
-469
lines changed

13 files changed

+1478
-469
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/*
2+
* Copyright 2019 Pranav Pandey
3+
* Copyright 2014 Soichiro Kashima
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package com.pranavpandey.android.dynamic.support.adapter;
19+
20+
import androidx.annotation.NonNull;
21+
import androidx.annotation.Nullable;
22+
import androidx.fragment.app.Fragment;
23+
import androidx.fragment.app.FragmentActivity;
24+
import androidx.fragment.app.FragmentManager;
25+
import androidx.lifecycle.Lifecycle;
26+
import androidx.recyclerview.widget.RecyclerView;
27+
import androidx.viewpager2.adapter.FragmentStateAdapter;
28+
29+
import com.pranavpandey.android.dynamic.support.theme.DynamicTheme;
30+
import com.pranavpandey.android.dynamic.support.utils.DynamicScrollUtils;
31+
import com.pranavpandey.android.dynamic.utils.DynamicColorUtils;
32+
33+
/**
34+
* FragmentStateAdapter to with the the {@link androidx.viewpager2.widget.ViewPager2}.
35+
* <p>The main purpose of this adapter is to tint the recycler view edge glow according to the
36+
* dynamic theme.
37+
*/
38+
public abstract class DynamicFragmentStateAdapter extends FragmentStateAdapter {
39+
40+
/**
41+
* Recycler view attached to this adapter.
42+
*/
43+
private RecyclerView mRecyclerView;
44+
45+
public DynamicFragmentStateAdapter(@NonNull FragmentActivity fragmentActivity) {
46+
super(fragmentActivity);
47+
}
48+
49+
public DynamicFragmentStateAdapter(@NonNull Fragment fragment) {
50+
super(fragment);
51+
}
52+
53+
public DynamicFragmentStateAdapter(@NonNull FragmentManager fragmentManager,
54+
@NonNull Lifecycle lifecycle) {
55+
super(fragmentManager, lifecycle);
56+
}
57+
58+
@Override
59+
public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
60+
super.onAttachedToRecyclerView(recyclerView);
61+
62+
this.mRecyclerView = recyclerView;
63+
64+
onTintRecyclerView();
65+
}
66+
67+
/**
68+
* This method will be called to tint the recycler view.
69+
*/
70+
protected void onTintRecyclerView() {
71+
if (mRecyclerView == null) {
72+
return;
73+
}
74+
75+
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
76+
@Override
77+
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
78+
super.onScrollStateChanged(recyclerView, newState);
79+
80+
DynamicScrollUtils.setEdgeEffectColor(recyclerView,
81+
!DynamicTheme.getInstance().get().isBackgroundAware()
82+
? DynamicTheme.getInstance().get().getPrimaryColor()
83+
: DynamicColorUtils.getContrastColor(
84+
DynamicTheme.getInstance().get().getPrimaryColor(),
85+
DynamicTheme.getInstance().get().getBackgroundColor()));
86+
}
87+
88+
});
89+
}
90+
91+
/**
92+
* Returns the recycler view attached to this adapter.
93+
*
94+
* @return The recycler view attached to this adapter.
95+
*/
96+
public @Nullable RecyclerView getRecyclerView() {
97+
return mRecyclerView;
98+
}
99+
}

dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/tutorial/DynamicSimpleTutorial.java

Lines changed: 57 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,14 @@
2424
import androidx.annotation.NonNull;
2525
import androidx.annotation.Nullable;
2626

27-
import com.pranavpandey.android.dynamic.support.tutorial.fragment.DynamicSimpleTutorialFragment;
27+
import com.pranavpandey.android.dynamic.support.tutorial.fragment.DynamicTutorialFragment;
2828

2929
/**
3030
* A simple tutorial item to display a title, subtitle and description along with an image
3131
* which can be tinted according to the background color.
3232
*/
33-
public class DynamicSimpleTutorial implements Parcelable {
33+
public class DynamicSimpleTutorial implements Parcelable,
34+
DynamicTutorial<DynamicSimpleTutorial, DynamicTutorialFragment> {
3435

3536
/**
3637
* Id to uniquely identify this tutorial.
@@ -67,6 +68,8 @@ public class DynamicSimpleTutorial implements Parcelable {
6768
*/
6869
private boolean tintImage;
6970

71+
private DynamicTutorialFragment mFragment;
72+
7073
/**
7174
* Constructor to initialize an object of this class.
7275
*
@@ -195,6 +198,7 @@ public DynamicSimpleTutorial setId(int id) {
195198
*
196199
* @return The background color used by this tutorial.
197200
*/
201+
@Override
198202
public @ColorInt int getBackgroundColor() {
199203
return backgroundColor;
200204
}
@@ -210,6 +214,7 @@ public DynamicSimpleTutorial setId(int id) {
210214
public DynamicSimpleTutorial setBackgroundColor(@ColorInt int backgroundColor) {
211215
this.backgroundColor = backgroundColor;
212216

217+
onBackgroundColorChanged(backgroundColor);
213218
return this;
214219
}
215220

@@ -328,14 +333,55 @@ public DynamicSimpleTutorial setTintImage(boolean tintImage) {
328333
return this;
329334
}
330335

331-
/**
332-
* Build the simple tutorial according to the supplied parameters.
333-
*
334-
* @return The dynamic tutorial fragment to show it in the view pager.
335-
*
336-
* @see DynamicSimpleTutorialFragment
337-
*/
338-
public @NonNull DynamicTutorial build() {
339-
return DynamicSimpleTutorialFragment.newInstance(this);
336+
@Override
337+
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
338+
if (mFragment != null) {
339+
mFragment.onPageScrolled(position, positionOffset, positionOffsetPixels);
340+
}
341+
}
342+
343+
@Override
344+
public void onPageSelected(int position) {
345+
if (mFragment != null) {
346+
mFragment.onPageSelected(position);
347+
}
348+
}
349+
350+
@Override
351+
public void onPageScrollStateChanged(int state) {
352+
if (mFragment != null) {
353+
mFragment.onPageScrollStateChanged(state);
354+
}
355+
}
356+
357+
@Override
358+
public @NonNull DynamicSimpleTutorial getTutorial() {
359+
return this;
360+
}
361+
362+
@Override
363+
public @NonNull DynamicTutorialFragment createTutorial() {
364+
mFragment = DynamicTutorialFragment.newInstance(this);
365+
366+
return mFragment;
367+
}
368+
369+
@Override
370+
public int getTutorialId() {
371+
return getId();
372+
}
373+
374+
@Override
375+
public void onBackgroundColorChanged(int color) {
376+
if (mFragment != null) {
377+
mFragment.onBackgroundColorChanged(color);
378+
}
379+
}
380+
381+
@Override
382+
public void onSetPadding(int left, int top, int right, int bottom) {
383+
if (mFragment != null) {
384+
mFragment.onSetPadding(left, top, right, bottom);
385+
}
340386
}
341387
}

dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/tutorial/DynamicTutorial.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package com.pranavpandey.android.dynamic.support.tutorial;
1818

1919
import androidx.annotation.ColorInt;
20+
import androidx.annotation.NonNull;
2021
import androidx.viewpager.widget.ViewPager;
2122

2223
import com.pranavpandey.android.dynamic.support.tutorial.activity.DynamicTutorialActivity;
@@ -28,14 +29,21 @@
2829
* <p><p>Any child view or fragment must implement this interface to support any color
2930
* transitions.
3031
*/
31-
public interface DynamicTutorial extends ViewPager.OnPageChangeListener {
32+
public interface DynamicTutorial<T, V> extends ViewPager.OnPageChangeListener {
3233

3334
/**
3435
* Returns the tutorial object.
3536
*
3637
* @return The tutorial object.
3738
*/
38-
Object getTutorial();
39+
@NonNull T getTutorial();
40+
41+
/**
42+
* Returns the tutorial view or fragment.
43+
*
44+
* @return The tutorial view or fragment.
45+
*/
46+
@NonNull V createTutorial();
3947

4048
/**
4149
* Returns the id for this tutorial.
@@ -58,4 +66,6 @@ public interface DynamicTutorial extends ViewPager.OnPageChangeListener {
5866
* @param color The color of the background.
5967
*/
6068
void onBackgroundColorChanged(@ColorInt int color);
69+
70+
void onSetPadding(int left, int top, int right, int bottom);
6171
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/*
2+
* Copyright 2019 Pranav Pandey
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+
17+
package com.pranavpandey.android.dynamic.support.tutorial;
18+
19+
import android.graphics.drawable.Drawable;
20+
import android.view.View;
21+
import android.widget.ImageView;
22+
import android.widget.TextView;
23+
24+
import androidx.annotation.ColorInt;
25+
import androidx.annotation.Nullable;
26+
27+
import com.pranavpandey.android.dynamic.support.widget.base.DynamicScrollableWidget;
28+
import com.pranavpandey.android.dynamic.support.widget.base.DynamicWidget;
29+
30+
/**
31+
* Helper class to do the dynamic tutorial operations.
32+
*/
33+
public class DynamicTutorialUtils {
34+
35+
/**
36+
* Set drawable for the tutorial image view and mange its visibility according to the data.
37+
*
38+
* @param imageView The image view to set the drawable.
39+
* @param drawable The drawable for the image view.
40+
*/
41+
public static void setImage(@Nullable ImageView imageView, @Nullable Drawable drawable) {
42+
if (imageView != null) {
43+
if (drawable != null) {
44+
imageView.setImageDrawable(drawable);
45+
imageView.setVisibility(View.VISIBLE);
46+
} else {
47+
imageView.setVisibility(View.GONE);
48+
}
49+
}
50+
}
51+
52+
/**
53+
* Set text for the tutorial text view and mange its visibility according to the data.
54+
*
55+
* @param textView The text view to set the text.
56+
* @param text The text for the text view.
57+
*/
58+
public static void setText(@Nullable TextView textView, @Nullable String text) {
59+
if (textView != null) {
60+
if (text != null) {
61+
textView.setText(text);
62+
textView.setVisibility(View.VISIBLE);
63+
} else {
64+
textView.setVisibility(View.GONE);
65+
}
66+
}
67+
}
68+
69+
/**
70+
* Tint dynamic widgets used by the tutorial according to the supplied color.
71+
*
72+
* @param dynamicWidget The dynamic widget to be tinted.
73+
* @param color The color to tint the widget.
74+
*/
75+
public static void tintDynamicView(@Nullable DynamicWidget dynamicWidget, @ColorInt int color) {
76+
if (dynamicWidget != null) {
77+
dynamicWidget.setColor(color);
78+
79+
if (dynamicWidget instanceof DynamicScrollableWidget) {
80+
((DynamicScrollableWidget) dynamicWidget).setScrollBarColor(color);
81+
}
82+
}
83+
}
84+
}

0 commit comments

Comments
 (0)