1010import android .support .v7 .widget .LinearLayoutManager ;
1111import android .support .v7 .widget .RecyclerView ;
1212import android .util .AttributeSet ;
13+ import android .util .Log ;
1314import android .view .animation .AccelerateDecelerateInterpolator ;
1415import android .view .animation .AccelerateInterpolator ;
1516import android .view .animation .Interpolator ;
@@ -77,7 +78,23 @@ protected void setup ( Context context, @Nullable AttributeSet attrs ) {
7778 setHasFixedSize (true );
7879 setHorizontalScrollBarEnabled (false );
7980
80- setFocusedPosition (0 , false );
81+ setFocusedPosition (0 , false , true );
82+ }
83+
84+ protected int adjustPositionToCenterIfNeeded (int inputPosition ) {
85+ if ( inputPosition != focusedPosition && layoutManager != null && layoutManager .areCellsUniform () && layoutManager .getUniformCellWidth () != 0 ) {
86+ boolean scrollingRight = inputPosition > focusedPosition ;
87+ float cellsInView = ((float ) getMeasuredWidth () / (float ) layoutManager .getUniformCellWidth ());
88+ int cellsToCenter = (int ) Math .floor ((cellsInView / 2.0f ));
89+ int offset = (scrollingRight ? 1 : -1 ) * cellsToCenter ;
90+ int adjustedPosition = Math .min (inputPosition + offset , getAdapter ().getItemCount () - 1 );
91+
92+ if ( adjustedPosition >= 0 && inputPosition >= offset ) {
93+ return adjustedPosition ;
94+ }
95+ }
96+
97+ return inputPosition ;
8198 }
8299
83100 public void setFocusedPosition ( int position , boolean animated ) {
@@ -89,20 +106,23 @@ public void setFocusedPosition ( int position, boolean animated, boolean silentl
89106 onFocusedPositionChangedListener .onFocusedPositionChanged (focusedPosition , position );
90107 }
91108
92- boolean requestedPositionIsVisible = position >= getChildAdapterPosition ( getChildAt ( 0 )) && position <= getChildAdapterPosition ( getChildAt ( getChildCount () - 1 ) );
109+ int adjustedScrollTarget = adjustPositionToCenterIfNeeded ( position );
93110
94- // @TODO, enhance this by attempting to center the focused position.
95- if (requestedPositionIsVisible && animated ) {
111+ if (requestedPositionIsVisible (position ) && requestedPositionIsVisible (adjustedScrollTarget ) && animated ) {
96112 deweyDecorator .startAnimation (focusedPosition , position );
97113 } else if (animated ) {
98- smoothScrollToPosition (position );
114+ smoothScrollToPosition (adjustedScrollTarget );
99115 } else {
100- scrollToPosition (position );
116+ scrollToPosition (adjustedScrollTarget );
101117 }
102118
103119 focusedPosition = position ;
104120 }
105121
122+ public boolean requestedPositionIsVisible ( int position ) {
123+ return position >= getChildAdapterPosition (getChildAt (0 )) && position <= getChildAdapterPosition (getChildAt (getChildCount () - 1 ));
124+ }
125+
106126 @ Override
107127 public void setAdapter ( Adapter adapter ) {
108128 super .setAdapter (adapter );
0 commit comments