Skip to content

Instantly share code, notes, and snippets.

@dyguests
Last active March 28, 2019 15:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dyguests/8dc49819fe98fa831cdc1a4dcb26dc90 to your computer and use it in GitHub Desktop.
Save dyguests/8dc49819fe98fa831cdc1a4dcb26dc90 to your computer and use it in GitHub Desktop.
Parallax ImageView,WindowImageView,Helper

** Do not just use Glide.xxx.into(imageView).

use ImageView.setImageAsDrawable() in ImageViews.kt

fun ImageView.setImageAsDrawable(
url: String,
@DrawableRes placeHolder: Int? = null
) {
Glide.with(this)
// .asBitmap()
.load(url)
.apply {
if (placeHolder != null) {
apply(RequestOptions().placeholder(placeHolder))
}
}
.into(object : CustomTarget<Drawable>() {
override fun onLoadCleared(placeholder: Drawable?) {
this@setImageAsDrawable.setImageDrawable(placeholder)
}
override fun onResourceReady(resource: Drawable, transition: Transition<in Drawable>?) {
this@setImageAsDrawable.setImageDrawable(resource)
}
})
}
package com.fanhl.parallaximage
import android.graphics.Matrix
import android.graphics.RectF
import android.util.Log
import android.widget.ImageView
import androidx.core.math.MathUtils
import androidx.recyclerview.widget.RecyclerView
/**
* 处理图像在滚动中的显示
*/
class ParallaxImageRecyclerViewHelper private constructor() {
/** 目前图像 */
private var target: ImageView? = null
/** 目前图像所在的滚动父布局 */
private var dependency: RecyclerView? = null
/** target的宽度与dependency的宽度的比率 */
private var widthRate = 1f
private var heightRate = 1f
private var horizontalBias = 0.5f
private var verticalBias = 0.5f
/**
* 临时存放区
* FIXME 之后加上生命周期
*/
private val outLocation = IntArray(2)
private val onScrollListener = object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
computeImageMatrix(
target ?: return,
dependency ?: return
)
}
}
private fun setup(recyclerView: RecyclerView, imageView: ImageView) {
this.target = imageView
if (this.dependency != recyclerView) {
this.dependency?.removeOnScrollListener(onScrollListener)
this.dependency = recyclerView
}
recyclerView?.addOnScrollListener(onScrollListener) ?: return
}
private fun computeImageMatrix(
target: ImageView,
dependency: RecyclerView
) {
//FIXME 这部分可以只修改一次
widthRate = target.width.toFloat() / dependency.width
heightRate = target.height.toFloat() / dependency.height
//FIXME 这部分可以根据父布局的滚动方向,只计算对应方向的就可以了
target.getLocationOnScreen(outLocation)
val targetX = outLocation[0]
val targetY = outLocation[1]
dependency.getLocationOnScreen(outLocation)
val dependencyX = outLocation[0]
val dependencyY = outLocation[1]
horizontalBias = ((targetX - dependencyX).toFloat() / (dependency.width - target.width)).clamp()
verticalBias = ((targetY - dependencyY).toFloat() / (dependency.height - target.height)).clamp()
// Log.d(TAG, "widthRate:$widthRate,heightRate:$heightRate horizontalBias:$horizontalBias,verticalBias:$verticalBias")
this.target?.apply {
val drawable = drawable ?: return
// val matrix = imageMatrix
val viewWidth = width// - paddingLeft - paddingRight
val viewHeight = height// - paddingTop - paddingBottom
val drawableWidth = drawable.intrinsicWidth
val drawableHeight = drawable.intrinsicHeight
// TODO 以下计算式等其它部分全部完全后再优化
val drawableRect = if (drawableWidth * viewHeight > drawableHeight * viewWidth) {
val scale = viewHeight.toFloat() / drawableHeight.toFloat()
// val horizontalBias = left.toFloat() / (left + (parent as View).right - right)
val dx = horizontalBias * (drawableWidth - viewWidth / scale)
RectF(dx, 0f, dx + drawableHeight.toFloat(), drawableHeight.toFloat() * viewWidth / viewHeight)
} else {
val scale = viewWidth.toFloat() / drawableWidth.toFloat()
// val verticalBias = top.toFloat() / (top + (parent as View).bottom - bottom)
val dy = verticalBias * (drawableHeight - viewHeight / scale)
RectF(0f, dy, drawableWidth.toFloat(), dy + drawableWidth.toFloat() * viewHeight / viewWidth)
}
val viewRect = RectF(0f, 0f, viewWidth.toFloat(), viewHeight.toFloat())
Log.d(TAG, "drawableRect:$drawableRect viewRect:$viewRect")
imageMatrix.setRectToRect(drawableRect, viewRect, Matrix.ScaleToFit.FILL)
invalidate()
// imageMatrix = matrix
}
}
companion object {
private val TAG = ParallaxImageRecyclerViewHelper::class.java.simpleName
fun setup(recyclerView: RecyclerView, imageView: ImageView) {
ParallaxImageRecyclerViewHelper().setup(recyclerView, imageView)
}
}
private fun Float.clamp() = MathUtils.clamp(this, 0f, 1f)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment