Skip to content

Commit

Permalink
Updating Text drawing code to use an underlying TextView (#62)
Browse files Browse the repository at this point in the history
* use textview instead of paint
* added font_style attr to allow setting custom font
* added example for custom font
* added attr for setting text to all caps
* added example for text all caps
* Add Support for TextAppearance
* Updating README with new screenshots
* Fixed TOC link for text_appearance
  • Loading branch information
cortinico authored Mar 24, 2019
1 parent cbf380e commit 27b4601
Show file tree
Hide file tree
Showing 7 changed files with 102 additions and 21 deletions.
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ A simple *Slide to Unlock* **Material** widget for **Android**, written in [**Ko
* [``area_margin``](#area_margin)
* [``inner_color`` & ``outer_color``](#inner_color--outer_color)
* [``border_radius``](#border_radius)
* [``text``, ``text_size``, ``text_style``](#text-text_size-text_style)
* [``text``, ``text_size``, ``text_style``, ``text_appearance``](#text-text_size-text_style-text_appearance)
* [``slider_height``](#slider_height)
* [``slider_locked``](#slider_locked)
* [``slider_icon``](#slider_icon)
Expand Down Expand Up @@ -123,15 +123,18 @@ Use the ``border_radius`` attribute to control the **radius** of the **inner cir

<p align="center"><img src="assets/border_radius_1.png" alt="border_radius_1" width="40%"/> <img src="assets/border_radius_2.png" alt="border_radius_2" width="40%"/></p>

#### ``text``, ``text_size``, ``text_style``
#### ``text``, ``text_size``, ``text_style``, ``text_appearance``

Use the ``text`` attribute to control the **text of your slider**. If not set, this attribute defaults to **SlideToActView**.

Use the ``text_size`` attribute to control the **size** of the **text of your slider**. A ``text_size`` set to **0sp** will result in hiding the text. If not set, this attribute defaults to **16sp**.

Use the ``text_style`` attribute to control the **style** of your text. Accepted values are ``normal``, ``bold`` and ``italic``.

<p align="center"><img src="assets/text.png" alt="text" width="40%"/></p>
Use the ``text_appearance`` attribute to provide an Android `TextAppearance` style to fully customize your Text.
Please use this attribute if you want to use a **custom font** or set the text to be **all caps**.

<p align="center"><img src="assets/text.png" alt="slider_text" width="40%"/> <img src="assets/text_appearance.png" alt="slider_text_appearance" width="40%"/></p>

#### ``slider_height``

Expand Down
Binary file added assets/text_appearance.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
15 changes: 15 additions & 0 deletions example/src/main/res/layout/content_text_size.xml
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,20 @@
style="@style/SlideToActView.Example"
app:text_size="18sp"
app:text="TextSize 18sp" />

<com.ncorti.slidetoact.SlideToActView
style="@style/SlideToActView.Example"
app:text_appearance="@style/TextAppearanceAllCaps"
app:text="TextAppearance - All caps" />

<com.ncorti.slidetoact.SlideToActView
style="@style/SlideToActView.Example"
app:text_appearance="@style/TextAppearanceBlueShadow"
app:text="TextAppearance - Blue Shadow" />

<com.ncorti.slidetoact.SlideToActView
style="@style/SlideToActView.Example"
app:text_appearance="@style/TextAppearancaCustomFont"
app:text="Custom font" />
</LinearLayout>
</ScrollView>
20 changes: 20 additions & 0 deletions example/src/main/res/values/styles.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,24 @@
<item name="android:layout_margin">8dp</item>
</style>

<style name="TextAppearancaCustomFont">
<item name="android:fontFamily">@font/montserrat_extrabold</item>
<item name="android:textAllCaps">true</item>
<item name="android:capitalize">characters</item>
<item name="android:textColor">@color/colorPrimaryDark</item>
</style>

<style name="TextAppearanceAllCaps">
<item name="android:textAllCaps">true</item>
</style>

<style name="TextAppearanceBlueShadow">
<item name="android:textStyle">italic|bold</item>
<item name="android:textColor">@color/white</item>
<item name="android:shadowColor">@color/colorPrimaryDark</item>
<item name="android:shadowDx">5.0</item>
<item name="android:shadowDy">5.0</item>
<item name="android:shadowRadius">5.0</item>
</style>

</resources>
78 changes: 60 additions & 18 deletions slidetoact/src/main/java/com/ncorti/slidetoact/SlideToActView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import android.support.annotation.RequiresApi
import android.support.graphics.drawable.AnimatedVectorDrawableCompat
import android.support.graphics.drawable.VectorDrawableCompat
import android.support.v4.content.ContextCompat
import android.support.v4.graphics.ColorUtils
import android.support.v4.widget.TextViewCompat
import android.util.AttributeSet
import android.util.TypedValue
import android.util.Xml
Expand All @@ -22,6 +24,7 @@ import android.view.View
import android.view.ViewOutlineProvider
import android.view.animation.AnticipateOvershootInterpolator
import android.view.animation.OvershootInterpolator
import android.widget.TextView
import org.xmlpull.v1.XmlPullParser
import org.xmlpull.v1.XmlPullParserException

Expand Down Expand Up @@ -62,22 +65,30 @@ class SlideToActView @JvmOverloads constructor (
var text: CharSequence = ""
set(value) {
field = value
mTextView.text = value
mTextPaint.set(mTextView.paint)
invalidate()
}

/** Typeface for the text field */
var typeFace = Typeface.NORMAL
set(value) {
field = value
mTextPaint.typeface = Typeface.create("sans-serif-light" , value)
mTextView.typeface = Typeface.create("sans-serif-light" , value)
mTextPaint.set(mTextView.paint)
invalidate()
}

/** Size for the text message */
private val mTextSize: Int

private var mTextYPosition = -1f
private var mTextXPosition = -1f
/** Text Appearance used to fully customize the font */
var textAppearance : Int = 0
set(value) {
field = value
if (value != 0) {
TextViewCompat.setTextAppearance(mTextView, value)
mTextPaint.set(mTextView.paint)
mTextPaint.color = mTextView.currentTextColor
}
}

/** Outer color used by the slider (primary) */
var outerColor: Int = 0
Expand All @@ -99,7 +110,8 @@ class SlideToActView @JvmOverloads constructor (
var textColor: Int = 0
set(value) {
field = value
mTextPaint.color = value
mTextView.setTextColor(value)
mTextPaint.color = textColor
invalidate()
}

Expand All @@ -116,6 +128,19 @@ class SlideToActView @JvmOverloads constructor (
mPositionPerc = value.toFloat() / (mAreaWidth - mAreaHeight).toFloat()
mPositionPercInv = 1 - value.toFloat() / (mAreaWidth - mAreaHeight).toFloat()
}

/** Positioning of text */
private var mTextYPosition = -1f
private var mTextXPosition = -1f

/** Private size for the text message */
private var mTextSize: Int = 0
set(value) {
field = value
mTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTextSize.toFloat())
mTextPaint.set(mTextView.paint)
}

/** Slider cursor position in percentage (between 0f and 1f) */
private var mPositionPerc: Float = 0f
/** 1/mPositionPerc */
Expand Down Expand Up @@ -149,7 +174,10 @@ class SlideToActView @JvmOverloads constructor (
private val mInnerPaint: Paint = Paint(Paint.ANTI_ALIAS_FLAG)

/** Paint used for text elements */
private val mTextPaint: Paint = Paint(Paint.ANTI_ALIAS_FLAG)
private var mTextPaint: Paint = Paint(Paint.ANTI_ALIAS_FLAG)

/** TextView used for text elements */
private var mTextView: TextView

/** Inner rectangle (used for arrow rotation) */
private var mInnerRect: RectF
Expand Down Expand Up @@ -186,6 +214,9 @@ class SlideToActView @JvmOverloads constructor (
val actualInnerColor : Int
val actualTextColor : Int

mTextView = TextView(context)
mTextPaint = mTextView.paint

val layoutAttrs: TypedArray = context.theme.obtainStyledAttributes(attrs,
R.styleable.SlideToActView, defStyleAttr, R.style.SlideToActView)
try {
Expand All @@ -200,16 +231,29 @@ class SlideToActView @JvmOverloads constructor (

actualOuterColor = layoutAttrs.getColor(R.styleable.SlideToActView_outer_color, defaultOuter)
actualInnerColor = layoutAttrs.getColor(R.styleable.SlideToActView_inner_color, defaultWhite)
actualTextColor = layoutAttrs.getColor(R.styleable.SlideToActView_text_color, defaultWhite)

// For text color, check if the `text_color` is set.
// if not check if the `outer_color` is set.
// if not, default to white.
actualTextColor = when {
layoutAttrs.hasValue(R.styleable.SlideToActView_text_color) ->
layoutAttrs.getColor(R.styleable.SlideToActView_text_color, defaultWhite)
layoutAttrs.hasValue(R.styleable.SlideToActView_inner_color) -> actualInnerColor
else -> defaultWhite
}

text = layoutAttrs.getString(R.styleable.SlideToActView_text)
typeFace = layoutAttrs.getInt(R.styleable.SlideToActView_text_style, 0)
mTextSize = layoutAttrs.getDimensionPixelSize(R.styleable.SlideToActView_text_size, resources.getDimensionPixelSize(R.dimen.default_text_size))
textColor = actualTextColor

// TextAppearance is the last as will have precedence over everything text related.
textAppearance = layoutAttrs.getResourceId(R.styleable.SlideToActView_text_appearance, 0)

isLocked = layoutAttrs.getBoolean(R.styleable.SlideToActView_slider_locked, false)
isRotateIcon = layoutAttrs.getBoolean(R.styleable.SlideToActView_rotate_icon, true)
isAnimateCompletion = layoutAttrs.getBoolean(R.styleable.SlideToActView_animate_completion, true)

mTextSize = layoutAttrs.getDimensionPixelSize(R.styleable.SlideToActView_text_size, resources.getDimensionPixelSize(R.dimen.default_text_size))
mOriginAreaMargin = layoutAttrs.getDimensionPixelSize(R.styleable.SlideToActView_area_margin, resources.getDimensionPixelSize(R.dimen.default_area_margin))
mActualAreaMargin = mOriginAreaMargin

Expand All @@ -234,11 +278,9 @@ class SlideToActView @JvmOverloads constructor (
}

mTextPaint.textAlign = Paint.Align.CENTER
mTextPaint.textSize = mTextSize.toFloat()

outerColor = actualOuterColor
innerColor = actualInnerColor
textColor = actualTextColor

mIconMargin = context.resources.getDimensionPixelSize(R.dimen.default_icon_margin)
mArrowMargin = mIconMargin
Expand Down Expand Up @@ -296,6 +338,12 @@ class SlideToActView @JvmOverloads constructor (
mOuterRect.set(mActualAreaWidth.toFloat(), 0f, mAreaWidth.toFloat() - mActualAreaWidth.toFloat(), mAreaHeight.toFloat())
canvas.drawRoundRect(mOuterRect, mBorderRadius.toFloat(), mBorderRadius.toFloat(), mOuterPaint)

// Text alpha
mTextPaint.alpha = (255 * mPositionPercInv).toInt()
// Checking if the TextView has a Transformation method applied (e.g. AllCaps).
val textToDraw = mTextView.transformationMethod?.getTransformation(text, mTextView) ?: text
canvas.drawText(textToDraw, 0, textToDraw.length, mTextXPosition, mTextYPosition, mTextPaint)

// Inner Cursor
// ratio is used to compute the proper border radius for the inner rect (see #8).
val ratio = (mAreaHeight - 2 * mActualAreaMargin).toFloat() / mAreaHeight.toFloat()
Expand All @@ -305,12 +353,6 @@ class SlideToActView @JvmOverloads constructor (
mAreaHeight.toFloat() - mActualAreaMargin.toFloat())
canvas.drawRoundRect(mInnerRect, mBorderRadius.toFloat() * ratio, mBorderRadius.toFloat() * ratio, mInnerPaint)

// Text alpha
mTextPaint.alpha = (255 * mPositionPercInv).toInt()

// Vertical + Horizontal centering
canvas.drawText(text.toString(), mTextXPosition, mTextYPosition, mTextPaint)

// Arrow angle
if (isRotateIcon) {
mArrowAngle = -180 * mPositionPerc
Expand Down
1 change: 1 addition & 0 deletions slidetoact/src/main/res/values/attrs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
<attr name="slider_icon" format="reference" />
<attr name="rotate_icon" format="boolean" />
<attr name="animate_completion" format="boolean" />
<attr name="text_appearance" format="reference" />
</declare-styleable>
<declare-styleable name="SlideToActViewTheme">
<attr name="slideToActViewStyle" format="reference"/>
Expand Down

0 comments on commit 27b4601

Please sign in to comment.