diff --git a/README.md b/README.md
index ecc7fac..87d4a90 100644
--- a/README.md
+++ b/README.md
@@ -12,10 +12,12 @@ Whatever you need to display some rating or pricing category - just use ProperRa
android:textSize="22sp"
android:textStyle="bold"
app:prb_defaultRating="4"
+ app:prb_minRating="1"
app:prb_symbolicTick="$"
app:prb_symbolicTickNormalColor="@android:color/darker_gray"
app:prb_symbolicTickSelectedColor="@android:color/holo_green_dark"
app:prb_totalTicks="5"
+ app:prb_tickAnimation="@anroid:anim/fade_in"
/>
```
@@ -44,7 +46,7 @@ Library's minSdkVersion is set to 14.
We use jitpack, so you can obtain made-up library right from our github sources in your module's `build.gradle` file:
-`compile 'com.github.techery:properratingbar:{version_name}'`
+`compile 'com.github.branpark:ProperRatingBar:0.0.6'`
Also you need to add jitpack as repository in the same file:
```groovy
@@ -59,7 +61,7 @@ So far we only support customising via xml layout.
Here is the list of applicable attributes:
+ ``prb_totalTicks``: total number of ticks to show. Default is '5'
+ ``prb_defaultRating``: use this to set rating from xml. Default is '3'
-+ ``prb_clickable``: if set to 'true' - use will be able to change rating by clicking. Default is 'false'
++ ``prb_minRating`` : use this to set minimum rating. Default is '0'
+ ``prb_symbolicTick``: symbol to be used as a tick. Default is '$'
+ ``android:textSize``: text size of symbolic tick. Default is '15sp'
@@ -70,12 +72,11 @@ Here is the list of applicable attributes:
+ ``prb_tickNormalDrawable``: drawable resource to use as a tick that is not selected (not rated). No default value
+ ``prb_tickSelectedDrawable``: drawable resource to use as a tick that is selected (rated). No default value
+ ``prb_tickSpacing``: margin to be applied to tick drawables. Only applies to drawable-type ticks. Default is '1dp' (gray)
++ ``prb_tickAnimation``: Animation to be applied to the tick view. No default value.
Also there's a number of methods to operate on ProperRatingBar programmatically:
```java
-public boolean isClickable();
-
/**
* Nifty sugar method to just toggle clickable to opposite state.
*/
@@ -112,6 +113,39 @@ public int getRating();
* @param rating new rating value
*/
public void setRating(int rating);
+
+/**
+* Set normal tick drawable
+* @param tickDrawable normal tick drawable
+*/
+public void setTickNormalDrawable(Drawable tickDrawable);
+
+/**
+* Set selected tick drawable
+* @param tickDrawable selected tick drawable
+*/
+public void setTickSelectedDrawable(Drawable tickDrawable);
+
+/**
+* Get normal tick drawable
+* @retrun normal tick drawable
+*/
+public Drawable getTickNormalDrawable();
+
+/**
+* Get selected tick drawable
+* @retrun selected tick drawable
+*/
+public Drawable setTickSelectedDrawable();
+
+/**
+* Animation resource id to be applied to the tick view.
+* @param animResId animation resource id
+*/
+public void setTickAnimationResId(int animResId);
+
+public int getTickAnimationResId();
+
```
## Tests
diff --git a/app/build.gradle b/app/build.gradle
index 7ba00d2..e43f4fb 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,8 +1,14 @@
apply plugin: 'com.android.application'
+allprojects {
+ repositories {
+ maven { url 'https://jitpack.io' }
+ }
+}
+
android {
compileSdkVersion 23
- buildToolsVersion "23.0.2"
+ buildToolsVersion '25.0.0'
defaultConfig {
applicationId "io.techery.properratingbar.sample"
diff --git a/app/src/main/res/anim/animation_scale_updown.xml b/app/src/main/res/anim/animation_scale_updown.xml
new file mode 100644
index 0000000..aed7dd7
--- /dev/null
+++ b/app/src/main/res/anim/animation_scale_updown.xml
@@ -0,0 +1,8 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/content_main.xml b/app/src/main/res/layout/content_main.xml
index 5e8f1b2..cf3aa1a 100644
--- a/app/src/main/res/layout/content_main.xml
+++ b/app/src/main/res/layout/content_main.xml
@@ -34,8 +34,7 @@
app:prb_symbolicTick="$"
app:prb_symbolicTickNormalColor="@android:color/darker_gray"
app:prb_symbolicTickSelectedColor="@android:color/holo_green_dark"
- app:prb_totalTicks="5"
- />
+ app:prb_totalTicks="5" />
-
-
-
+
+
+
+
+
@@ -52,7 +54,6 @@
-
diff --git a/library/src/io/techery/properratingbar/ProperRatingBar.java b/library/src/io/techery/properratingbar/ProperRatingBar.java
index 773730e..c66486b 100644
--- a/library/src/io/techery/properratingbar/ProperRatingBar.java
+++ b/library/src/io/techery/properratingbar/ProperRatingBar.java
@@ -9,7 +9,10 @@
import android.os.Parcelable;
import android.util.AttributeSet;
import android.util.TypedValue;
+import android.view.MotionEvent;
import android.view.View;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
@@ -45,8 +48,8 @@ of this software and associated documentation files (the "Software"), to deal
public class ProperRatingBar extends LinearLayout {
private static final int DF_TOTAL_TICKS = 5;
- private static final int DF_DEFAULT_TICKS = 3;
- private static final boolean DF_CLICKABLE = false;
+ private static final int DF_DEFAULT_RATING = 3;
+ private static final int DF_MIN_RATING = 0;
private static final int DF_SYMBOLIC_TICK_RES = R.string.prb_default_symbolic_string;
private static final int DF_SYMBOLIC_TEXT_SIZE_RES = R.dimen.prb_symbolic_tick_default_text_size;
private static final int DF_SYMBOLIC_TEXT_STYLE = Typeface.NORMAL;
@@ -56,7 +59,6 @@ public class ProperRatingBar extends LinearLayout {
private int totalTicks;
private int lastSelectedTickIndex;
- private boolean clickable;
private String symbolicTick;
private int customTextSize;
private int customTextStyle;
@@ -66,9 +68,11 @@ public class ProperRatingBar extends LinearLayout {
private Drawable tickSelectedDrawable;
private int tickSpacing;
- private boolean useSymbolicTick = false;
+ private boolean useSymbolicTick;
private int rating;
- private RatingListener listener = null;
+ private int minRating;
+ private int animResId;
+ private RatingListener listener;
public ProperRatingBar(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -79,9 +83,8 @@ private void init(Context context, AttributeSet attrs) {
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ProperRatingBar);
//
totalTicks = a.getInt(R.styleable.ProperRatingBar_prb_totalTicks, DF_TOTAL_TICKS);
- rating = a.getInt(R.styleable.ProperRatingBar_prb_defaultRating, DF_DEFAULT_TICKS);
- //
- clickable = a.getBoolean(R.styleable.ProperRatingBar_prb_clickable, DF_CLICKABLE);
+ rating = a.getInt(R.styleable.ProperRatingBar_prb_defaultRating, DF_DEFAULT_RATING);
+ minRating = a.getInt(R.styleable.ProperRatingBar_prb_minRating, DF_MIN_RATING);
//
symbolicTick = a.getString(R.styleable.ProperRatingBar_prb_symbolicTick);
if (symbolicTick == null) symbolicTick = context.getString(DF_SYMBOLIC_TICK_RES);
@@ -98,6 +101,9 @@ private void init(Context context, AttributeSet attrs) {
tickSelectedDrawable = a.getDrawable(R.styleable.ProperRatingBar_prb_tickSelectedDrawable);
tickSpacing = a.getDimensionPixelOffset(R.styleable.ProperRatingBar_prb_tickSpacing,
context.getResources().getDimensionPixelOffset(DF_TICK_SPACING_RES));
+
+ animResId = a.getResourceId(R.styleable.ProperRatingBar_prb_tickAnimation, 0);
+
//
afterInit();
//
@@ -118,56 +124,35 @@ private void afterInit() {
private void addTicks(Context context) {
this.removeAllViews();
for (int i = 0; i < totalTicks; i++) {
- addTick(context, i);
+ addTick(context);
}
redrawTicks();
}
- private void addTick(Context context, int position) {
+ private void addTick(Context context) {
if (useSymbolicTick) {
- addSymbolicTick(context, position);
+ addSymbolicTick(context);
} else {
- addDrawableTick(context, position);
+ addDrawableTick(context);
}
}
- private void addSymbolicTick(Context context, int position) {
+ private void addSymbolicTick(Context context) {
TextView tv = new TextView(context);
tv.setText(symbolicTick);
tv.setTextSize(TypedValue.COMPLEX_UNIT_PX, customTextSize);
if (customTextStyle != 0) {
tv.setTypeface(Typeface.DEFAULT, customTextStyle);
}
- updateTicksClickParameters(tv, position);
this.addView(tv);
}
- private void addDrawableTick(Context context, int position) {
+ private void addDrawableTick(Context context) {
ImageView iv = new ImageView(context);
iv.setPadding(tickSpacing, tickSpacing, tickSpacing, tickSpacing);
- updateTicksClickParameters(iv, position);
this.addView(iv);
}
- private void updateTicksClickParameters(View tick, int position) {
- if (clickable) {
- tick.setTag(R.id.prb_tick_tag_id, position);
- tick.setOnClickListener(mTickClickedListener);
- } else {
- tick.setOnClickListener(null);
- }
- }
-
- private View.OnClickListener mTickClickedListener = new OnClickListener() {
- @Override
- public void onClick(View v) {
- lastSelectedTickIndex = (int) v.getTag(R.id.prb_tick_tag_id);
- rating = lastSelectedTickIndex + 1;
- redrawTicks();
- if (listener != null) listener.onRatePicked(ProperRatingBar.this);
- }
- };
-
private void redrawTicks() {
iterateTicks(new TicksIterator() {
@Override
@@ -219,7 +204,6 @@ private interface TicksIterator {
public Parcelable onSaveInstanceState() {
SavedState savedState = new SavedState(super.onSaveInstanceState());
savedState.rating = rating;
- savedState.clickable = clickable;
return savedState;
}
@@ -240,7 +224,6 @@ public void onRestoreInstanceState(Parcelable state) {
static class SavedState extends BaseSavedState {
int rating;
- boolean clickable;
SavedState(Parcelable superState) {
super(superState);
@@ -249,14 +232,12 @@ static class SavedState extends BaseSavedState {
private SavedState(Parcel in) {
super(in);
this.rating = in.readInt();
- this.clickable = in.readByte() == 1;
}
@Override
public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
out.writeInt(this.rating);
- out.writeByte((byte) (this.clickable ? 1 : 0));
}
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
@@ -270,29 +251,66 @@ public SavedState[] newArray(int size) {
};
}
+ @Override
+ public boolean dispatchTouchEvent(MotionEvent event) {
+ if (!isClickable()) {
+ return super.dispatchTouchEvent(event);
+ }
+
+ int action = event.getAction();
+ if (action == MotionEvent.ACTION_MOVE || action == MotionEvent.ACTION_UP) {
+ int containerWidth = getWidth() - getPaddingLeft() - getPaddingRight();
+ float x = event.getX() - getPaddingLeft();
+ int oneTickWidth = containerWidth / totalTicks;
+ int r = (int)(Math.ceil(x / oneTickWidth));
+ if (rating != r) {
+ setRating(r);
+ return true;
+ }
+ }
+ return super.dispatchTouchEvent(event);
+ }
+
+ private Animation loadAnimation() {
+ if (animResId > 0) {
+ return AnimationUtils.loadAnimation(getContext(), animResId);
+ }
+ return null;
+ }
+
+ private void animateLastSelectedTick() {
+ Animation anim = loadAnimation();
+ if (anim == null) {
+ return ;
+ }
+ View tickView = getChildAt(lastSelectedTickIndex);
+ if (tickView != null) {
+ tickView.clearAnimation();
+ tickView.startAnimation(anim);
+ }
+ }
+
///////////////////////////////////////////////////////////////////////////
// Essential public methods
///////////////////////////////////////////////////////////////////////////
- public boolean isClickable() {
- return clickable;
- }
-
/**
* Nifty sugar method to just toggle clickable to opposite state.
*/
public void toggleClickable() {
- setClickable(!clickable);
+ setClickable(!isClickable());
}
- public void setClickable(boolean clickable) {
- this.clickable = clickable;
- iterateTicks(new TicksIterator() {
- @Override
- public void onTick(View tick, int position) {
- updateTicksClickParameters(tick, position);
- }
- });
+ /**
+ * Animation resource id to be applied to the tick view.
+ * @param animResId animation resource id
+ */
+ public void setTickAnimationResId(int animResId) {
+ this.animResId = animResId;
+ }
+
+ public int getTickAnimationResId() {
+ return animResId;
}
/**
@@ -332,13 +350,25 @@ public int getRating() {
/**
* Set the rating to show
- * @param rating new rating value
+ * @param value new rating value
*/
- public void setRating(int rating) {
- if (rating > this.totalTicks) rating = totalTicks;
- this.rating = rating;
- lastSelectedTickIndex = rating - 1;
- redrawTicks();
+ public void setRating(int value) {
+ int newRating = value;
+ if (newRating > this.totalTicks) {
+ newRating = totalTicks;
+ } else if (newRating < this.minRating) {
+ newRating = minRating;
+ }
+
+ if (this.rating != newRating) {
+ this.rating = newRating;
+ lastSelectedTickIndex = newRating - 1;
+ if (listener != null) {
+ listener.onRatePicked(this);
+ }
+ redrawTicks();
+ animateLastSelectedTick();
+ }
}
public void setSymbolicTick(String tick) {
@@ -349,4 +379,22 @@ public void setSymbolicTick(String tick) {
public String getSymbolicTick() {
return this.symbolicTick;
}
+
+ public void setTickNormalDrawable(Drawable tickDrawable) {
+ this.tickNormalDrawable = tickDrawable;
+ redrawTicks();
+ }
+
+ public void setTickSelectedDrawable(Drawable tickDrawable) {
+ this.tickSelectedDrawable = tickDrawable;
+ redrawTicks();
+ }
+
+ public Drawable getTickNormalDrawable() {
+ return tickNormalDrawable;
+ }
+
+ public Drawable setTickSelectedDrawable() {
+ return tickSelectedDrawable;
+ }
}