Skip to content

Commit

Permalink
fix(spinner): Android spinner animation (#61)
Browse files Browse the repository at this point in the history
* fix(spinner): Android spinner animation

* clean up
  • Loading branch information
gusparis authored Dec 28, 2020
1 parent 9727fd6 commit 1a17082
Show file tree
Hide file tree
Showing 9 changed files with 117 additions and 40 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package com.gusparis.monthpicker;

import android.os.Build;

import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
Expand All @@ -14,7 +12,6 @@

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.fragment.app.FragmentActivity;

@ReactModule(name = RNMPickerModule.REACT_CLASS)
Expand All @@ -36,7 +33,6 @@ public String getName() {
}

@ReactMethod
@RequiresApi(api = Build.VERSION_CODES.O)
public void open(@Nullable ReadableMap options, Promise promise) {
FragmentActivity fragmentActivity = (FragmentActivity) getCurrentActivity();
assert fragmentActivity != null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public class RNDate {

RNDate(ReadableMap props, RNProps prop) {
now = Calendar.getInstance();
if (props.hasKey(prop.value()) && !props.isNull(prop.value())) {
if (props.hasKey(prop.value())) {
now.setTimeInMillis((long) props.getDouble(prop.value()));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,17 @@ public RNDate value() {

@Override
public RNDate minimumValue() {
if (props.isNull(MINIMUM_VALUE.value())) {
return null;
}
return new RNDate(props, MINIMUM_VALUE);
}

@Override
public RNDate maximumValue() {
if (props.isNull(MAXIMUM_VALUE.value())) {
return null;
}
return new RNDate(props, MAXIMUM_VALUE);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,45 +1,37 @@
package com.gusparis.monthpicker.builder;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.DateFormatSymbols;

class MonthNumberPicker extends MonthYearNumberPicker {

@Override
MonthNumberPicker onScrollListener(MonthYearScrollListener scrollListener) {
monthPicker.setOnScrollListener(scrollListener);
picker(monthPicker).setOnScrollListener(scrollListener);
picker(monthPicker).setOnValueChangedListener(scrollListener);
return this;
}

@Override
MonthNumberPicker build() {
DateFormatSymbols dfs = new DateFormatSymbols(props.locale());

monthPicker.setMinValue(0);
monthPicker.setMaxValue(11);
monthPicker.setFormatter(MonthFormatter.getMonthFormatter(props.mode(), dfs));
monthPicker.setWrapSelectorWheel(false);
monthPicker.setValue(props.value().getMonth());
picker(monthPicker).setMinValue(0);
picker(monthPicker).setMaxValue(11);
picker(monthPicker).setFormatter(MonthFormatter.getMonthFormatter(props.mode(), dfs));
picker(monthPicker).setWrapSelectorWheel(false);
picker(monthPicker).setValue(props.value().getMonth());
// Fix for Formatter blank initial rendering
try {
Method method = monthPicker.getClass().getDeclaredMethod("changeValueByOne", boolean.class);
method.setAccessible(true);
method.invoke(monthPicker, true);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
monthPicker.incrementByOne(true);
return this;
}

@Override
synchronized void setValue() {
int month = monthPicker.getValue();
int year = yearPicker.getValue();
if (monthPicker.getCounter() > 0) {
return;
}
int month = picker(monthPicker).getValue();
int year = picker(yearPicker).getValue();
int value = month;
if (props.minimumValue() != null &&
year == props.minimumValue().getYear() &&
Expand All @@ -50,11 +42,11 @@ synchronized void setValue() {
month > props.maximumValue().getMonth()) {
value = props.maximumValue().getMonth();
}
monthPicker.setValue(value);
monthPicker.run(value - month);
}

@Override
int getValue() {
return monthPicker.getValue();
return picker(monthPicker).getValue();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ abstract class MonthYearNumberPicker implements Observer {
private static final int MONTH_PICKER_ID = R.id.month_picker;
private static final int YEAR_PICKER_ID = R.id.year_picker;

NumberPicker monthPicker;
NumberPicker yearPicker;
protected Picker monthPicker;
protected Picker yearPicker;
RNMonthPickerProps props;

MonthYearNumberPicker view(View view) {
this.monthPicker = view.findViewById(MONTH_PICKER_ID);
this.yearPicker = view.findViewById(YEAR_PICKER_ID);
this.monthPicker = new Picker(view.findViewById(MONTH_PICKER_ID));
this.yearPicker = new Picker(view.findViewById(YEAR_PICKER_ID));
return this;
}

Expand All @@ -29,6 +29,10 @@ MonthYearNumberPicker props(RNMonthPickerProps props) {
return this;
}

protected NumberPicker picker(Picker picker) {
return picker.getPicker();
}

@Override
public void update(Observable o, Object arg) {
setValue();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,27 @@

import android.widget.NumberPicker;
import android.widget.NumberPicker.OnScrollListener;
import android.widget.NumberPicker.OnValueChangeListener;

import java.util.Observable;

class MonthYearScrollListener extends Observable implements OnScrollListener {
class MonthYearScrollListener extends Observable implements OnScrollListener, OnValueChangeListener {
private int currentScrollState;

@Override
public void onScrollStateChange(NumberPicker view, int scrollState) {
currentScrollState = scrollState;
if (scrollState == SCROLL_STATE_IDLE) {
setChanged();
notifyObservers(view);
}
}

@Override
public void onValueChange(NumberPicker view, int i, int i1) {
if (currentScrollState == SCROLL_STATE_IDLE) {
setChanged();
notifyObservers(view);
}
}
}
63 changes: 63 additions & 0 deletions android/src/main/java/com/gusparis/monthpicker/builder/Picker.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package com.gusparis.monthpicker.builder;

import android.os.Handler;
import android.view.View;
import android.widget.NumberPicker;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

class Picker {
private NumberPicker picker;
private int counter = 0;
private int incrementValue;
private boolean isIncrement;

private final Handler handler = new Handler();
private final Runnable runnable = new Runnable() {
@Override
public void run() {
startScrolling();
}
};

Picker(View view) {
this.picker = (NumberPicker) view;
}

public int getCounter() {
return this.counter;
}

public NumberPicker getPicker() {
return this.picker;
}

void run(int incrementValue) {
this.isIncrement = incrementValue >= 0;
this.incrementValue = incrementValue >= 0 ? incrementValue : -incrementValue;
handler.postDelayed(runnable, 80);
}

public void incrementByOne(boolean increment) {
try {
final Method method = picker.getClass().getDeclaredMethod("changeValueByOne", boolean.class);
method.setAccessible(true);
method.invoke(picker, increment);

} catch (final NoSuchMethodException | InvocationTargetException |
IllegalAccessException | IllegalArgumentException e) {
e.printStackTrace();
}
}

private void startScrolling() {
++counter;
if (counter > incrementValue) {
counter = 0;
return;
}
incrementByOne(isIncrement);
handler.postDelayed(runnable, 80);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,33 +6,37 @@ class YearNumberPicker extends MonthYearNumberPicker {

@Override
YearNumberPicker onScrollListener(MonthYearScrollListener scrollListener) {
yearPicker.setOnScrollListener(scrollListener);
picker(yearPicker).setOnScrollListener(scrollListener);
picker(yearPicker).setOnValueChangedListener(scrollListener);
return this;
}

@Override
YearNumberPicker build() {
int year = props.value().getYear();
yearPicker.setMinValue(year - DEFAULT_SIZE);
yearPicker.setMaxValue(year + DEFAULT_SIZE);
yearPicker.setValue(year);
picker(yearPicker).setMinValue(year - DEFAULT_SIZE);
picker(yearPicker).setMaxValue(year + DEFAULT_SIZE);
picker(yearPicker).setValue(year);
return this;
}

@Override
synchronized void setValue() {
int year = yearPicker.getValue();
if (yearPicker.getCounter() > 0) {
return;
}
int year = picker(yearPicker).getValue();
int value = year;
if (props.minimumValue() != null && year < props.minimumValue().getYear()) {
value = props.minimumValue().getYear();
} else if (props.maximumValue() != null && year > props.maximumValue().getYear()) {
value = props.maximumValue().getYear();
}
yearPicker.setValue(value);
yearPicker.run(value - year);
}

@Override
int getValue() {
return yearPicker.getValue();
return picker(yearPicker).getValue();
}
}
1 change: 1 addition & 0 deletions example/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ const App = () => {
onChange={onValueChange}
value={date}
minimumDate={new Date()}
maximumDate={new Date(2022, 5)}
locale="en"
mode="full"
/>
Expand Down

0 comments on commit 1a17082

Please sign in to comment.