Skip to content

Instantly share code, notes, and snippets.

@gigiperih
Last active December 3, 2021 10:19
Show Gist options
  • Save gigiperih/8ed0667d55756e7a6f653be606b71774 to your computer and use it in GitHub Desktop.
Save gigiperih/8ed0667d55756e7a6f653be606b71774 to your computer and use it in GitHub Desktop.
ShimmerConstraintLayout: lifecycle aware shimmering constraint layout
<com.pkg.widget.constraintlayout.ShimmerConstraintLayout
android:id="@+id/cl_footer_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:shimmer_layout="@layout/view_nha_shimmer_detail_footer"
app:shimmer_on_top="true"
app:shimmer_padding_end="@dimen/TDS_spacing_20dp"
app:shimmer_padding_start="@dimen/TDS_spacing_20dp">
</com.pkg.widget.constraintlayout.ShimmerConstraintLayout>
<declare-styleable name="ShimmerConstraintLayout">
<attr name="shimmer_layout" format="reference" />
<attr name="shimmer_padding_start" format="dimension" />
<attr name="shimmer_padding_end" format="dimension" />
<attr name="shimmer_padding_top" format="dimension" />
<attr name="shimmer_padding_bottom" format="dimension" />
<attr name="shimmer_on_top" format="boolean" />
</declare-styleable>
class ShimmerConstraintLayout @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : ConstraintLayout(context, attrs, defStyleAttr) {
@LayoutRes
private var layoutRes: Int = 0
@Dimension
private var shimmerPaddingStart: Int = 0
@Dimension
private var shimmerPaddingEnd: Int = 0
@Dimension
private var shimmerPaddingTop: Int = 0
@Dimension
private var shimmerPaddingBottom: Int = 0
private var isShimmerOnTop = false
private var shimmerView: View? = null
init {
context.obtainStyledAttributes(
attrs,
R.styleable.ShimmerConstraintLayout,
0, 0
).apply {
try {
layoutRes = getResourceId(R.styleable.ShimmerConstraintLayout_shimmer_layout, 0)
isShimmerOnTop = getBoolean(R.styleable.ShimmerConstraintLayout_shimmer_on_top, false)
shimmerPaddingStart = getDimensionPixelSize(
R.styleable.ShimmerConstraintLayout_shimmer_padding_start,
0
)
shimmerPaddingEnd = getDimensionPixelSize(
R.styleable.ShimmerConstraintLayout_shimmer_padding_end,
0
)
shimmerPaddingTop = getDimensionPixelSize(
R.styleable.ShimmerConstraintLayout_shimmer_padding_top,
0
)
shimmerPaddingBottom = getDimensionPixelSize(
R.styleable.ShimmerConstraintLayout_shimmer_padding_bottom,
0
)
if (layoutRes != 0) buildShimmerView()
} finally {
recycle()
}
}
}
private fun buildShimmerView() {
// inflate shimmer view from layoutRes
shimmerView = LayoutInflater.from(context).inflate(layoutRes, this, false)
shimmerView?.let { v ->
v.id = View.generateViewId()
v.setBackgroundColor(ContextCompat.getColor(context, RCore.color.TDS_N0))
val param = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
v.layoutParams = param
v.setPadding(shimmerPaddingStart, shimmerPaddingTop, shimmerPaddingEnd, shimmerPaddingBottom)
// workaround for child views that have elevations
if (isShimmerOnTop) v.translationZ = 1f
// apply constraint
val set = ConstraintSet()
set.clone(this)
set.connect(v.id, ConstraintSet.TOP, this.id, ConstraintSet.TOP)
set.connect(v.id, ConstraintSet.START, this.id, ConstraintSet.START)
set.connect(v.id, ConstraintSet.END, this.id, ConstraintSet.END)
set.applyTo(this)
addViewInLayout(shimmerView, -1, v.layoutParams)
}
}
fun attachLiveData(liveData: LiveData<*>) {
findViewTreeLifecycleOwner()?.let { owner ->
liveData.observe(owner) {
if (childCount > 0) {
shimmerView?.let { shimmer ->
// reset elevation
shimmer.translationZ = 0f
// remove shimmer view from constraintLayout
removeViewInLayout(shimmer)
}
}
}
}
}
}
shimmerConstraintLayout.attachLiveData(getViewModel().getLiveData())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment