Move from java/ to kotlin/ directory

Android 12 dynamic color usage on login screen
This commit is contained in:
2021-08-31 02:18:29 +03:00
parent 2453e534ae
commit 1209c37e24
135 changed files with 140 additions and 57 deletions
@@ -0,0 +1,61 @@
package com.meloda.fast.widget
import android.annotation.SuppressLint
import android.content.Context
import android.util.AttributeSet
import android.widget.LinearLayout
import com.meloda.fast.R
class BoundedLinearLayout : LinearLayout {
private var mBoundedWidth: Int
private var mBoundedHeight: Int
constructor(context: Context?) : super(context) {
mBoundedWidth = 0
mBoundedHeight = 0
}
@SuppressLint("CustomViewStyleable")
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
val a = context.obtainStyledAttributes(attrs, R.styleable.BoundedView)
mBoundedWidth = a.getDimensionPixelSize(R.styleable.BoundedView_bounded_width, 0)
mBoundedHeight = a.getDimensionPixelSize(R.styleable.BoundedView_bounded_height, 0)
a.recycle()
}
var maxWidth: Int
get() = mBoundedWidth
set(width) {
if (mBoundedWidth != width) {
mBoundedWidth = width
requestLayout()
}
}
var maxHeight: Int
get() = mBoundedHeight
set(height) {
if (mBoundedHeight != height) {
mBoundedHeight = height
requestLayout()
}
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
// Adjust width as necessary
var widthMeasureSpec = widthMeasureSpec
var heightMeasureSpec = heightMeasureSpec
val measuredWidth = MeasureSpec.getSize(widthMeasureSpec)
if (mBoundedWidth in 1 until measuredWidth) {
val measureMode = MeasureSpec.getMode(widthMeasureSpec)
widthMeasureSpec = MeasureSpec.makeMeasureSpec(mBoundedWidth, measureMode)
}
// Adjust height as necessary
val measuredHeight = MeasureSpec.getSize(heightMeasureSpec)
if (mBoundedHeight in 1 until measuredHeight) {
val measureMode = MeasureSpec.getMode(heightMeasureSpec)
heightMeasureSpec = MeasureSpec.makeMeasureSpec(mBoundedHeight, measureMode)
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
}
}
@@ -0,0 +1,68 @@
package com.meloda.fast.widget
import android.content.Context
import android.graphics.Canvas
import android.graphics.Path
import android.graphics.RectF
import android.util.AttributeSet
import android.view.ViewTreeObserver
import androidx.appcompat.widget.AppCompatImageView
class CircleImageView : AppCompatImageView {
companion object {
val SCALE_TYPE = ScaleType.CENTER_CROP
}
private var path: Path? = null
private var rect: RectF? = null
constructor(context: Context) : this(context, null)
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
context,
attrs,
defStyleAttr
) {
init()
}
override fun onDraw(canvas: Canvas?) {
rect ?: return
canvas ?: return
if (rect!!.right == 0f || rect!!.bottom == 0f) {
createRect(width, height)
}
canvas.clipPath(path!!)
super.onDraw(canvas)
}
private fun init() {
scaleType = SCALE_TYPE
viewTreeObserver.addOnPreDrawListener(object : ViewTreeObserver.OnPreDrawListener {
override fun onPreDraw(): Boolean {
createRect(width, height)
viewTreeObserver.removeOnPreDrawListener(this)
return false
}
})
}
private fun createRect(width: Int, height: Int) {
rect = RectF(0f, 0f, width.toFloat(), height.toFloat())
path = Path()
path!!.addRoundRect(
rect!!,
(width / 2).toFloat(),
(height / 2).toFloat(),
Path.Direction.CW
)
}
}
@@ -0,0 +1,137 @@
package com.meloda.fast.widget
import android.content.Context
import android.graphics.drawable.Drawable
import android.util.AttributeSet
import android.view.Gravity
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import androidx.annotation.ColorInt
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import androidx.core.view.isVisible
import com.meloda.fast.extensions.ContextExtensions.drawable
import com.meloda.fast.extensions.DrawableExtensions.tint
import com.meloda.fast.extensions.FloatExtensions.int
import com.meloda.fast.R
import com.meloda.fast.util.AndroidUtils
@Suppress("UNCHECKED_CAST")
class NoItemsView @JvmOverloads constructor(
context: Context, private var attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : LinearLayout(context, attrs, defStyleAttr) {
private lateinit var noItemsPicture: ImageView
private lateinit var noItemsTextView: TextView
private val textViewParams
get() = LayoutParams(
LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT
)
private val imageViewParams
get() = LayoutParams(
LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT
)
init {
create()
}
private fun create() {
val a = context.obtainStyledAttributes(attrs, R.styleable.NoItemsView)
minimumWidth = AndroidUtils.px(256).int()
minimumHeight = minimumWidth
orientation = VERTICAL
gravity = Gravity.CENTER
noItemsPicture = ImageView(context)
val params = imageViewParams
params.height = AndroidUtils.px(64).int()
params.width = AndroidUtils.px(64).int()
noItemsPicture.layoutParams = params
val noItemsDrawable = a.getDrawable(R.styleable.NoItemsView_noItemsImage)
noItemsDrawable?.let {
val noItemsDrawableTintColor = a.getColor(R.styleable.NoItemsView_noItemsImageTint, -1)
if (noItemsDrawableTintColor != -1) {
it.setTint(noItemsDrawableTintColor)
}
setNoItemsImage(it)
}
addView(noItemsPicture)
noItemsTextView = TextView(context)
val textParams = textViewParams
textParams.width = AndroidUtils.px(256).int()
if (noItemsDrawable != null) {
textParams.topMargin = AndroidUtils.px(8).int()
}
noItemsTextView.layoutParams = textParams
noItemsTextView.gravity = Gravity.CENTER
noItemsTextView.setTextAppearance(R.style.TextAppearance_MaterialComponents_Body1)
val noItemsTextColor = a.getColor(R.styleable.NoItemsView_noItemsTextColor, -1)
if (noItemsTextColor != -1) {
setNoItemsTextColor(noItemsTextColor)
}
val noItemsText = a.getString(R.styleable.NoItemsView_noItemsText)
noItemsText?.let {
setNoItemsText(it)
}
addView(noItemsTextView)
val isVisibleByDefault = a.getBoolean(R.styleable.NoItemsView_isVisibleByDefault, true)
isVisible = isVisibleByDefault
a.recycle()
}
fun setNoItemsImage(@DrawableRes resId: Int) {
setNoItemsImage(context.drawable(resId))
}
fun setNoItemsImage(drawable: Drawable?) {
noItemsPicture.setImageDrawable(drawable)
}
fun setNoItemsImageTint(@ColorInt color: Int) {
noItemsPicture.drawable.tint(color)
}
fun setNoItemsText(@StringRes resId: Int) {
noItemsTextView.setText(resId)
}
fun setNoItemsText(text: String) {
noItemsTextView.text = text
}
fun setNoItemsTextColor(@ColorInt color: Int) {
noItemsTextView.setTextColor(color)
}
fun show() {
isVisible = true
}
fun hide() {
isVisible = false
}
}
@@ -0,0 +1,141 @@
package com.meloda.fast.widget
import android.app.Activity
import android.content.Context
import android.content.res.ColorStateList
import android.graphics.Canvas
import android.graphics.drawable.Drawable
import android.util.AttributeSet
import android.util.TypedValue
import android.view.Gravity
import android.view.View
import android.widget.ImageButton
import android.widget.ImageView
import android.widget.TextView
import androidx.annotation.ColorInt
import androidx.annotation.DrawableRes
import androidx.core.content.res.ResourcesCompat
import com.google.android.material.appbar.MaterialToolbar
import com.google.android.material.theme.overlay.MaterialThemeOverlay
import com.meloda.fast.R
import com.meloda.fast.util.AndroidUtils
class Toolbar : MaterialToolbar {
constructor(context: Context) : this(context, null)
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
MaterialThemeOverlay.wrap(
context,
attrs,
defStyleAttr,
com.google.android.material.R.style.Widget_MaterialComponents_Toolbar
),
attrs,
defStyleAttr
)
private fun init() {
//...
}
override fun setTitle(resId: Int) {
title = context.getString(resId)
}
override fun setTitle(title: CharSequence?) {
findViewById<TextView>(R.id.toolbarTitle).text = title
}
override fun setTitleTextColor(color: Int) {
findViewById<TextView>(R.id.toolbarTitle).setTextColor(color)
}
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
init()
}
override fun setNavigationIcon(icon: Drawable?) {
findViewById<ImageButton>(R.id.toolbarNavigationIcon).setImageDrawable(icon)
}
override fun setNavigationIcon(@DrawableRes resId: Int) {
findViewById<ImageButton>(R.id.toolbarNavigationIcon).setImageResource(resId)
}
// fun setNavigationIconTintList(tintList: ColorStateList?) {
// findViewById<ImageButton>(R.id.toolbarNavigationIcon).drawable?.setTintList(tintList)
// }
//
// fun setNavigationIconTint(@ColorInt tintColor: Int) {
// findViewById<ImageButton>(R.id.toolbarNavigationIcon).drawable?.setTint(tintColor)
// }
fun setNavigationClickListener(listener: OnClickListener?) {
findViewById<View>(R.id.toolbarNavigation).setOnClickListener(listener)
}
fun setNavigationOnBackClickListener(activity: Activity) {
findViewById<View>(R.id.toolbarNavigation).setOnClickListener { activity.onBackPressed() }
}
fun setNavigationVisibility(visible: Boolean) {
findViewById<View>(R.id.toolbarNavigation).visibility = if (visible) VISIBLE else GONE
}
fun tintNavigationIcon(@ColorInt color: Int) {
findViewById<ImageButton>(R.id.toolbarNavigationIcon).imageTintList =
ColorStateList.valueOf(color)
}
fun setAvatarIcon(icon: Drawable?) {
findViewById<ImageView>(R.id.toolbarAvatar).setImageDrawable(icon)
}
fun setAvatarIcon(@DrawableRes resId: Int) {
// findViewById<SimpleDraweeView>(R.id.toolbarAvatar).setActualImageResource(resId)
}
fun setAvatarClickListener(listener: OnClickListener?) {
findViewById<View>(R.id.toolbarAvatar).setOnClickListener(listener)
}
fun setAvatarVisibility(visible: Boolean) {
findViewById<View>(R.id.toolbarAvatar).visibility = if (visible) VISIBLE else GONE
}
// fun getAvatar(): SimpleDraweeView {
// return findViewById(R.id.toolbarAvatar)
// }
fun setTitleMode(titleMode: TitleMode) {
val title = findViewById<TextView>(R.id.toolbarTitle)
when (titleMode) {
TitleMode.SIMPLE -> {
title.gravity = Gravity.CENTER
title.typeface = ResourcesCompat.getFont(context, R.font.google_sans_medium)
title.setTextColor(AndroidUtils.getThemeAttrColor(context, R.attr.colorAccent))
title.setTextSize(TypedValue.COMPLEX_UNIT_SP, 22f)
}
TitleMode.HINT -> {
title.gravity = Gravity.CENTER_VERTICAL and Gravity.START
title.typeface = ResourcesCompat.getFont(context, R.font.google_sans_regular)
title.setTextColor(
AndroidUtils.getThemeAttrColor(
context,
R.attr.textColorSecondary
)
)
title.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16f)
}
}
}
enum class TitleMode {
SIMPLE, HINT
}
}
@@ -0,0 +1,56 @@
package com.meloda.fast.widget
import android.content.Context
import android.text.Layout
import android.util.AttributeSet
import androidx.appcompat.widget.AppCompatTextView
import com.meloda.fast.R
import kotlin.math.ceil
import kotlin.math.max
class WrapTextView(context: Context, attrs: AttributeSet? = null) :
AppCompatTextView(context, attrs) {
private var fixWrapText = false
constructor(context: Context) : this(context, null)
init {
init(context, attrs)
}
private fun init(context: Context, attrs: AttributeSet?) {
val a = context.theme.obtainStyledAttributes(attrs, R.styleable.WrapTextView, 0, 0)
try {
fixWrapText = a.getBoolean(R.styleable.WrapTextView_fixWrap, false)
} finally {
a.recycle()
}
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
if (fixWrapText && MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.EXACTLY) {
val width = getMaxWidth(layout)
if (width in 1 until measuredWidth) {
super.onMeasure(
MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST),
heightMeasureSpec
)
}
}
}
private fun getMaxWidth(layout: Layout): Int {
if (layout.lineCount < 2) return 0
var maxWidth = 0.0f
for (i in 0 until layout.lineCount) {
maxWidth = max(maxWidth, layout.getLineWidth(i))
}
return ceil(maxWidth).toInt()
}
}