Preview:
package utils

import android.animation.Animator
import android.animation.Animator.*
import android.animation.ObjectAnimator
import android.animation.PropertyValuesHolder
import android.animation.ValueAnimator
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.graphics.drawable.BitmapDrawable
import android.util.Log
import android.view.View
import android.view.ViewGroup.*
import android.widget.ImageView
import android.widget.Toast
import androidx.core.view.marginTop
import androidx.fragment.app.FragmentActivity
import androidx.palette.graphics.Palette
import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import applicaton.BaseViewModel.*
import applicaton.BaseViewModel.BaseRequest.*
import br.com.icaro.filme.R
import com.github.clans.fab.FloatingActionMenu
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.gson.Gson
import com.squareup.picasso.Callback
import com.squareup.picasso.MemoryPolicy
import com.squareup.picasso.NetworkPolicy
import com.squareup.picasso.Picasso
import domain.reelgood.movie.Availability
import domain.tvshow.Tvshow
import error.BottomSheetError
import error.CallBackError
import java.text.DateFormat
import java.text.Normalizer
import java.text.ParseException
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Date
import java.util.Locale

/**
 * Created by icaro on 03/09/17.
 */
/**
 * IMAGEVIEW
 */
fun ImageView.setPicasso(
	stillPath: String?,
	patten: Int = 4,
	sucesso: () -> Unit = {},
	error: () -> Unit = {},
	img_erro: Int = R.drawable.poster_empty,
): ImageView {
	Picasso.get()
		.load(
			UtilsApp
				.getBaseUrlImagem(UtilsApp.getTamanhoDaImagem(context, patten)) + stillPath
		)
		.error(img_erro)
		.memoryPolicy(MemoryPolicy.NO_STORE, MemoryPolicy.NO_CACHE)
		.networkPolicy(NetworkPolicy.NO_CACHE, NetworkPolicy.NO_STORE)
		.into(this, object : Callback {
			override fun onSuccess() {
				sucesso()
			}

			override fun onError(e: java.lang.Exception?) {
				error()
			}
		})
	return this
}

fun ImageView.setPicassoWithCache(
	stillPath: String?, patten: Int = 4,
	sucesso: () -> Unit = {},
	error: () -> Unit = {},
	img_erro: Int = R.drawable.poster_empty,
): ImageView {
	Picasso.get()
		.load(
			UtilsApp
				.getBaseUrlImagem(UtilsApp.getTamanhoDaImagem(context, patten)) + stillPath
		)
		.error(img_erro)
		.into(this, object : Callback {
			override fun onSuccess() {
				sucesso()
			}

			override fun onError(e: java.lang.Exception?) {
				error()
			}
		})
	return this
}

fun ImageView.setPicassoWithCacheAndHolder(
	stillPath: String?, patten: Int = 4,
	sucesso: () -> Unit = {},
	error: () -> Unit = {},
	img_erro: Int = R.drawable.poster_empty,
	holder: Int,
): ImageView {
	Picasso.get()
		.load(UtilsApp.getBaseUrlImagem(UtilsApp.getTamanhoDaImagem(context, patten)) + stillPath)
		.placeholder(holder)
		.error(img_erro)
		.into(this, object : Callback {
			override fun onSuccess() {
				sucesso()
			}

			override fun onError(e: java.lang.Exception?) {
				error()
			}
		})
	return this
}

fun ImageView.loadPallet(): Int? {
	val color = (drawable as? BitmapDrawable)?.run {
		Palette.Builder(this.bitmap).generate().swatches.first().rgb
	}
	return color ?: 0
}

fun loadPalette(view: ImageView): Int { // Todo Usar ext
	val imageView = view as ImageView
	val drawable = imageView.drawable as? BitmapDrawable
	if (drawable != null) {
		return Palette.Builder(drawable.bitmap).generate().swatches.last().rgb
	}
	return 0
}

/**
 * ACTIVITY
 */
fun Activity.makeToast(restText: Int, time: Int = Toast.LENGTH_SHORT) {
	this.makeToast(this.getString(restText), time)
}

fun Activity.makeToast(text: String?, time: Int = Toast.LENGTH_SHORT) {
	Toast.makeText(this, text, time).show()
}

/**
 * Context
 */
fun Context.makeToast(text: String?, time: Int = Toast.LENGTH_SHORT) {
	Toast.makeText(this, text, time).show()
}

/**
 * VIEW
 */
fun View.gone() {
	this.visibility = View.GONE
}

fun View.visible() {
	this.visibility = View.VISIBLE
}

fun View.invisible() {
	this.visibility = View.INVISIBLE
}

fun View.animeRotation(
	end: () -> Unit = {},
	cancel: () -> Unit = {},
	start: () -> Unit = {},
	repeat: () -> Unit = {},
) {
	ObjectAnimator
		.ofPropertyValuesHolder(
			this,
			PropertyValuesHolder.ofFloat(View.SCALE_X, 1.0f, 0.2f),
			PropertyValuesHolder.ofFloat(View.SCALE_Y, 1.0f, 0.2f),
			PropertyValuesHolder.ofFloat(View.SCALE_X, 0.0f, 1.0f),
			PropertyValuesHolder.ofFloat(View.SCALE_Y, 0.0f, 1.0f)
		)
		.apply {
			duration = 790
			addListener(object : AnimatorListener {
				override fun onAnimationRepeat(animation: Animator?) {
					repeat()
				}

				override fun onAnimationEnd(animation: Animator?) {
					end()
				}

				override fun onAnimationCancel(animation: Animator?) {
					cancel()
				}

				override fun onAnimationStart(animation: Animator?) {
					start()
				}
			})
		}.start()
}

/**
 * Any
 */
fun Any.putString(cxt: Context): String = when (this) {
	is String -> this
	is Int -> cxt.getString(this)
	else -> {
		require(false) { "Need R.string.id or string" }
		""
	}
}

/**
 * STRING
 */
fun String.removerAcentos(): String {
	this.replace(".", "")
	this.replace(":", "")
	this.replace("/", "")
	this.replace(";", "")
	return Normalizer.normalize(this, Normalizer.Form.NFD).replace("[^\\p{ASCII}]".toRegex(), "")
}

fun String.parseDate(): String {
	return try {
		val sim = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss")
		val data = sim.parse(this)
		DateFormat.getDateInstance(DateFormat.SHORT).format(data)
	} catch (ex: Exception) {
		"-/-"
	}
}

fun String.parseDateShot(): String {
	return try {
		val sim = SimpleDateFormat("yyyy-MM-dd")
		val data = sim.parse(this)
		DateFormat.getDateInstance(DateFormat.SHORT).format(data)
	} catch (ex: Exception) {
		"-/-"
	}
}

fun verifyLaunch(air_date: Date?): Boolean {
	if (air_date == null) return false
	val now = Calendar.getInstance().time
	return if (air_date.before(now)) {
		true
	} else !air_date.after(now)
}

fun String.getDate(format: String = "yyyy-MM-dd"): Date? {
	return try {
		let {
			val sdf = SimpleDateFormat(format, Locale.getDefault())
			sdf.parse(it)
		}
	} catch (e: ParseException) {
		e.printStackTrace()
		null
	}
}

fun String.released(): Boolean {
	val data = getDate()
	return verifyLaunch(data)
}

@Throws(Exception::class)
fun String.yearDate(): String {
	return if (this.length >= 4) this.substring(0, 4) else ""
}

fun String.periodLaunch(): Boolean {
	val oneWeekBack = Calendar.getInstance().apply { add(Calendar.DAY_OF_YEAR, -7) }.time
	return getDate() != null && getDate()!!.after(oneWeekBack) //valida data
}

fun String.getNameTypeReel(): String {
	return replace(":", "-")
		.replace(" ", "-")
		.replace("&", "and")
		.replace(".", "")
		.replace("é", "e")
		.replace("ẽ", "e")
		.replace("è", "e")
		.replace("ë", "e")
		.replace("ç", "c")
		.replace("â", "a")
		.replace("ã", "a")
		.replace("á", "a")
		.replace("à", "a")
		.replace("ä", "a")
		.replace("ä", "a")
		.replace("'", "")
		.replace("\"", "")
		.replace("´", "")
		.replace("~", "")
		.replace("^", "")
		.replace("---", "-")
		.replace("----", "-")
		.replace("--", "-")
		.toLowerCase()
}

fun String?.notNullOrEmpty() = !this.isNullOrEmpty()
fun <T> Gson.fromJsonWithLog(json: String?, classOfT: Class<T>): T {
	return this.fromJson<T>(json, classOfT).apply {
		this.toString().log(classOfT.name)
	}
}

fun String.log(tag: String = "") = Log.i(tag, this)

fun Tvshow.createIdReal() = createIdReal(this.originalName ?: "", this.firstAirDate ?: "")
private fun createIdReal(originalName: String, data: String) =
	"${originalName.getNameTypeReel()}-${data.yearDate()}"

/**
 * RECYCLER
 */
fun RecyclerView.setScrollInvisibleFloatMenu(floatButton: FloatingActionMenu) {
	addOnScrollListener(object : RecyclerView.OnScrollListener() {
		override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
			when (newState) {
				RecyclerView.SCROLL_STATE_IDLE -> floatButton.visible()
				RecyclerView.SCROLL_STATE_DRAGGING -> floatButton.invisible()
				RecyclerView.SCROLL_STATE_SETTLING -> floatButton.invisible()
			}
		}
	})
}

@SuppressLint("WrongConstant")
fun RecyclerView.patternRecyler(horizont: Boolean = true): RecyclerView {
	val typeOrient = if (horizont) LinearLayoutManager.HORIZONTAL else LinearLayoutManager.VERTICAL
	layoutManager = LinearLayoutManager(context, typeOrient, false)
	itemAnimator = DefaultItemAnimator()
	setHasFixedSize(true)
	return this
}

fun RecyclerView.patternRecyclerGrid(quant: Int = 2): RecyclerView {
	layoutManager = GridLayoutManager(context, quant)
	setHasFixedSize(true)
	itemAnimator = DefaultItemAnimator()
	return this
}

fun RecyclerView.minHeight(): RecyclerView {
	layoutParams.height = 1
	importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_NO
	isFocusable = false
	return this
}

/**
 * AVAILABILITY
 */
fun Availability.getPricePurchase(): String {
	val less = purchaseCostSd?.let { purchaseCostHd?.coerceAtMost(it) }
	val biggest = purchaseCostSd?.let { purchaseCostHd?.coerceAtLeast(it) }
	if (less == biggest) return less.toString()
	return "${if (less != 0.0) less.toString() else "--"} - ${if (biggest != 0.0) biggest.toString() else "--"}"
}

fun Availability.getPriceRental(): String {
	val less = rentalCostSd?.let { rentalCostHd?.coerceAtMost(it) }
	val biggest = rentalCostSd?.let { rentalCostHd?.coerceAtLeast(it) }
	if (less == biggest) return less.toString()
	return "${if (less != 0.0) less.toString() else "--"} - ${if (biggest != 0.0) biggest.toString() else "--"}"
}

/**
 * BottomSheetBehavior
 */
fun BottomSheetBehavior<View>.setAnimation(container: View, viewHeight: View) {
	ValueAnimator.ofInt(container.measuredHeight, viewHeight.marginTop).apply {
		addUpdateListener {
			peekHeight = it.animatedValue as Int
		}
		duration = 500
	}.start()

	container.post {
		val newLayoutParams = (container.layoutParams as? MarginLayoutParams)
		newLayoutParams?.setMargins(0, 0, 0, viewHeight.marginTop + 1)
		container.layoutParams = newLayoutParams
	}
}

/**
 * MutableList
 */
fun <T> MutableList<T>.replaceItemList(item: T, predicate: (T) -> Boolean): MutableList<T> {
	return this.map {
		if (predicate(it)) item else it
	}.toMutableList()
}

fun <T> Any.listSize(item: T, size: Int): ArrayList<T> {
	return if (size <= 0) {
		arrayListOf()
	} else {
		arrayListOf<T>().apply {
			for (i in 0 until size) {
				add(item)
			}
		}
	}
}

/**
 * BaseRequest
 */
fun <T> BaseRequest<T>.success() = (this as Success<T>).result
fun <T> BaseRequest<T>.resolver(
	activity: FragmentActivity,
	successBlock: (data: T) -> Unit,
	failureBlock: (error: Exception) -> Unit = {},
	loadingBlock: (loading: Boolean) -> Unit = {},
	genericError: CallBackError? = null,
) {
	when (this) {
		is Success -> successBlock(result)
		is Loading -> loadingBlock(loading)
		is Failure -> {
			error.toString().log()
			if (genericError != null) {
				BottomSheetError().newInstance(callBackError = genericError)
					.show(activity.supportFragmentManager, "")
			} else {
				failureBlock(error)
			}
		}
	}
}


downloadDownload PNG downloadDownload JPEG downloadDownload SVG

Tip: You can change the style, width & colours of the snippet with the inspect tool before clicking Download!

Click to optimize width for Twitter