mirror of
https://github.com/antebudimir/tempus.git
synced 2026-01-02 02:13:33 +00:00
build: change of package name
This commit is contained in:
parent
49afdbe4eb
commit
b76a38cb30
274 changed files with 1981 additions and 2161 deletions
|
|
@ -0,0 +1,35 @@
|
|||
package com.cappielloantonio.tempo.helper;
|
||||
|
||||
import android.os.Build;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatDelegate;
|
||||
|
||||
public class ThemeHelper {
|
||||
private static final String TAG = "ThemeHelper";
|
||||
|
||||
public static final String LIGHT_MODE = "light";
|
||||
public static final String DARK_MODE = "dark";
|
||||
public static final String DEFAULT_MODE = "default";
|
||||
|
||||
public static void applyTheme(@NonNull String themePref) {
|
||||
switch (themePref) {
|
||||
case LIGHT_MODE: {
|
||||
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
|
||||
break;
|
||||
}
|
||||
case DARK_MODE: {
|
||||
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
|
||||
} else {
|
||||
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
package com.cappielloantonio.tempo.helper.recyclerview;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.LinearSnapHelper;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
public class CustomLinearSnapHelper extends LinearSnapHelper {
|
||||
@Override
|
||||
public View findSnapView(RecyclerView.LayoutManager layoutManager) {
|
||||
if (layoutManager instanceof LinearLayoutManager) {
|
||||
LinearLayoutManager linearLayoutManager = (LinearLayoutManager) layoutManager;
|
||||
if (!needToDoSnap(linearLayoutManager)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return super.findSnapView(layoutManager);
|
||||
}
|
||||
|
||||
public boolean needToDoSnap(LinearLayoutManager linearLayoutManager) {
|
||||
return linearLayoutManager.findFirstCompletelyVisibleItemPosition() != 0 && linearLayoutManager.findLastCompletelyVisibleItemPosition() != linearLayoutManager.getItemCount() - 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
package com.cappielloantonio.tempo.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);
|
||||
|
||||
if (itemCount <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 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 / 4;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
package com.cappielloantonio.tempo.helper.recyclerview;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
public class GridItemDecoration extends RecyclerView.ItemDecoration {
|
||||
private final int spanCount;
|
||||
private final int spacing;
|
||||
private final boolean includeEdge;
|
||||
|
||||
public GridItemDecoration(int spanCount, int spacing, boolean includeEdge) {
|
||||
this.spanCount = spanCount;
|
||||
this.spacing = spacing;
|
||||
this.includeEdge = includeEdge;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, RecyclerView parent, @NonNull RecyclerView.State state) {
|
||||
int position = parent.getChildAdapterPosition(view); // item position
|
||||
int column = position % spanCount; // item column
|
||||
|
||||
if (includeEdge) {
|
||||
outRect.left = spacing - column * spacing / spanCount; // spacing - column * ((1f / spanCount) * spacing)
|
||||
outRect.right = (column + 1) * spacing / spanCount; // (column + 1) * ((1f / spanCount) * spacing)
|
||||
|
||||
if (position < spanCount) { // top edge
|
||||
outRect.top = spacing;
|
||||
}
|
||||
outRect.bottom = spacing; // item bottom
|
||||
} else {
|
||||
outRect.left = column * spacing / spanCount; // column * ((1f / spanCount) * spacing)
|
||||
outRect.right = spacing - (column + 1) * spacing / spanCount; // spacing - (column + 1) * ((1f / spanCount) * spacing)
|
||||
if (position >= spanCount) {
|
||||
outRect.top = spacing; // item top
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
package com.cappielloantonio.tempo.helper.recyclerview
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.view.ViewConfiguration
|
||||
import android.widget.FrameLayout
|
||||
import androidx.viewpager2.widget.ViewPager2
|
||||
import androidx.viewpager2.widget.ViewPager2.ORIENTATION_HORIZONTAL
|
||||
import kotlin.math.absoluteValue
|
||||
import kotlin.math.sign
|
||||
|
||||
class NestedScrollableHost : FrameLayout {
|
||||
constructor(context: Context) : super(context)
|
||||
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
|
||||
|
||||
private var touchSlop = 0
|
||||
private var initialX = 0f
|
||||
private var initialY = 0f
|
||||
private val parentViewPager: ViewPager2?
|
||||
get() {
|
||||
var v: View? = parent as? View
|
||||
while (v != null && v !is ViewPager2) {
|
||||
v = v.parent as? View
|
||||
}
|
||||
return v as? ViewPager2
|
||||
}
|
||||
|
||||
private val child: View? get() = if (childCount > 0) getChildAt(0) else null
|
||||
|
||||
init {
|
||||
touchSlop = ViewConfiguration.get(context).scaledTouchSlop
|
||||
}
|
||||
|
||||
private fun canChildScroll(orientation: Int, delta: Float): Boolean {
|
||||
val direction = -delta.sign.toInt()
|
||||
return when (orientation) {
|
||||
0 -> child?.canScrollHorizontally(direction) ?: false
|
||||
1 -> child?.canScrollVertically(direction) ?: false
|
||||
else -> throw IllegalArgumentException()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onInterceptTouchEvent(e: MotionEvent): Boolean {
|
||||
handleInterceptTouchEvent(e)
|
||||
return super.onInterceptTouchEvent(e)
|
||||
}
|
||||
|
||||
private fun handleInterceptTouchEvent(e: MotionEvent) {
|
||||
val orientation = parentViewPager?.orientation ?: return
|
||||
|
||||
// Early return if child can't scroll in same direction as parent
|
||||
if (!canChildScroll(orientation, -1f) && !canChildScroll(orientation, 1f)) {
|
||||
return
|
||||
}
|
||||
|
||||
if (e.action == MotionEvent.ACTION_DOWN) {
|
||||
initialX = e.x
|
||||
initialY = e.y
|
||||
parent.requestDisallowInterceptTouchEvent(true)
|
||||
} else if (e.action == MotionEvent.ACTION_MOVE) {
|
||||
val dx = e.x - initialX
|
||||
val dy = e.y - initialY
|
||||
val isVpHorizontal = orientation == ORIENTATION_HORIZONTAL
|
||||
|
||||
// assuming ViewPager2 touch-slop is 2x touch-slop of child
|
||||
val scaledDx = dx.absoluteValue * if (isVpHorizontal) .5f else 1f
|
||||
val scaledDy = dy.absoluteValue * if (isVpHorizontal) 1f else .5f
|
||||
|
||||
if (scaledDx > touchSlop || scaledDy > touchSlop) {
|
||||
if (isVpHorizontal == (scaledDy > scaledDx)) {
|
||||
// Gesture is perpendicular, allow all parents to intercept
|
||||
parent.requestDisallowInterceptTouchEvent(false)
|
||||
} else {
|
||||
// Gesture is parallel, query child if movement in that direction is possible
|
||||
if (canChildScroll(orientation, if (isVpHorizontal) dx else dy)) {
|
||||
// Child can scroll, disallow all parents to intercept
|
||||
parent.requestDisallowInterceptTouchEvent(true)
|
||||
} else {
|
||||
// Child cannot scroll, allow all parents to intercept
|
||||
parent.requestDisallowInterceptTouchEvent(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
package com.cappielloantonio.tempo.helper.recyclerview;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
|
||||
public abstract class PaginationScrollListener extends RecyclerView.OnScrollListener {
|
||||
private final LinearLayoutManager layoutManager;
|
||||
|
||||
protected PaginationScrollListener(LinearLayoutManager layoutManager) {
|
||||
this.layoutManager = layoutManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
|
||||
super.onScrolled(recyclerView, dx, dy);
|
||||
|
||||
int visibleItemCount = layoutManager.getChildCount();
|
||||
int totalItemCount = layoutManager.getItemCount();
|
||||
int firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition();
|
||||
|
||||
if (!isLoading()) {
|
||||
if (firstVisibleItemPosition >= 0 && (visibleItemCount + firstVisibleItemPosition) >= (totalItemCount / 4 * 3)) {
|
||||
loadMoreItems();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void loadMoreItems();
|
||||
|
||||
public abstract boolean isLoading();
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
package com.cappielloantonio.tempo.helper.recyclerview;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.RelativeLayout;
|
||||
|
||||
public class SquareLayout extends RelativeLayout {
|
||||
public SquareLayout(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public SquareLayout(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public SquareLayout(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
public SquareLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue