Gadgetbridge/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/welcome/WelcomePageIndicator.java

136 lines
4.6 KiB
Java

/* Copyright (C) 2024 Arjan Schrijver
This file is part of Gadgetbridge.
Gadgetbridge is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gadgetbridge is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.activities.welcome;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
import androidx.annotation.Nullable;
import androidx.viewpager2.widget.ViewPager2;
import nodomain.freeyourgadget.gadgetbridge.R;
public class WelcomePageIndicator extends View {
private ViewPager2 viewPager;
private int pageCount;
private int dotRadius = 15;
private int color;
private Paint outlinePaint;
private Paint filledPaint;
private float currentX = 0.0f;
private ValueAnimator dotAnimator;
public WelcomePageIndicator(Context context) {
super(context);
init();
}
public WelcomePageIndicator(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
determineColor(context, attrs);
init();
}
public WelcomePageIndicator(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
determineColor(context, attrs);
init();
}
private void determineColor(Context context, @Nullable AttributeSet attrs) {
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.WelcomePageIndicator);
color = a.getColor(R.styleable.WelcomePageIndicator_page_indicator_color, Color.BLACK);
a.recycle();
}
private void init() {
outlinePaint = new Paint();
outlinePaint.setColor(color);
outlinePaint.setStyle(Paint.Style.STROKE);
outlinePaint.setStrokeWidth(4);
outlinePaint.setAntiAlias(true);
filledPaint = new Paint();
filledPaint.setColor(color);
filledPaint.setStyle(Paint.Style.FILL);
outlinePaint.setAntiAlias(true);
}
public void setViewPager(ViewPager2 viewPager) {
this.viewPager = viewPager;
this.pageCount = viewPager.getAdapter().getItemCount();
viewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
@Override
public void onPageSelected(int position) {
animateIndicator(position);
}
});
invalidate();
}
private int getHorizontalMargin() {
int dotDiameter = dotRadius * 2;
int dotSpaces = pageCount * 2 - 1;
return (getWidth() - dotSpaces * dotDiameter) / 2 + dotRadius;
}
private void animateIndicator(int position) {
float horizontalMargin = getHorizontalMargin();
if (horizontalMargin <= 0.0f) {
// Not animating because the drawable is not ready yet
return;
}
float targetX = horizontalMargin + 4 * dotRadius * position;
if (dotAnimator != null && dotAnimator.isRunning()) {
dotAnimator.cancel();
}
if (currentX == 0.0f) currentX = horizontalMargin;
dotAnimator = ValueAnimator.ofFloat(currentX, targetX);
dotAnimator.addUpdateListener(animation -> {
currentX = (float) animation.getAnimatedValue();
invalidate();
});
dotAnimator.setDuration(300);
dotAnimator.start();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (viewPager == null || pageCount == 0) {
return;
}
float horizontalMargin = getHorizontalMargin();
if (currentX == 0.0f && horizontalMargin != 0.0f) currentX = horizontalMargin;
float circleY = getHeight() / 2f;
for (int i = 0; i < pageCount; i++) {
float circleX = horizontalMargin + 4 * dotRadius * i;
canvas.drawCircle(circleX, circleY, dotRadius, outlinePaint);
}
canvas.drawCircle(currentX, circleY, dotRadius, filledPaint);
}
}