Skip to content
This repository was archived by the owner on Jul 16, 2025. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions library/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ android {

dependencies {
compile 'com.nineoldandroids:library:2.4.0'
compile 'com.android.support:appcompat-v7:23.1.1'
compile 'com.android.support:recyclerview-v7:23.1.1'
compile 'com.android.support:appcompat-v7:23.2.0'
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't include build.gradle dependencies updates

compile 'com.android.support:recyclerview-v7:23.2.0'
}

apply from: '../maven_push.gradle'
Expand Down
124 changes: 95 additions & 29 deletions library/src/main/java/fr/ganfra/materialspinner/MaterialSpinner.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@
import android.graphics.Point;
import android.graphics.Typeface;
import android.os.Build;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.AppCompatSpinner;
import android.text.Layout;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
Expand Down Expand Up @@ -99,7 +101,9 @@ public class MaterialSpinner extends AppCompatSpinner implements ValueAnimator.A
private float arrowSize;
private boolean enableErrorLabel;
private boolean enableFloatingLabel;
private boolean isRtl;
private boolean rtlFloatingLabel;
private boolean rtlError;
private boolean rtlText;

private HintAdapter hintAdapter;

Expand Down Expand Up @@ -151,14 +155,15 @@ private void initAttributes(Context context, AttributeSet attrs) {
TypedArray defaultArray = context.obtainStyledAttributes(new int[]{R.attr.colorControlNormal, R.attr.colorAccent});
int defaultBaseColor = defaultArray.getColor(0, 0);
int defaultHighlightColor = defaultArray.getColor(1, 0);
int defaultErrorColor = context.getResources().getColor(R.color.error_color);
int defaultErrorColor = ContextCompat.getColor(context, R.color.error_color);
int defaultDisabledColor = ContextCompat.getColor(context, R.color.disabled_color);
defaultArray.recycle();

TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.MaterialSpinner);
baseColor = array.getColor(R.styleable.MaterialSpinner_ms_baseColor, defaultBaseColor);
highlightColor = array.getColor(R.styleable.MaterialSpinner_ms_highlightColor, defaultHighlightColor);
errorColor = array.getColor(R.styleable.MaterialSpinner_ms_errorColor, defaultErrorColor);
disabledColor = context.getResources().getColor(R.color.disabled_color);
disabledColor = array.getColor(R.styleable.MaterialSpinner_ms_disabledColor, defaultDisabledColor);
error = array.getString(R.styleable.MaterialSpinner_ms_error);
hint = array.getString(R.styleable.MaterialSpinner_ms_hint);
hintColor = array.getColor(R.styleable.MaterialSpinner_ms_hintColor, baseColor);
Expand All @@ -173,7 +178,9 @@ private void initAttributes(Context context, AttributeSet attrs) {
arrowSize = array.getDimension(R.styleable.MaterialSpinner_ms_arrowSize, dpToPx(DEFAULT_ARROW_WIDTH_DP));
enableErrorLabel = array.getBoolean(R.styleable.MaterialSpinner_ms_enableErrorLabel, true);
enableFloatingLabel = array.getBoolean(R.styleable.MaterialSpinner_ms_enableFloatingLabel, true);
isRtl = array.getBoolean(R.styleable.MaterialSpinner_ms_isRtl, false);
rtlFloatingLabel = array.getBoolean(R.styleable.MaterialSpinner_ms_rtlFloatingLabel, false);
rtlError = array.getBoolean(R.styleable.MaterialSpinner_ms_rtlError, false);
rtlText = array.getBoolean(R.styleable.MaterialSpinner_ms_rtlText, false);

String typefacePath = array.getString(R.styleable.MaterialSpinner_ms_typeface);
if (typefacePath != null) {
Expand Down Expand Up @@ -298,17 +305,16 @@ private void hideFloatingLabel() {
}

private void startErrorScrollingAnimator() {

int textWidth = Math.round(textPaint.measureText(error.toString()));
if (errorLabelAnimator == null) {
errorLabelAnimator = ObjectAnimator.ofInt(this, "errorLabelPosX", 0, textWidth + getWidth() / 2);
errorLabelAnimator = ObjectAnimator.ofInt(this, "errorLabelPosX", getErrorAnimationValues(textWidth));
errorLabelAnimator.setStartDelay(1000);
errorLabelAnimator.setInterpolator(new LinearInterpolator());
errorLabelAnimator.setDuration(150 * error.length());
errorLabelAnimator.addUpdateListener(this);
errorLabelAnimator.setRepeatCount(ValueAnimator.INFINITE);
} else {
errorLabelAnimator.setIntValues(0, textWidth + getWidth() / 2);
errorLabelAnimator.setIntValues(getErrorAnimationValues(textWidth));
}
errorLabelAnimator.start();
}
Expand Down Expand Up @@ -408,11 +414,11 @@ protected void onDraw(Canvas canvas) {

} else {
//scrolling
canvas.drawText(error.toString(), startX + rightLeftSpinnerPadding - errorLabelPosX, startYErrorLabel, textPaint);
canvas.drawText(error.toString(), getErrorStartX(error.toString()), startYErrorLabel, textPaint);
if (errorLabelPosX > 0) {
canvas.save();
canvas.translate(textPaint.measureText(error.toString()) + getWidth() / 2, 0);
canvas.drawText(error.toString(), startX + rightLeftSpinnerPadding - errorLabelPosX, startYErrorLabel, textPaint);
canvas.drawText(error.toString(), getErrorStartX(error.toString()), startYErrorLabel, textPaint);
canvas.restore();
}
}
Expand Down Expand Up @@ -440,14 +446,10 @@ protected void onDraw(Canvas canvas) {
textPaint.setAlpha((int) ((0.8 * floatingLabelPercent + 0.2) * baseAlpha * floatingLabelPercent));
}
String textToDraw = floatingLabelText != null ? floatingLabelText.toString() : hint.toString();
if (isRtl) {
canvas.drawText(textToDraw, getWidth() - rightLeftSpinnerPadding - textPaint.measureText(textToDraw), startYFloatingLabel, textPaint);
} else {
canvas.drawText(textToDraw, startX + rightLeftSpinnerPadding, startYFloatingLabel, textPaint);
}
canvas.drawText(textToDraw, getFloatingLabelStartX(textToDraw), startYFloatingLabel, textPaint);
}

drawSelector(canvas, getWidth() - rightLeftSpinnerPadding, getPaddingTop() + dpToPx(8));
drawSelector(canvas, getArrowStartX(), getPaddingTop() + dpToPx(8));


}
Expand All @@ -464,8 +466,8 @@ private void drawSelector(Canvas canvas, int posX, int posY) {
Point point3 = selectorPoints[2];

point1.set(posX, posY);
point2.set((int) (posX - (arrowSize)), posY);
point3.set((int) (posX - (arrowSize / 2)), (int) (posY + (arrowSize / 2)));
point2.set(getArrowPositionX(posX, arrowSize), posY);
point3.set(getArrowPositionX(posX, (arrowSize / 2)), (int) (posY + (arrowSize / 2)));

selectorPath.reset();
selectorPath.moveTo(point1.x, point1.y);
Expand All @@ -475,6 +477,46 @@ private void drawSelector(Canvas canvas, int posX, int posY) {
canvas.drawPath(selectorPath, paint);
}

private int getFloatingLabelStartX(String text) {
if (isRtlFloatingLabel()) {
return (int) (getWidth() - rightLeftSpinnerPadding - textPaint.measureText(text));
} else {
return rightLeftSpinnerPadding;
}
}

private int getErrorStartX(String text) {
if (isRtlError()) {
return (int) (getWidth() - textPaint.measureText(text)) - errorLabelPosX;
} else {
return rightLeftSpinnerPadding - errorLabelPosX;
}
}

private int getArrowStartX() {
if (isRtlText()) {
return rightLeftSpinnerPadding;
} else {
return getWidth() - rightLeftSpinnerPadding;
}
}

private int getArrowPositionX(int posX, float arrowSize) {
if (isRtlText()) {
return (int) (posX + (arrowSize));
} else {
return (int) (posX - (arrowSize));
}
}

private int[] getErrorAnimationValues(int textWidth) {
if (isRtlError()) {
return new int[]{textWidth + getWidth() / 2, 0};
} else {
return new int[]{0, textWidth + getWidth() / 2};
}
}

/*
* **********************************************************************************
* LISTENER METHODS
Expand Down Expand Up @@ -646,14 +688,29 @@ public CharSequence getError() {
return this.error;
}

public void setRtl() {
isRtl = true;
invalidate();
}
public boolean isRtlFloatingLabel() {
return rtlFloatingLabel;
}

public boolean isRtl() {
return isRtl;
}
public void setRtlFloatingLabel(boolean rtlFloatingLabel) {
this.rtlFloatingLabel = rtlFloatingLabel;
}

public boolean isRtlError() {
return rtlError;
}

public void setRtlError(boolean rtlError) {
this.rtlError = rtlError;
}

public boolean isRtlText() {
return rtlText;
}

public void setRtlText(boolean rtlText) {
this.rtlText = rtlText;
}

/**
* @deprecated {use @link #setPaddingSafe(int, int, int, int)} to keep internal computation OK
Expand Down Expand Up @@ -795,24 +852,33 @@ public View getDropDownView(int position, View convertView, ViewGroup parent) {

private View buildView(int position, View convertView, ViewGroup parent, boolean isDropDownView) {
if (getItemViewType(position) == HINT_TYPE) {
return getHintView(convertView, parent, isDropDownView);
return getHintView(parent, isDropDownView);
}
//workaround to have multiple types in spinner
if (convertView != null) {
convertView = (convertView.getTag() != null && convertView.getTag() instanceof Integer && (Integer) convertView.getTag() != HINT_TYPE) ? convertView : null;
}
position = hint != null ? position - 1 : position;
return isDropDownView ? mSpinnerAdapter.getDropDownView(position, convertView, parent) : mSpinnerAdapter.getView(position, convertView, parent);
View view = isDropDownView ? mSpinnerAdapter.getDropDownView(position, convertView, parent) : mSpinnerAdapter.getView(position, convertView, parent);

if (isRtlText() && view instanceof TextView) {
((TextView) view).setGravity(Gravity.RIGHT);
}

return view;
}

private View getHintView(final View convertView, final ViewGroup parent, final boolean isDropDownView) {
private View getHintView(final ViewGroup parent, final boolean isDropDownView) {

final LayoutInflater inflater = LayoutInflater.from(mContext);
final int resid = isDropDownView ? android.R.layout.simple_spinner_dropdown_item : android.R.layout.simple_spinner_item;
final TextView textView = (TextView) inflater.inflate(resid, parent, false);
final int resId = isDropDownView ? android.R.layout.simple_spinner_dropdown_item : android.R.layout.simple_spinner_item;
final TextView textView = (TextView) inflater.inflate(resId, parent, false);
textView.setText(hint);
textView.setTextColor(MaterialSpinner.this.isEnabled() ? hintColor : disabledColor);
textView.setTag(HINT_TYPE);
if (isRtlText()) {
textView.setGravity(Gravity.RIGHT);
}
return textView;
}

Expand Down
12 changes: 7 additions & 5 deletions library/src/main/res/values/attrs.xml
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="MaterialSpinner">
<attr name="ms_baseColor" format="integer"/>
<attr name="ms_highlightColor" format="integer"/>
<attr name="ms_errorColor" format="integer"/>
<attr name="ms_baseColor" format="color"/>
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change does not have to do with the PR

<attr name="ms_highlightColor" format="color"/>
<attr name="ms_errorColor" format="color"/>
<attr name="ms_disabledColor" format="color"/>
<attr name="ms_error" format="string"/>
<attr name="ms_hint" format="string"/>
<attr name="ms_hintColor" format="color"/>
Expand All @@ -19,7 +20,8 @@
<attr name="ms_arrowColor" format="color"/>
<attr name="ms_enableFloatingLabel" format="boolean"/>
<attr name="ms_enableErrorLabel" format="boolean"/>
<attr name="ms_isRtl" format="boolean"/>

<attr name="ms_rtlFloatingLabel" format="boolean"/>
<attr name="ms_rtlError" format="boolean"/>
<attr name="ms_rtlText" format="boolean"/>
</declare-styleable>
</resources>
2 changes: 1 addition & 1 deletion sample/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ android {

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:23.1.1'
compile 'com.android.support:appcompat-v7:23.2.0'
compile project(':library')

}