После нескольких дней поиска у меня наконец-то появилось достаточно ресурсов для решения проблемы.Для начинающих используйте следующие ресурсы:
1) https://guides.codepath.com/android/Basic-Painting-with-Views
2) https://guides.codepath.com/android/Progress-Bar-Custom-View
3) https://developer.android.com/guide/topics/ui/custom-components
Основные шаги -
- Расширение существующего класса или подкласса представления своим собственным классом.
- Переопределение некоторых методов из суперкласса.Методы суперкласса для переопределения начинаются с 'on', например, onDraw (), onMeasure () и onKeyDown ().Это похоже на события on ... в Activity или ListActivity, которые вы переопределяете для жизненного цикла и других функций.
- Используйте свой новый класс расширений.После завершения ваш новый класс расширения может использоваться вместо представления, на котором он основан.
Ниже приведен код, демонстрирующий рабочие Часы на холсте -
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import java.util.Calendar;
/**
* Created by moonis
* on 23/06/18.
*/
public class CustomClock extends View {
private int height, width = 0;
private int padding = 0;
private int fontSize = 0;
int numeralSpacing = 0;
private int handTruncation, hourHandTruncation = 0;
private int radius = 0;
private Paint paint;
private boolean isInit;
private int[] numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
private Rect rect = new Rect();
public CustomClock(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
setFocusable(true);
setFocusableInTouchMode(true);
}
private void initClock() {
height = getHeight();
width = getWidth();
padding = numeralSpacing + 50;
fontSize = (int) DeviceDimensionHelper.convertDpToPixel(13, getContext());
int min = Math.min(height, width);
radius = min / 2 - padding;
handTruncation = min / 20;
hourHandTruncation = min / 7;
paint = new Paint();
isInit = false;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (!isInit) {
initClock();
}
canvas.drawColor(Color.BLACK);
drawCircle(canvas);
drawCentre(canvas);
drawNumeral(canvas);
drawHands(canvas);
postInvalidateDelayed(500);
}
private void drawCircle(Canvas canvas) {
paint.reset();
paint.setColor(Color.WHITE);
paint.setAntiAlias(true);
paint.setStrokeWidth(5);
paint.setStyle(Paint.Style.STROKE);
canvas.drawCircle(width / 2, height / 2, radius + padding - 10, paint);
}
private void drawCentre(Canvas canvas) {
paint.setStyle(Paint.Style.FILL);
canvas.drawCircle(width / 2, height / 2, 12, paint);
}
private void drawNumeral(Canvas canvas) {
paint.setTextSize(fontSize);
for (int number : numbers) {
String tmp = String.valueOf(number);
paint.getTextBounds(tmp, 0, tmp.length(), rect);
double angle = Math.PI / 6 * (number - 3);
int x = (int) (width / 2 + Math.cos(angle) * radius - rect.width() / 2);
int y = (int) (height / 2 + Math.sin(angle) * radius - rect.height() / 2);
canvas.drawText(tmp, x, y, paint);
}
}
private void drawHands(Canvas canvas) {
Calendar c = Calendar.getInstance();
float hour = c.get(Calendar.HOUR_OF_DAY);
hour = hour > 12 ? hour - 12 : hour;
drawHand(canvas, (hour + c.get(Calendar.MINUTE) / 60) * 5f, true);
drawHand(canvas, c.get(Calendar.MINUTE), false);
drawHand(canvas, c.get(Calendar.SECOND), false);
}
private void drawHand(Canvas canvas, double loc, boolean isHour) {
double angle = Math.PI * loc / 30 - Math.PI / 2;
int handRadius = isHour ? radius - handTruncation - hourHandTruncation : radius - handTruncation;
canvas.drawLine(width / 2, height / 2, (float) (width / 2 + Math.cos(angle) * handRadius), (float) (height / 2 + Math.sin(angle) * handRadius), paint);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float touchX = event.getX();
float touchY = event.getY();
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
//code to move clock hands on screen gestures
break;
case MotionEvent.ACTION_MOVE:
//code to move clock hands on screen gestures
break;
default:
return false;
}
//redraw view
postInvalidate();
return true;
}
}
Наконец, эту библиотеку можно использовать для достижения желаемого результата -
https://github.com/moldedbits/android-dial-picker