Skip to content

Commit

Permalink
Merge branch 'release/1.0.2'
Browse files Browse the repository at this point in the history
  • Loading branch information
aids61517 committed Aug 9, 2019
2 parents 7650a59 + b9bf9a5 commit 91827a6
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,23 @@ package com.aids61517.easyratingviewexample

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.aids61517.easyratingview.EasyRatingView
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

ratingContainer.apply {
EasyRatingView(this@MainActivity).apply {
emptyDrawableResourceId = R.drawable.ic_review_empty_small
fullDrawableResourceId = R.drawable.ic_review_full_small
rating = 3f
maxRating = 4f
spacing = 50
}.also { addView(it) }
}
}
}
15 changes: 10 additions & 5 deletions app/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,22 @@
android:id="@+id/ratingView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:paddingTop="10dp"
android:paddingBottom="30dp"
app:emptyDrawable="@drawable/ic_review_empty_small"
app:fullDrawable="@drawable/ic_review_full_small"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:maxRating="10"
app:numStars="5"
app:rating="2.8"
app:rating="6"
app:spacing="10dp"
app:step="0.5" />

<LinearLayout
android:id="@+id/ratingContainer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="40dp"
android:orientation="horizontal"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/ratingView" />
</androidx.constraintlayout.widget.ConstraintLayout>
Original file line number Diff line number Diff line change
Expand Up @@ -13,87 +13,145 @@ class EasyRatingView @JvmOverloads constructor(
attributeSet: AttributeSet? = null,
defStyleAttribute: Int
) : View(context, attributeSet, defStyleAttribute) {
constructor(context: Context, attrs: AttributeSet) : this(context, attrs, 0)
constructor(context: Context, attrs: AttributeSet? = null) : this(context, attrs, 0)

private lateinit var emptyDrawable: Drawable
private lateinit var fullDrawable: Drawable
var emptyDrawableResourceId: Int = 0
set(value) {
if (field != value) {
field = value
emptyDrawable = ContextCompat.getDrawable(context, value)!!
}
}

private val fullBitmapShader by lazy {
val srcBitmap = drawableToBitmap(fullDrawable)
BitmapShader(srcBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)
}
var emptyDrawable: Drawable? = null
set(value) {
field = value
invalidate()
requestLayout()
}

private val fullDrawablePaint by lazy {
Paint().apply {
isAntiAlias = true
shader = fullBitmapShader
var fullDrawableResourceId: Int = 0
set(value) {
if (field != value) {
field = value
fullDrawable = ContextCompat.getDrawable(context, value)!!
}
}
}

var rating: Float = 0f
var fullDrawable: Drawable? = null
set(value) {
field = if (value > numberStars) numberStars.toFloat() else value
field = value
value?.let {
val srcBitmap = drawableToBitmap(value)
fullBitmapShader =
BitmapShader(srcBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)
}
invalidate()
}

private val numberStars: Int
private val spacing: Int
private val step: Float
var rating: Float = 0f
set(value) {
if (field != value) {
field = value
invalidate()
}
}

var numberStars: Int = 5
set(value) {
if (field != value) {
field = value
invalidate()
requestLayout()
}
}

var spacing: Int = 0
set(value) {
if (field != value) {
field = value
invalidate()
requestLayout()
}
}

var step: Float = 0.5f
set(value) {
if (field != value) {
field = value
invalidate()
}
}

var maxRating: Float = 0f
set(value) {
if (field != value) {
field = value
invalidate()
}
}

private var fullBitmapShader: BitmapShader? = null
set(value) {
field = value
fullDrawablePaint = Paint().apply {
isAntiAlias = true
shader = fullBitmapShader
}
}

private var fullDrawablePaint: Paint? = null

init {
val typedArray = context.obtainStyledAttributes(attributeSet, R.styleable.EasyRatingView)
numberStars = typedArray.getInt(R.styleable.EasyRatingView_numStars, 5)
spacing = typedArray.getDimensionPixelSize(R.styleable.EasyRatingView_spacing, 0)
rating = typedArray.getFloat(R.styleable.EasyRatingView_rating, 0f)
step = typedArray.getFloat(R.styleable.EasyRatingView_step, 0.5f)
val fullDrawableId = typedArray.getResourceId(R.styleable.EasyRatingView_fullDrawable, 0)
val emptyDrawableId = typedArray.getResourceId(R.styleable.EasyRatingView_emptyDrawable, 0)
maxRating = typedArray.getFloat(R.styleable.EasyRatingView_maxRating, 0f)
fullDrawableResourceId = typedArray.getResourceId(R.styleable.EasyRatingView_fullDrawable, 0)
emptyDrawableResourceId = typedArray.getResourceId(R.styleable.EasyRatingView_emptyDrawable, 0)
typedArray.recycle()
if (fullDrawableId != 0) {
fullDrawable = ContextCompat.getDrawable(context, fullDrawableId)!!
}
if (emptyDrawableId != 0) {
emptyDrawable = ContextCompat.getDrawable(context, emptyDrawableId)!!
}
}

override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
if (::emptyDrawable.isInitialized.not() || numberStars == 0) {
if (emptyDrawable == null || numberStars == 0) {
setMeasuredDimension(0, 0)
return
}

val drawableWidth = emptyDrawable.intrinsicWidth
val drawableHeight = emptyDrawable.intrinsicHeight
val expectWidth = numberStars * drawableWidth + (numberStars - 1) * spacing + paddingStart + paddingEnd
val realWidth = resolveSizeAndState(expectWidth, widthMeasureSpec, 0)
val expectHeight = drawableHeight + paddingTop + paddingBottom
val realHeight = resolveSizeAndState(expectHeight, heightMeasureSpec, 0)
setMeasuredDimension(realWidth, realHeight)
emptyDrawable?.let {
val drawableWidth = it.intrinsicWidth
val drawableHeight = it.intrinsicHeight
val expectWidth =
numberStars * drawableWidth + (numberStars - 1) * spacing + paddingStart + paddingEnd
val realWidth = resolveSizeAndState(expectWidth, widthMeasureSpec, 0)
val expectHeight = drawableHeight + paddingTop + paddingBottom
val realHeight = resolveSizeAndState(expectHeight, heightMeasureSpec, 0)
setMeasuredDimension(realWidth, realHeight)
}
}

override fun onDraw(canvas: Canvas) {
if (::emptyDrawable.isInitialized.not() || numberStars == 0) {
if (emptyDrawable == null || numberStars == 0) {
return
}

val drawStartX = paddingStart
val drawStartY = paddingTop
emptyDrawable.apply {
val width = emptyDrawable.intrinsicWidth
val height = emptyDrawable.intrinsicHeight
emptyDrawable?.apply {
val width = intrinsicWidth
val height = intrinsicHeight
for (i in 0 until numberStars) {
val startX = i * (width + spacing) + drawStartX
setBounds(startX, drawStartY, startX + width, drawStartY + height)
draw(canvas)
}
}

if (::fullDrawable.isInitialized.not()) {
return
}

fullDrawable.apply {
fullDrawable?.apply {
val maxRating = if (maxRating != 0f) maxRating else numberStars.toFloat()
val rating = if (rating > maxRating) maxRating else (rating / maxRating) * numberStars
val finalRating = rating.getFinalRatingByStep(step)
val width = intrinsicWidth
val height = intrinsicHeight
Expand All @@ -114,7 +172,7 @@ class EasyRatingView @JvmOverloads constructor(
0f,
targetWidth,
height.toFloat(),
fullDrawablePaint
fullDrawablePaint!!
)
canvas.restore()
}
Expand Down
1 change: 1 addition & 0 deletions easyratingview/src/main/res/values/attrs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<attr name="numStars" format="integer"/>
<attr name="rating" format="float"/>
<attr name="step" format="float"/>
<attr name="maxRating" format="float"/>
<attr name="spacing" format="dimension"/>
<attr name="fullDrawable" format="reference"/>
<attr name="emptyDrawable" format="reference"/>
Expand Down

0 comments on commit 91827a6

Please sign in to comment.