Конструктор класса для различных типов параметров
Всех приветствую.
Пытаюсю сделать реализацию получения значений от элементов UI не зависящей от конкретного элемента (Кнопка, seekbar, imageview и т.д)
Значение от этих элемнтов должен принимать уже другой класс
Но тут проблема - как понять, что конкретно было передано в класс - кнопка или seekbar? А может вообще imageView?
Прикол в том, что для каждого элемента разные способы получения значений.
Да и не каждый элемент может вернуть значение от нужного элемента.
Допустим, чтобы поворачивать колеса у автомобиля - больше подойдет SeekBar, нежели кнопка / картинка с onClickListener'ом.
Пример кода, где я застрял:
public interface IUIElementValueListener {
void onStateChanged(float value);
}
public abstract class UIElement {
protected float value;
protected boolean old_button_state;
Button button;
SeekBar seekBar;
ImageView imageView;
IUIElementValueListener listener;
public UIElement(Button button, Seekbar seekbar, ImageView imageView, IUIElementValueListener listener){
this.listener = listener;
// Бред же, ну?
if (button != null){
initButton(button);
}
if (seekBar != null){
initSeekbar(seekBar);
}
if (imageView != null){
initImageView(imageView);
}
}
public abstract void initButton(Button button);
public abstract void initSeekbar(SeekBar seekBar);
public abstract void initImageView(ImageView imageView);
public float getValue(){
return this.value;
}
}
public class Steering extends UIElement {
public Steering(Button button, SeekBar seekBar, ImageView imageView, IUIElementValueListener listener) {
super(button, seekBar, imageView, listener);
}
@Override
public void initSeekbar(SeekBar seekBar) {
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
value = i;
listener.onStateChanged(value);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}
// Да, кнопкой повернуть колеса можно. Но лучше использовать seekbar, а метод initButton отсюда лучше убрать вовсе.
@SuppressLint("ClickableViewAccessibility")
@Override
public void initButton(Button button) {
button.setOnTouchListener((View.OnTouchListener) (v, event) -> {
if(event.getAction() == MotionEvent.ACTION_UP){
value = 0.0f;
listener.onStateChanged(value);
return true;
}
if (event.getAction() == MotionEvent.ACTION_DOWN){
value = 1.0f;
listener.onStateChanged(value);
return true;
}
return false;
});
}
@Override
public void initImageView(ImageView imageView) {
}
}
public class GearBox extends UIElement{
public GearBox(Button button, SeekBar seekBar, ImageView imageView, IUIElementValueListener listener) {
super(button, seekBar, imageView, listener);
}
@Override
public void initSeekbar(SeekBar seekBar) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
seekBar.setMin(0);
}
seekBar.setMax(2);
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
value = i;
listener.onStateChanged(value);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}
@Override
public void initButton(Button button) {
button.setOnClickListener(view -> {
old_button_state = !old_button_state;
value = old_button_state ? 1.0f : 0.0f;
listener.onStateChanged(value);
});
}
@Override
public void initImageView(ImageView imageView) {
imageView.setOnClickListener(view -> {
old_button_state = !old_button_state;
value = old_button_state ? 1.0f : 0.0f;
listener.onStateChanged(value);
});
}
}
Ответы (1 шт):
Можно в абстрактном классе использовать общий предок (View), в имплементациях приводить к нужному конкретному типу (каждый наследник UIElement у вас ведь будет работать с одним, заранее известным типом виджета, как я понял).
Ещё лучше использовать дженерики - это позволит избавиться от кастов и связанных с этим ошибок в рантайме:
public abstract class UIElement<T extends View> {
protected float value;
protected boolean old_button_state;
T view;
IUIElementValueListener listener;
public UIElement(T view, IUIElementValueListener listener){
this.listener = listener;
init(view);
}
public abstract void init(T view);
public float getValue(){
return this.value;
}
}
public class Steering extends UIElement<SeekBar> {
public Steering(SeekBar seekBar, IUIElementValueListener listener) {
super(seekBar, listener);
}
@Override
public void init(SeekBar seekBar) {
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
value = i;
listener.onStateChanged(value);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}
}