aboutsummaryrefslogtreecommitdiff
path: root/WordPress/src/main/java/org/wordpress/android/ui/WPNumberPicker.java
diff options
context:
space:
mode:
Diffstat (limited to 'WordPress/src/main/java/org/wordpress/android/ui/WPNumberPicker.java')
-rw-r--r--WordPress/src/main/java/org/wordpress/android/ui/WPNumberPicker.java261
1 files changed, 261 insertions, 0 deletions
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/WPNumberPicker.java b/WordPress/src/main/java/org/wordpress/android/ui/WPNumberPicker.java
new file mode 100644
index 000000000..0f2de5050
--- /dev/null
+++ b/WordPress/src/main/java/org/wordpress/android/ui/WPNumberPicker.java
@@ -0,0 +1,261 @@
+package org.wordpress.android.ui;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.EditText;
+import android.widget.NumberPicker;
+import android.widget.TextView;
+
+import org.wordpress.android.R;
+import org.wordpress.android.util.WPPrefUtils;
+
+import java.lang.reflect.Field;
+
+public class WPNumberPicker extends NumberPicker {
+ private static final String DIVIDER_FIELD = "mSelectionDivider";
+ private static final String INPUT_FIELD = "mInputText";
+ private static final String INDICES_FIELD = "mSelectorIndices";
+ private static final String CUR_OFFSET_FIELD = "mCurrentScrollOffset";
+ private static final String SELECTOR_HEIGHT_FIELD = "mSelectorElementHeight";
+ private static final String INITIAL_OFFSET_FIELD = "mInitialScrollOffset";
+ private static final String CURRENT_OFFSET_FIELD = "mCurrentScrollOffset";
+ private static final String PAINT_FIELD = "mSelectorWheelPaint";
+
+ private static final int DISPLAY_COUNT = 5;
+ private static final int MIDDLE_INDEX = 2;
+
+ private Field mOffsetField;
+ private Field mSelectorHeight;
+ private Field mSelectorIndices;
+ private Field mInitialOffset;
+ private Field mCurrentOffset;
+
+ private EditText mInputView;
+ private Formatter mFormatter;
+ private Paint mPaint;
+ private int[] mDisplayValues;
+
+ public WPNumberPicker(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ mDisplayValues = new int[DISPLAY_COUNT];
+ getFieldsViaReflection();
+ }
+
+ @Override
+ public void addView(View child, int index, android.view.ViewGroup.LayoutParams params) {
+ super.addView(child, index, params);
+ if (child instanceof TextView) {
+ WPPrefUtils.layoutAsNumberPickerPeek((TextView) child);
+ }
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ super.onLayout(changed, left, top, right, bottom);
+ updateIntitialOffset();
+ setVerticalFadingEdgeEnabled(false);
+ setHorizontalFadingEdgeEnabled(false);
+ WPPrefUtils.layoutAsNumberPickerSelected(mInputView);
+ mInputView.setVisibility(View.INVISIBLE);
+ }
+
+ @Override
+ public void setValue(int value) {
+ if (value < getMinValue()) value = getMinValue();
+ if (value > getMaxValue()) value = getMaxValue();
+ super.setValue(value);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ int[] selectorIndices = getIndices();
+ setIndices(new int[0]);
+ setIndices(selectorIndices);
+
+ // Draw the middle number with a different font
+ setDisplayValues();
+ float elementHeight = getSelectorElementHeight();
+ float x = ((getRight() - getLeft()) / 2.0f);
+ float y = getScrollOffset();
+ Paint paint = mInputView.getPaint();
+ paint.setTextAlign(Paint.Align.CENTER);
+ //noinspection deprecation
+ paint.setColor(getResources().getColor(R.color.blue_medium));
+ int alpha = isEnabled() ? 255 : 96;
+ paint.setAlpha(alpha);
+ mPaint.setAlpha(alpha);
+
+ int offset = getResources().getDimensionPixelSize(R.dimen.margin_medium);
+ // Draw the visible values
+ for (int i = 0; i < DISPLAY_COUNT; ++i) {
+ String scrollSelectorValue;
+ if (mFormatter != null) {
+ scrollSelectorValue = mFormatter.format(mDisplayValues[i]);
+ } else {
+ scrollSelectorValue = String.valueOf(mDisplayValues[i]);
+ }
+ if (i == MIDDLE_INDEX) {
+ canvas.drawText(scrollSelectorValue, x, y - ((paint.descent() + paint.ascent()) / 2) - offset, paint);
+ } else {
+ canvas.drawText(scrollSelectorValue, x, y - ((mPaint.descent() + mPaint.ascent()) / 2) - offset, mPaint);
+ }
+ y += elementHeight;
+ }
+ }
+
+ @Override
+ public void setFormatter(Formatter formatter) {
+ super.setFormatter(formatter);
+ mFormatter = formatter;
+ }
+
+ private void setDisplayValues() {
+ int value = getValue();
+ for (int i = 0; i < DISPLAY_COUNT; ++i) {
+ mDisplayValues[i] = value - MIDDLE_INDEX + i;
+ if (mDisplayValues[i] < getMinValue()) {
+ mDisplayValues[i] = getMaxValue() + (mDisplayValues[i] + 1 - getMinValue());
+ } else if (mDisplayValues[i] > getMaxValue()) {
+ mDisplayValues[i] = getMinValue() + (mDisplayValues[i] - getMaxValue() - 1);
+ }
+ }
+ }
+
+ private void setIndices(int[] indices) {
+ if (mSelectorIndices != null) {
+ try {
+ mSelectorIndices.set(this, indices);
+ } catch (IllegalArgumentException | IllegalAccessException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ private int[] getIndices() {
+ if (mSelectorIndices != null) {
+ try {
+ return (int[]) mSelectorIndices.get(this);
+ } catch (IllegalArgumentException | IllegalAccessException e) {
+ e.printStackTrace();
+ }
+ }
+
+ return null;
+ }
+
+ private int getScrollOffset() {
+ if (mOffsetField != null) {
+ try {
+ return (Integer) mOffsetField.get(this);
+ } catch (IllegalArgumentException | IllegalAccessException e) {
+ e.printStackTrace();
+ }
+ }
+
+ return 0;
+ }
+
+ private int getSelectorElementHeight() {
+ if (mSelectorHeight != null) {
+ try {
+ return (Integer) mSelectorHeight.get(this);
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ }
+ }
+
+ return 0;
+ }
+
+ private void updateIntitialOffset() {
+ if (mInitialOffset != null) {
+ try {
+ int offset = (Integer) mInitialOffset.get(this) - getSelectorElementHeight();
+ mInitialOffset.set(this, offset);
+ // Only do this once
+ mInitialOffset = null;
+
+ if (mCurrentOffset != null) {
+ mCurrentOffset.set(this, offset);
+ }
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * From https://www.snip2code.com/Snippet/67740/NumberPicker-with-transparent-selection-
+ */
+ private void removeDividers(Class<?> clazz) {
+ Field selectionDivider = getFieldAndSetAccessible(clazz, DIVIDER_FIELD);
+ if (selectionDivider != null) {
+ try {
+ selectionDivider.set(this, null);
+ } catch (IllegalArgumentException | IllegalAccessException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ private void getTextPaint(Class<?> clazz) {
+ Field paint = getFieldAndSetAccessible(clazz, PAINT_FIELD);
+ if (paint != null) {
+ try {
+ mPaint = (Paint) paint.get(this);
+ } catch (IllegalArgumentException | IllegalAccessException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ private void getInputField(Class<?> clazz) {
+ Field inputField = getFieldAndSetAccessible(clazz, INPUT_FIELD);
+ if (inputField != null) {
+ try {
+ mInputView = ((EditText) inputField.get(this));
+ } catch (IllegalArgumentException | IllegalAccessException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * Gets a class field using reflection and makes it accessible.
+ */
+ private Field getFieldAndSetAccessible(Class<?> clazz, String fieldName) {
+ Field field = null;
+ try {
+ field = clazz.getDeclaredField(fieldName);
+ field.setAccessible(true);
+ } catch (NoSuchFieldException e) {
+ e.printStackTrace();
+ }
+
+ return field;
+ }
+
+ private void getFieldsViaReflection() {
+ Class<?> numberPickerClass = null;
+ try {
+ numberPickerClass = Class.forName(NumberPicker.class.getName());
+ } catch (ClassNotFoundException e) {
+ e.printStackTrace();
+ }
+ if (numberPickerClass == null) return;
+
+ mSelectorHeight = getFieldAndSetAccessible(numberPickerClass, SELECTOR_HEIGHT_FIELD);
+ mOffsetField = getFieldAndSetAccessible(numberPickerClass, CUR_OFFSET_FIELD);
+ mSelectorIndices = getFieldAndSetAccessible(numberPickerClass, INDICES_FIELD);
+ mInitialOffset = getFieldAndSetAccessible(numberPickerClass, INITIAL_OFFSET_FIELD);
+ mCurrentOffset = getFieldAndSetAccessible(numberPickerClass, CURRENT_OFFSET_FIELD);
+
+ getTextPaint(numberPickerClass);
+ getInputField(numberPickerClass);
+ removeDividers(numberPickerClass);
+ setIndices(new int[DISPLAY_COUNT]);
+ }
+}