Skip to content

Commit

Permalink
Merge pull request #126 from rubensousa/fading_edge
Browse files Browse the repository at this point in the history
Add support for fading edges
  • Loading branch information
rubensousa authored Apr 16, 2023
2 parents d3b6f16 + 5e9d522 commit 29ddde5
Show file tree
Hide file tree
Showing 11 changed files with 692 additions and 5 deletions.
15 changes: 15 additions & 0 deletions dpadrecyclerview/api/dpadrecyclerview.api
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,12 @@ public class com/rubensousa/dpadrecyclerview/DpadRecyclerView : androidx/recycle
public final fun addRecyclerListener (Landroidx/recyclerview/widget/RecyclerView$RecyclerListener;)V
public final fun clearOnLayoutCompletedListeners ()V
public final fun clearOnViewHolderSelectedListeners ()V
protected fun dispatchDraw (Landroid/graphics/Canvas;)V
protected final fun dispatchGenericFocusedEvent (Landroid/view/MotionEvent;)Z
public final fun dispatchKeyEvent (Landroid/view/KeyEvent;)Z
public fun dispatchTouchEvent (Landroid/view/MotionEvent;)Z
public final fun enableMaxEdgeFading (Z)V
public final fun enableMinEdgeFading (Z)V
public final fun findFirstCompletelyVisibleItemPosition ()I
public final fun findFirstVisibleItemPosition ()I
public final fun findLastCompletelyVisibleItemPosition ()I
Expand All @@ -52,6 +55,10 @@ public class com/rubensousa/dpadrecyclerview/DpadRecyclerView : androidx/recycle
public final fun getCurrentSubPositions ()I
public final fun getFocusableDirection ()Lcom/rubensousa/dpadrecyclerview/FocusableDirection;
public final fun getInitialPrefetchItemCount ()I
public final fun getMaxEdgeFadingLength ()I
public final fun getMaxEdgeFadingOffset ()I
public final fun getMinEdgeFadingLength ()I
public final fun getMinEdgeFadingOffset ()I
public final fun getOnKeyInterceptListener ()Lcom/rubensousa/dpadrecyclerview/DpadRecyclerView$OnKeyInterceptListener;
public final fun getOnMotionInterceptListener ()Lcom/rubensousa/dpadrecyclerview/DpadRecyclerView$OnMotionInterceptListener;
public final fun getOnUnhandledKeyListener ()Lcom/rubensousa/dpadrecyclerview/DpadRecyclerView$OnUnhandledKeyListener;
Expand All @@ -69,11 +76,14 @@ public class com/rubensousa/dpadrecyclerview/DpadRecyclerView : androidx/recycle
public final fun isItemPrefetchEnabled ()Z
public final fun isLayoutEnabled ()Z
public final fun isLayoutReversed ()Z
public final fun isMaxEdgeFadingEnabled ()Z
public final fun isMinEdgeFadingEnabled ()Z
public final fun isScrollEnabled ()Z
protected final fun onFocusChanged (ZILandroid/graphics/Rect;)V
protected final fun onRequestFocusInDescendants (ILandroid/graphics/Rect;)Z
public final fun onRtlPropertiesChanged (I)V
public fun onScrollStateChanged (I)V
protected fun onSizeChanged (IIII)V
public final fun removeOnLayoutCompletedListener (Lcom/rubensousa/dpadrecyclerview/DpadRecyclerView$OnLayoutCompletedListener;)V
public final fun removeOnViewHolderSelectedListener (Lcom/rubensousa/dpadrecyclerview/OnViewHolderSelectedListener;)V
public final fun removeView (Landroid/view/View;)V
Expand All @@ -83,6 +93,7 @@ public class com/rubensousa/dpadrecyclerview/DpadRecyclerView : androidx/recycle
public static synthetic fun setChildAlignment$default (Lcom/rubensousa/dpadrecyclerview/DpadRecyclerView;Lcom/rubensousa/dpadrecyclerview/ChildAlignment;ZILjava/lang/Object;)V
public final fun setChildDrawingOrderCallback (Landroidx/recyclerview/widget/RecyclerView$ChildDrawingOrderCallback;)V
public final fun setExtraLayoutSpaceStrategy (Lcom/rubensousa/dpadrecyclerview/ExtraLayoutSpaceStrategy;)V
public final fun setFadingEdgeLength (I)V
public final fun setFocusDrawingOrderEnabled (Z)V
public final fun setFocusOutAllowed (ZZ)V
public final fun setFocusOutSideAllowed (ZZ)V
Expand All @@ -97,6 +108,10 @@ public class com/rubensousa/dpadrecyclerview/DpadRecyclerView : androidx/recycle
public final fun setItemPrefetchEnabled (Z)V
public final fun setLayoutEnabled (Z)V
public final fun setLayoutManager (Landroidx/recyclerview/widget/RecyclerView$LayoutManager;)V
public final fun setMaxEdgeFadingLength (I)V
public final fun setMaxEdgeFadingOffset (I)V
public final fun setMinEdgeFadingLength (I)V
public final fun setMinEdgeFadingOffset (I)V
public final fun setOnChildLaidOutListener (Lcom/rubensousa/dpadrecyclerview/OnChildLaidOutListener;)V
public final fun setOnKeyInterceptListener (Lcom/rubensousa/dpadrecyclerview/DpadRecyclerView$OnKeyInterceptListener;)V
public final fun setOnMotionInterceptListener (Lcom/rubensousa/dpadrecyclerview/DpadRecyclerView$OnMotionInterceptListener;)V
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@ package com.rubensousa.dpadrecyclerview

import android.content.Context
import android.content.res.TypedArray
import android.graphics.Canvas
import android.graphics.Rect
import android.util.AttributeSet
import android.view.Gravity
import android.view.KeyEvent
import android.view.MotionEvent
import android.view.View
import android.view.animation.Interpolator
import androidx.annotation.Px
import androidx.core.view.ViewCompat
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
Expand Down Expand Up @@ -57,6 +59,7 @@ open class DpadRecyclerView @JvmOverloads constructor(

private val viewHolderTaskExecutor = ViewHolderTaskExecutor()
private val focusableChildDrawingCallback = FocusableChildDrawingCallback()
private val fadingEdge = FadingEdge()

private var pivotLayoutManager: PivotLayoutManager? = null
private var isOverlappingRenderingEnabled = true
Expand Down Expand Up @@ -97,6 +100,13 @@ open class DpadRecyclerView @JvmOverloads constructor(
// Call setItemAnimator to set it up
this.itemAnimator = itemAnimator

val fadingEdgeLength = typedArray.getDimensionPixelOffset(
R.styleable.DpadRecyclerView_android_fadingEdgeLength, 0
)
if (fadingEdgeLength > 0) {
setFadingEdgeLength(fadingEdgeLength)
}

setWillNotDraw(true)
setChildDrawingOrderCallback(focusableChildDrawingCallback)
overScrollMode = OVER_SCROLL_NEVER
Expand Down Expand Up @@ -357,6 +367,45 @@ open class DpadRecyclerView @JvmOverloads constructor(
}
}

override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
super.onSizeChanged(w, h, oldw, oldh)
fadingEdge.onSizeChanged(w, h, oldw, oldh, this)
}

final override fun setFadingEdgeLength(length: Int) {
super.setFadingEdgeLength(length)
layoutManager?.let {
enableMinEdgeFading(true)
enableMaxEdgeFading(true)
setMaxEdgeFadingLength(length)
setMinEdgeFadingLength(length)
}
}

override fun dispatchDraw(canvas: Canvas) {
val applyMinEdgeFading = fadingEdge.isMinFadingEdgeRequired(this)
val applyMaxEdgeFading = fadingEdge.isMaxFadingEdgeRequired(this)
if (!applyMaxEdgeFading && !applyMinEdgeFading) {
super.dispatchDraw(canvas)
return
}
val minFadeLength = if (applyMinEdgeFading) fadingEdge.minShaderLength else 0
val maxFadeLength = if (applyMaxEdgeFading) fadingEdge.maxShaderLength else 0
val minEdge = fadingEdge.getMinEdge(this)
val maxEdge = fadingEdge.getMaxEdge(this)

val save = canvas.save()
fadingEdge.clip(minEdge, maxEdge, applyMinEdgeFading, applyMaxEdgeFading, canvas, this)
super.dispatchDraw(canvas)
if (minFadeLength > 0) {
fadingEdge.drawMin(canvas, this)
}
if (maxFadeLength > 0) {
fadingEdge.drawMax(canvas, this)
}
canvas.restoreToCount(save)
}

/**
* Sets the strategy for calculating extra layout space.
*
Expand Down Expand Up @@ -402,6 +451,81 @@ open class DpadRecyclerView @JvmOverloads constructor(
*/
fun isLayoutEnabled(): Boolean = requireLayout().isLayoutEnabled()

/**
* Enables fading out the min edge to transparent.
* @param enable true if edge fading should be enabled for the left or top of the layout
*/
fun enableMinEdgeFading(enable: Boolean) {
fadingEdge.enableMinEdgeFading(enable, this)
}

/**
* @return true if edge fading is enabled for the left or top of the layout
*/
fun isMinEdgeFadingEnabled(): Boolean = fadingEdge.isFadingMinEdge

/**
* Sets the length of the fading effect applied to the min edge in pixels
*/
fun setMinEdgeFadingLength(@Px length: Int) {
fadingEdge.setMinEdgeFadingLength(length, this)
}

/**
* See: [setMinEdgeFadingLength]
*/
fun getMinEdgeFadingLength(): Int = fadingEdge.minShaderLength

/**
* Sets the start position of the fading effect applied to the min edge in pixels.
* Default is 0, which means that the fading effect starts from the min edge (left or top)
*/
fun setMinEdgeFadingOffset(@Px offset: Int) {
fadingEdge.setMinEdgeFadingOffset(offset, this)
}

/**
* See: [setMinEdgeFadingOffset]
*/
fun getMinEdgeFadingOffset(): Int = fadingEdge.minShaderOffset

/**
* Enables fading out the max edge to transparent.
* @param enable true if edge fading should be enabled for the right or bottom of the layout
*/
fun enableMaxEdgeFading(enable: Boolean) {
fadingEdge.enableMaxEdgeFading(enable, this)
}

/**
* @return true if edge fading is enabled for the right or bottom of the layout
*/
fun isMaxEdgeFadingEnabled(): Boolean = fadingEdge.isFadingMaxEdge

/**
* Sets the length of the fading effect applied to the max edge in pixels
*/
fun setMaxEdgeFadingLength(@Px length: Int) {
fadingEdge.setMaxEdgeFadingLength(length, this)
}

/**
* See: [setMaxEdgeFadingLength]
*/
fun getMaxEdgeFadingLength(): Int = fadingEdge.maxShaderLength

/**
* Sets the length of the fading effect applied to the min edge in pixels
*/
fun setMaxEdgeFadingOffset(@Px offset: Int) {
fadingEdge.setMaxEdgeFadingOffset(offset, this)
}

/**
* See: [setMaxEdgeFadingOffset]
*/
fun getMaxEdgeFadingOffset(): Int = fadingEdge.maxShaderOffset

/**
* Enables or disables the default rule of drawing the selected view after all other views.
* Default is true
Expand Down Expand Up @@ -1007,7 +1131,7 @@ open class DpadRecyclerView @JvmOverloads constructor(
&& position != NO_POSITION
&& position == getSelectedPosition()
) {
pivotLayoutManager?.removeCurrentViewHolderSelection()
pivotLayoutManager?.removeCurrentViewHolderSelection()
}
}
}
Expand Down
Loading

0 comments on commit 29ddde5

Please sign in to comment.