Guest User

Untitled

a guest
Dec 16th, 2017
72
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.14 KB | None | 0 0
  1. package es.cityride.mantapp
  2.  
  3. import android.content.Context
  4. import android.graphics.PorterDuff
  5. import android.graphics.drawable.Drawable
  6. import android.support.design.widget.TabLayout
  7. import android.util.AttributeSet
  8. import android.util.SparseArray
  9. import android.view.LayoutInflater
  10. import android.view.View
  11. import android.widget.ImageView
  12. import android.widget.TextView
  13. /**
  14. * Use:
  15. * tabLayout.with(tabPosition).badge(true).badgeCount(badgeCount).icon(R.drawable.ic_local_shipping_24dp).build()
  16. */
  17.  
  18. class BadgeTabLayout : TabLayout {
  19. private val mTabBuilders = SparseArray<Builder>()
  20.  
  21. constructor(context: Context) : super(context) {}
  22.  
  23. constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {}
  24.  
  25. constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {}
  26.  
  27. fun with(position: Int): Builder {
  28. val tab = getTabAt(position)
  29. return with(tab)
  30. }
  31.  
  32. /**
  33. * Apply a builder for this tab.
  34. *
  35. * @param tab for which we create a new builder or retrieve its builder if existed.
  36. * @return the required Builder.
  37. */
  38. fun with(tab: TabLayout.Tab?): Builder {
  39. if (tab == null) {
  40. throw IllegalArgumentException("Tab must not be null")
  41. }
  42.  
  43. var builder: Builder? = mTabBuilders.get(tab.position)
  44. if (builder == null) {
  45. builder = Builder(this, tab)
  46. mTabBuilders.put(tab.position, builder)
  47. }
  48.  
  49. return builder
  50. }
  51.  
  52. class Builder
  53. /**
  54. * This construct take a TabLayout parent to have its context and other attributes sets. And
  55. * the tab whose icon will be updated.
  56. *
  57. * @param parent
  58. * @param tab
  59. */
  60. (parent: TabLayout, private val mTab: TabLayout.Tab) {
  61.  
  62. private val mView: View?
  63. private val mContext: Context = parent.context
  64. private var mBadgeTextView: TextView? = null
  65. private var mIconView: ImageView? = null
  66. private var mIconDrawable: Drawable? = null
  67. private var mIconColorFilter: Int? = null
  68. private var mBadgeCount = Integer.MIN_VALUE
  69. private var mHasBadge = false
  70.  
  71. init {
  72. // initialize current tab's custom view.
  73. if (mTab.customView != null) {
  74. this.mView = mTab.customView
  75. } else {
  76. this.mView = LayoutInflater.from(parent.context)
  77. .inflate(R.layout.tab_custom_icon, parent, false)
  78. }
  79.  
  80. if (mView != null) {
  81. this.mIconView = mView.findViewById<View>(R.id.tab_icon) as ImageView
  82. this.mBadgeTextView = mView.findViewById<View>(R.id.tab_badge) as TextView
  83. }
  84.  
  85. if (this.mBadgeTextView != null) {
  86. this.mHasBadge = mBadgeTextView!!.visibility == View.VISIBLE
  87. try {
  88. this.mBadgeCount = Integer.parseInt(mBadgeTextView!!.text.toString())
  89. } catch (er: NumberFormatException) {
  90. er.printStackTrace()
  91. this.mBadgeCount = INVALID_NUMBER
  92. }
  93.  
  94. }
  95.  
  96. if (this.mIconView != null) {
  97. mIconDrawable = mIconView!!.drawable
  98. }
  99. }
  100.  
  101.  
  102. fun imageContentDescription(contentDescription: String): Builder {
  103. mIconView?.contentDescription = contentDescription
  104. return this
  105. }
  106.  
  107. /**
  108. * The related Tab is about to have a badge
  109. *
  110. * @return this builder
  111. */
  112. fun hasBadge(): Builder {
  113. mHasBadge = true
  114. return this
  115. }
  116.  
  117. /**
  118. * The related Tab is not about to have a badge
  119. *
  120. * @return this builder
  121. */
  122. fun noBadge(): Builder {
  123. mHasBadge = false
  124. return this
  125. }
  126.  
  127. /**
  128. * Dynamically set the availability of tab's badge
  129. *
  130. * @param hasBadge
  131. * @return this builder
  132. */
  133. // This method is used for DEBUG purpose only
  134. /*hide*/
  135. fun badge(hasBadge: Boolean): Builder {
  136. mHasBadge = hasBadge
  137. return this
  138. }
  139.  
  140. /**
  141. * Set icon custom drawable by Resource ID;
  142. *
  143. * @param drawableRes
  144. * @return this builder
  145. */
  146. fun icon(drawableRes: Int): Builder {
  147. mIconDrawable = getDrawableCompat(mContext, drawableRes)
  148. return this
  149. }
  150.  
  151. /**
  152. * Set icon custom drawable by Drawable Object
  153. *
  154. * @param drawable
  155. * @return this builder
  156. */
  157. fun icon(drawable: Drawable?): Builder {
  158. mIconDrawable = drawable
  159. return this
  160. }
  161.  
  162. /**
  163. * Set drawable color. Use this when user wants to change drawable's color filter
  164. *
  165. * @param color
  166. * @return this builder
  167. */
  168. fun iconColor(color: Int?): Builder {
  169. mIconColorFilter = color
  170. return this
  171. }
  172.  
  173. /**
  174. * increase current badge by 1
  175. *
  176. * @return this builder
  177. */
  178. fun increase(): Builder {
  179. mBadgeCount = if (mBadgeTextView == null)
  180. INVALID_NUMBER
  181. else
  182. Integer.parseInt(mBadgeTextView!!.text.toString()) + 1
  183. return this
  184. }
  185.  
  186. /**
  187. * decrease current badge by 1
  188. *
  189. * @return
  190. */
  191. fun decrease(): Builder {
  192. mBadgeCount = if (mBadgeTextView == null)
  193. INVALID_NUMBER
  194. else
  195. Integer.parseInt(mBadgeTextView!!.text.toString()) - 1
  196. return this
  197. }
  198.  
  199. /**
  200. * set badge count
  201. *
  202. * @param count expected badge number
  203. * @return this builder
  204. */
  205. public fun badgeCount(count: Int): Builder {
  206. mBadgeCount = count
  207. return this
  208. }
  209.  
  210. /**
  211. * Build the current Tab icon's custom view
  212. */
  213. fun build() {
  214. if (mView == null) {
  215. return
  216. }
  217.  
  218. // update badge counter
  219. if (mBadgeTextView != null) {
  220. mBadgeTextView!!.text = formatBadgeNumber(mBadgeCount)
  221.  
  222. if (mHasBadge) {
  223. mBadgeTextView!!.visibility = View.VISIBLE
  224. } else {
  225. // set to View#INVISIBLE to not screw up the layout
  226. mBadgeTextView!!.visibility = View.INVISIBLE
  227. }
  228. }
  229.  
  230. // update icon drawable
  231. if (mIconView != null && mIconDrawable != null) {
  232. mIconView!!.setImageDrawable(mIconDrawable!!.mutate())
  233. // be careful if you modify this. make sure your result matches your expectation.
  234. if (mIconColorFilter != null) {
  235. mIconDrawable!!.setColorFilter(mIconColorFilter!!, PorterDuff.Mode.MULTIPLY)
  236. }
  237. }
  238.  
  239. mTab.customView = mView
  240. }
  241.  
  242. companion object {
  243.  
  244. /**
  245. * This badge widget must not support this value.
  246. */
  247. private val INVALID_NUMBER = Integer.MIN_VALUE
  248. }
  249. }
  250.  
  251. companion object {
  252.  
  253. private fun getDrawableCompat(context: Context, drawableRes: Int): Drawable? {
  254. var drawable: Drawable? = null
  255. try {
  256. drawable = context.resources.getDrawable(drawableRes, context.theme)
  257. } catch (ex: NullPointerException) {
  258. ex.printStackTrace()
  259. }
  260.  
  261. return drawable
  262. }
  263.  
  264. /**
  265. * This format must follow User's badge policy.
  266. *
  267. * @param value of current badge
  268. * @return corresponding badge number. TextView need to be passed by a String/CharSequence
  269. */
  270. private fun formatBadgeNumber(value: Int): String {
  271. if (value < 0) {
  272. return "-" + formatBadgeNumber(-value)
  273. }
  274.  
  275. return if (value <= 10) {
  276. // equivalent to String#valueOf(int);
  277. Integer.toString(value)
  278. } else "10+"
  279.  
  280. // my own policy
  281. }
  282. }
  283. }
Add Comment
Please, Sign In to add comment