mirror of
https://github.com/antebudimir/tempus.git
synced 2025-12-31 17:43:32 +00:00
Add dots indicator to horizontalGridView in HomeFragment
This commit is contained in:
parent
8060d1db64
commit
8789b44e26
4 changed files with 144 additions and 1 deletions
2
.idea/misc.xml
generated
2
.idea/misc.xml
generated
|
|
@ -43,7 +43,7 @@
|
||||||
<entry key="app/src/main/res/layout/fragment_album_catalogue.xml" value="0.3229166666666667" />
|
<entry key="app/src/main/res/layout/fragment_album_catalogue.xml" value="0.3229166666666667" />
|
||||||
<entry key="app/src/main/res/layout/fragment_album_page.xml" value="0.2769409038238702" />
|
<entry key="app/src/main/res/layout/fragment_album_page.xml" value="0.2769409038238702" />
|
||||||
<entry key="app/src/main/res/layout/fragment_artist_page.xml" value="0.1" />
|
<entry key="app/src/main/res/layout/fragment_artist_page.xml" value="0.1" />
|
||||||
<entry key="app/src/main/res/layout/fragment_home.xml" value="0.1" />
|
<entry key="app/src/main/res/layout/fragment_home.xml" value="0.3229166666666667" />
|
||||||
<entry key="app/src/main/res/layout/fragment_login.xml" value="0.3166496424923391" />
|
<entry key="app/src/main/res/layout/fragment_login.xml" value="0.3166496424923391" />
|
||||||
<entry key="app/src/main/res/layout/fragment_player_bottom_sheet.xml" value="0.3166496424923391" />
|
<entry key="app/src/main/res/layout/fragment_player_bottom_sheet.xml" value="0.3166496424923391" />
|
||||||
<entry key="app/src/main/res/layout/fragment_playlist_catalogue.xml" value="0.3229166666666667" />
|
<entry key="app/src/main/res/layout/fragment_playlist_catalogue.xml" value="0.3229166666666667" />
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,112 @@
|
||||||
|
package com.cappielloantonio.play.helper.recyclerview;
|
||||||
|
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.graphics.Rect;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import androidx.annotation.ColorInt;
|
||||||
|
import androidx.recyclerview.widget.GridLayoutManager;
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public class DotsIndicatorDecoration extends RecyclerView.ItemDecoration {
|
||||||
|
private static final String TAG = "DotsIndicatorDecoration";
|
||||||
|
|
||||||
|
private final int indicatorHeight;
|
||||||
|
private final int indicatorItemPadding;
|
||||||
|
private final int radius;
|
||||||
|
|
||||||
|
private final Paint inactivePaint = new Paint();
|
||||||
|
private final Paint activePaint = new Paint();
|
||||||
|
|
||||||
|
public DotsIndicatorDecoration(int radius, int padding, int indicatorHeight, @ColorInt int colorInactive, @ColorInt int colorActive) {
|
||||||
|
float strokeWidth = Resources.getSystem().getDisplayMetrics().density * 1;
|
||||||
|
this.radius = radius;
|
||||||
|
|
||||||
|
inactivePaint.setStrokeCap(Paint.Cap.ROUND);
|
||||||
|
inactivePaint.setStrokeWidth(strokeWidth);
|
||||||
|
inactivePaint.setStyle(Paint.Style.STROKE);
|
||||||
|
inactivePaint.setAntiAlias(true);
|
||||||
|
inactivePaint.setColor(colorInactive);
|
||||||
|
|
||||||
|
activePaint.setStrokeCap(Paint.Cap.ROUND);
|
||||||
|
activePaint.setStrokeWidth(strokeWidth);
|
||||||
|
activePaint.setStyle(Paint.Style.FILL);
|
||||||
|
activePaint.setAntiAlias(true);
|
||||||
|
activePaint.setColor(colorActive);
|
||||||
|
|
||||||
|
this.indicatorItemPadding = padding;
|
||||||
|
this.indicatorHeight = indicatorHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDrawOver(@NotNull Canvas c, @NotNull RecyclerView parent, @NotNull RecyclerView.State state) {
|
||||||
|
super.onDrawOver(c, parent, state);
|
||||||
|
|
||||||
|
if (parent.getAdapter() == null) return;
|
||||||
|
|
||||||
|
int itemCount = (int) Math.ceil((double) parent.getAdapter().getItemCount() / 5);
|
||||||
|
|
||||||
|
// center horizontally, calculate width and subtract half from center
|
||||||
|
float totalLength = this.radius * 2 * itemCount;
|
||||||
|
float paddingBetweenItems = Math.max(0, itemCount - 1) * indicatorItemPadding;
|
||||||
|
float indicatorTotalWidth = totalLength + paddingBetweenItems;
|
||||||
|
float indicatorStartX = (parent.getWidth() - indicatorTotalWidth) / 2f;
|
||||||
|
|
||||||
|
// center vertically in the allotted space
|
||||||
|
float indicatorPosY = parent.getHeight() - indicatorHeight - (float) indicatorItemPadding / 3;
|
||||||
|
|
||||||
|
drawInactiveDots(c, indicatorStartX, indicatorPosY, itemCount);
|
||||||
|
|
||||||
|
final int activePosition;
|
||||||
|
|
||||||
|
if (parent.getLayoutManager() instanceof GridLayoutManager) {
|
||||||
|
activePosition = ((GridLayoutManager) parent.getLayoutManager()).findFirstVisibleItemPosition();
|
||||||
|
} else if (parent.getLayoutManager() instanceof LinearLayoutManager) {
|
||||||
|
activePosition = ((LinearLayoutManager) parent.getLayoutManager()).findFirstVisibleItemPosition();
|
||||||
|
} else {
|
||||||
|
// not supported layout manager
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (activePosition == RecyclerView.NO_POSITION) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// find offset of active page if the user is scrolling
|
||||||
|
final View activeChild = parent.getLayoutManager().findViewByPosition(activePosition);
|
||||||
|
if (activeChild == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
drawActiveDot(c, indicatorStartX, indicatorPosY, activePosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void drawInactiveDots(Canvas c, float indicatorStartX, float indicatorPosY, int itemCount) {
|
||||||
|
// width of item indicator including padding
|
||||||
|
final float itemWidth = this.radius * 2 + indicatorItemPadding;
|
||||||
|
|
||||||
|
float start = indicatorStartX + radius;
|
||||||
|
for (int i = 0; i < itemCount; i++) {
|
||||||
|
c.drawCircle(start, indicatorPosY, radius, inactivePaint);
|
||||||
|
start += itemWidth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void drawActiveDot(Canvas c, float indicatorStartX, float indicatorPosY, int highlightPosition) {
|
||||||
|
// width of item indicator including padding
|
||||||
|
final float itemWidth = this.radius * 2 + indicatorItemPadding;
|
||||||
|
float highlightStart = (float) Math.ceil(indicatorStartX + radius + itemWidth * highlightPosition / 5);
|
||||||
|
c.drawCircle(highlightStart, indicatorPosY, radius, activePaint);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void getItemOffsets(@NotNull Rect outRect, @NotNull View view, @NotNull RecyclerView parent, @NotNull RecyclerView.State state) {
|
||||||
|
super.getItemOffsets(outRect, view, parent, state);
|
||||||
|
outRect.bottom = indicatorHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -11,6 +11,7 @@ import android.view.ViewGroup;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
import androidx.core.view.ViewCompat;
|
import androidx.core.view.ViewCompat;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
|
|
@ -31,6 +32,7 @@ import com.cappielloantonio.play.adapter.SongHorizontalAdapter;
|
||||||
import com.cappielloantonio.play.adapter.YearAdapter;
|
import com.cappielloantonio.play.adapter.YearAdapter;
|
||||||
import com.cappielloantonio.play.databinding.FragmentHomeBinding;
|
import com.cappielloantonio.play.databinding.FragmentHomeBinding;
|
||||||
import com.cappielloantonio.play.helper.recyclerview.CustomLinearSnapHelper;
|
import com.cappielloantonio.play.helper.recyclerview.CustomLinearSnapHelper;
|
||||||
|
import com.cappielloantonio.play.helper.recyclerview.DotsIndicatorDecoration;
|
||||||
import com.cappielloantonio.play.model.Album;
|
import com.cappielloantonio.play.model.Album;
|
||||||
import com.cappielloantonio.play.model.Artist;
|
import com.cappielloantonio.play.model.Artist;
|
||||||
import com.cappielloantonio.play.model.Song;
|
import com.cappielloantonio.play.model.Song;
|
||||||
|
|
@ -358,6 +360,15 @@ public class HomeFragment extends Fragment {
|
||||||
|
|
||||||
SnapHelper starredTrackSnapHelper = new PagerSnapHelper();
|
SnapHelper starredTrackSnapHelper = new PagerSnapHelper();
|
||||||
starredTrackSnapHelper.attachToRecyclerView(bind.starredTracksRecyclerView);
|
starredTrackSnapHelper.attachToRecyclerView(bind.starredTracksRecyclerView);
|
||||||
|
|
||||||
|
bind.starredTracksRecyclerView.addItemDecoration(
|
||||||
|
new DotsIndicatorDecoration(
|
||||||
|
getResources().getDimensionPixelSize(R.dimen.radius),
|
||||||
|
getResources().getDimensionPixelSize(R.dimen.radius) * 4,
|
||||||
|
getResources().getDimensionPixelSize(R.dimen.dots_height),
|
||||||
|
requireContext().getResources().getColor(R.color.titleTextColor, null),
|
||||||
|
requireContext().getResources().getColor(R.color.titleTextColor, null))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initStarredAlbumsView() {
|
private void initStarredAlbumsView() {
|
||||||
|
|
@ -380,6 +391,15 @@ public class HomeFragment extends Fragment {
|
||||||
|
|
||||||
SnapHelper starredAlbumSnapHelper = new PagerSnapHelper();
|
SnapHelper starredAlbumSnapHelper = new PagerSnapHelper();
|
||||||
starredAlbumSnapHelper.attachToRecyclerView(bind.starredAlbumsRecyclerView);
|
starredAlbumSnapHelper.attachToRecyclerView(bind.starredAlbumsRecyclerView);
|
||||||
|
|
||||||
|
bind.starredAlbumsRecyclerView.addItemDecoration(
|
||||||
|
new DotsIndicatorDecoration(
|
||||||
|
getResources().getDimensionPixelSize(R.dimen.radius),
|
||||||
|
getResources().getDimensionPixelSize(R.dimen.radius) * 4,
|
||||||
|
getResources().getDimensionPixelSize(R.dimen.dots_height),
|
||||||
|
requireContext().getResources().getColor(R.color.titleTextColor, null),
|
||||||
|
requireContext().getResources().getColor(R.color.titleTextColor, null))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initStarredArtistsView() {
|
private void initStarredArtistsView() {
|
||||||
|
|
@ -402,6 +422,15 @@ public class HomeFragment extends Fragment {
|
||||||
|
|
||||||
SnapHelper starredArtistSnapHelper = new PagerSnapHelper();
|
SnapHelper starredArtistSnapHelper = new PagerSnapHelper();
|
||||||
starredArtistSnapHelper.attachToRecyclerView(bind.starredArtistsRecyclerView);
|
starredArtistSnapHelper.attachToRecyclerView(bind.starredArtistsRecyclerView);
|
||||||
|
|
||||||
|
bind.starredArtistsRecyclerView.addItemDecoration(
|
||||||
|
new DotsIndicatorDecoration(
|
||||||
|
getResources().getDimensionPixelSize(R.dimen.radius),
|
||||||
|
getResources().getDimensionPixelSize(R.dimen.radius) * 4,
|
||||||
|
getResources().getDimensionPixelSize(R.dimen.dots_height),
|
||||||
|
requireContext().getResources().getColor(R.color.titleTextColor, null),
|
||||||
|
requireContext().getResources().getColor(R.color.titleTextColor, null))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initRecentAddedAlbumView() {
|
private void initRecentAddedAlbumView() {
|
||||||
|
|
|
||||||
|
|
@ -11,4 +11,6 @@
|
||||||
|
|
||||||
<dimen name="notification_big_image_size">128dp</dimen>
|
<dimen name="notification_big_image_size">128dp</dimen>
|
||||||
|
|
||||||
|
<dimen name="radius">2dp</dimen>
|
||||||
|
<dimen name="dots_height">2dp</dimen>
|
||||||
</resources>
|
</resources>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue