Last active
October 12, 2017 13:02
-
-
Save ar-g/98b21f6a6ad3935d3df38416cb1dcfc8 to your computer and use it in GitHub Desktop.
Custom flat view for performance sake
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package classifieds.yalla.features.ad.page.widget | |
import android.content.Context | |
import android.graphics.Canvas | |
import android.graphics.drawable.ShapeDrawable | |
import android.graphics.drawable.shapes.OvalShape | |
import android.support.v4.content.ContextCompat | |
import android.text.Layout | |
import android.text.TextUtils | |
import android.view.Gravity | |
import android.view.View | |
import android.view.ViewGroup | |
import android.widget.Button | |
import android.widget.ImageView | |
import classifieds.yalla.R | |
import classifieds.yalla.shared.utils.ViewUtils | |
import classifieds.yalla.shared.utils.ViewUtils.dpToPx | |
import classifieds.yalla.shared.utils.ViewUtils.spToPx | |
import com.facebook.fbui.textlayoutbuilder.TextLayoutBuilder | |
class PaidFeatureView(ctx: Context) : ViewGroup(ctx) { | |
private val extendFeatureBtn: Button | |
lateinit var featureIcon: ImageView | |
private var titleLayout: Layout? = null | |
private var statusLayout: Layout? = null | |
private var dateLayout: Layout? = null | |
private var title: String? = null | |
private var status: String? = null | |
private var date: String? = null | |
private var titleHeight: Int = 0 | |
private var statusHeight: Int = 0 | |
private var statusWidth: Int = 0 | |
private var dotWidth: Int = 0 | |
private val content0_25x: Int | |
private val content: Int | |
private val content2x: Int | |
private val whiteColor: Int | |
private var leftWithoutIcon: Int = 0 | |
private var titleTop: Int = 0 | |
private var statusTop: Int = 0 | |
private val titleTextLayoutBuilder: TextLayoutBuilder | |
private val statusTextLayoutBuilder: TextLayoutBuilder | |
private var dateTextLayoutBuilder: TextLayoutBuilder? = null | |
private var dotDrawable: ShapeDrawable? = null | |
private var centerTop: Int = 0 | |
init { | |
setWillNotDraw(false) | |
content0_25x = resources.getDimensionPixelSize(R.dimen.content0_25x) | |
content = resources.getDimensionPixelSize(R.dimen.content) | |
content2x = resources.getDimensionPixelSize(R.dimen.content2x) | |
whiteColor = ContextCompat.getColor(context, R.color.white) | |
extendFeatureBtn = Button(context) | |
extendFeatureBtn.setText(R.string.payment_extend) | |
extendFeatureBtn.textSize = 12f | |
extendFeatureBtn.setTextColor(whiteColor) | |
extendFeatureBtn.gravity = Gravity.CENTER | |
extendFeatureBtn.setPadding(0, 0, 0, 0) | |
extendFeatureBtn.layoutParams = MarginLayoutParams(dpToPx(resources, 90f), dpToPx(resources, 24f)) | |
ViewUtils.setBackground(extendFeatureBtn, ContextCompat.getDrawable(context, R.drawable.round_green_btn_selector)) | |
ViewUtils.setStateListAnimator(extendFeatureBtn, R.drawable.button_state_list_anim_material) | |
addView(extendFeatureBtn) | |
initFeatureIcon(context) | |
val primaryTextColor = ContextCompat.getColor(context, R.color.primary_text) | |
titleTextLayoutBuilder = TextLayoutBuilder() | |
.setTextColor(primaryTextColor) | |
.setTextSize(spToPx(resources, 15f).toInt()) | |
.setShouldWarmText(true) | |
.setSingleLine(true) | |
statusTextLayoutBuilder = TextLayoutBuilder() | |
.setTextColor(primaryTextColor) | |
.setTextSize(spToPx(resources, 12f).toInt()) | |
.setShouldWarmText(true) | |
.setSingleLine(true) | |
setPadding(content2x, content2x, content2x, content2x) | |
} | |
private fun initDate() { | |
if (dateTextLayoutBuilder == null) { | |
dateTextLayoutBuilder = TextLayoutBuilder() | |
.setTextColor(ContextCompat.getColor(context, R.color.secondary_text)) | |
.setTextSize(spToPx(resources, 12f).toInt()) | |
.setShouldWarmText(true) | |
.setSingleLine(true) | |
.setEllipsize(TextUtils.TruncateAt.END) | |
} | |
if (dotDrawable == null) { | |
dotWidth = dpToPx(resources, 5f) | |
dotDrawable = ShapeDrawable(OvalShape()) | |
dotDrawable?.intrinsicHeight = dotWidth | |
dotDrawable?.intrinsicWidth = dotWidth | |
dotDrawable?.paint?.color = ContextCompat.getColor(context, R.color.secondary_text) | |
} | |
} | |
private fun initFeatureIcon(context: Context) { | |
featureIcon = ImageView(context) | |
val size: Int = dpToPx(resources, 34f) | |
featureIcon.layoutParams = LayoutParams(size, size) | |
addView(featureIcon) | |
} | |
fun setOnExtendButtonClickListener(l: View.OnClickListener?) { | |
extendFeatureBtn.setOnClickListener(l) | |
} | |
fun setTitle(title: String?) { | |
if (this.title.equals(title)) { | |
return | |
} | |
this.title = title | |
requestLayout() | |
invalidate() | |
} | |
fun statusActive(dateTo: String?) { | |
if (dateTo == null) { | |
date = null | |
} else { | |
initDate() | |
status = resources.getString(R.string.payment_active) | |
statusTextLayoutBuilder.textColor = ContextCompat.getColor(context, R.color.green_light) | |
date = String.format(resources.getString(R.string.payment_to_date), dateTo) | |
} | |
requestLayout() | |
invalidate() | |
} | |
fun statusInactive() { | |
status = resources.getString(R.string.payment_inactive) | |
statusTextLayoutBuilder.textColor = ContextCompat.getColor(context, R.color.pink) | |
requestLayout() | |
invalidate() | |
} | |
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { | |
val width = MeasureSpec.getSize(widthMeasureSpec) | |
var height = paddingTop + paddingBottom | |
featureIcon.measure( | |
MeasureSpec.makeMeasureSpec(featureIcon.layoutParams.width, MeasureSpec.EXACTLY), | |
MeasureSpec.makeMeasureSpec(featureIcon.layoutParams.height, MeasureSpec.EXACTLY) | |
) | |
height += featureIcon.measuredHeight | |
extendFeatureBtn.measure( | |
MeasureSpec.makeMeasureSpec(extendFeatureBtn.layoutParams.width, MeasureSpec.EXACTLY), | |
MeasureSpec.makeMeasureSpec(extendFeatureBtn.layoutParams.height, MeasureSpec.EXACTLY) | |
) | |
leftWithoutIcon = featureIcon.measuredWidth + paddingLeft + content2x | |
val widthLeft = width - (leftWithoutIcon + extendFeatureBtn.measuredWidth + paddingRight + content2x) | |
titleLayout = titleTextLayoutBuilder | |
.setText(title) | |
.setMaxWidth(widthLeft) | |
.build() | |
titleHeight = titleLayout?.height ?: 0 | |
statusLayout = statusTextLayoutBuilder | |
.setText(status) | |
.setMaxWidth(widthLeft) | |
.build() | |
statusHeight = statusLayout?.height ?: 0 | |
statusWidth = statusLayout?.width ?: 0 | |
dateTextLayoutBuilder?.let { | |
dateLayout = it | |
.setText(date) | |
.setMaxWidth(widthLeft - (statusWidth + dotWidth)) | |
.build() | |
} | |
setMeasuredDimension(width, height) | |
} | |
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) { | |
val parentTop = paddingTop | |
val parentLeft = paddingLeft | |
val parentBottom = bottom - top - paddingBottom | |
val height = parentBottom - parentTop | |
centerTop = height / 2 | |
titleTop = centerTop - content0_25x | |
statusTop = centerTop + content0_25x | |
val featureIconTop = parentTop + (height - featureIcon.measuredHeight) / 2 | |
featureIcon.layout( | |
parentLeft, | |
featureIconTop, | |
parentLeft + featureIcon.measuredWidth, | |
featureIconTop + featureIcon.measuredHeight | |
) | |
val extendFeatureBtnTop: Int = parentTop + (height - extendFeatureBtn.measuredHeight) / 2 | |
val extendFeatureBtnLeft: Int = right - paddingRight - extendFeatureBtn.measuredWidth | |
extendFeatureBtn.layout( | |
extendFeatureBtnLeft, | |
extendFeatureBtnTop, | |
extendFeatureBtnLeft + extendFeatureBtn.measuredWidth, | |
extendFeatureBtnTop + extendFeatureBtn.measuredHeight | |
) | |
dotDrawable?.let { | |
val dotLeft = leftWithoutIcon + statusWidth + content | |
val dotTop = titleTop + statusTop + content0_25x * 2 + it.intrinsicHeight / 2 | |
it.setBounds( | |
dotLeft, | |
dotTop, | |
dotLeft + it.intrinsicWidth, | |
dotTop + it.intrinsicHeight | |
) | |
} | |
} | |
override fun onDraw(canvas: Canvas) { | |
super.onDraw(canvas) | |
canvas.drawColor(whiteColor) | |
canvas.save() | |
canvas.translate(leftWithoutIcon.toFloat(), titleTop.toFloat()) | |
titleLayout?.draw(canvas) | |
statusLayout?.let { | |
canvas.translate(0f, statusTop.toFloat()) | |
it.draw(canvas) | |
canvas.translate(dotWidth + content2x + statusWidth.toFloat(), 0f) | |
dateLayout?.draw(canvas) | |
} | |
canvas.restore() | |
dotDrawable?.draw(canvas) | |
} | |
override fun hasOverlappingRendering(): Boolean { | |
return false | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment