package com.wasu.cs.widget; import android.content.Context; import android.graphics.Rect; import android.support.v4.view.ViewCompat; import android.support.v7.widget.RecyclerView; import android.util.AttributeSet; import android.view.Gravity; import android.view.View; public class ChildrenFavRecyclerView extends RecyclerView { private Context mContext; public ChildrenFavRecyclerView(Context context) { super(context); init(context); } public ChildrenFavRecyclerView(Context context, AttributeSet attrs) { super(context, attrs); init(context); } public ChildrenFavRecyclerView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context); } private void init(Context context) { this.mContext = context; } /*@Override public void smoothScrollBy(int dx, int dy) { if (hasFocus()) { if (dx > 0) { int mdx = (int) (dx +mContext.getResources().getDimension(R.dimen.d_10dp)); super.smoothScrollBy(mdx, dy); } else if (dx < 0) { int mdx = (int) (dx - mContext.getResources().getDimension(R.dimen.d_10dp)); super.smoothScrollBy(mdx, dy); } else { Log.d("danxx", "FRV dy--->" + dx); } } // super.smoothScrollBy(dx ,dy); }*/ /** * center scroll * @param child * @param rect * @param immediate * @return */ // @Override // public boolean requestChildRectangleOnScreen(View child, Rect rect, boolean immediate) { // final int parentLeft = getPaddingLeft(); // final int parentTop = getPaddingTop(); // final int parentRight = getWidth() - getPaddingRight(); // final int parentBottom = getHeight() - getPaddingBottom(); // final int childLeft = child.getLeft()-child.getPaddingLeft() + rect.left; // final int childTop = child.getTop() + rect.top; // final int childRight = childLeft + rect.width(); // final int childBottom = childTop + rect.height(); // // final int offScreenLeft = Math.min(0, childLeft - parentLeft); // final int offScreenTop = Math.min(0, childTop - parentTop); // final int offScreenRight = Math.max(0, childRight - parentRight); // final int offScreenBottom = Math.max(0, childBottom - parentBottom); // // int centerTop = getHeight() / 2 - child.getHeight() / 2; // int centerBottom = getHeight() / 2 + child.getHeight() / 2; // int centerLeft = getWidth() / 2 - child.getWidth() / 2; // int centerRight = getWidth() / 2 + child.getWidth() / 2; // // int position = getChildAdapterPosition(child); // int childCount = getAdapter().getItemCount(); // // int dx = 0; // if (position == 0 || position == childCount - 1){ // // Favor the "start" layout direction over the end when bringing one side or the other // // of a large rect into view. If we decide to bring in end because start is already // // visible, limit the scroll such that start won't go out of bounds. // if (ViewCompat.getLayoutDirection(this) == ViewCompat.LAYOUT_DIRECTION_RTL) { // dx = offScreenRight != 0 ? offScreenRight // : Math.max(offScreenLeft, childRight - parentRight); // } else { // dx = offScreenLeft != 0 ? offScreenLeft // : Math.min(childLeft - parentLeft, offScreenRight); // } // }else { // switch (Gravity.CENTER_HORIZONTAL){ // case Gravity.CENTER_HORIZONTAL: // case Gravity.CENTER: // dx = childLeft - centerLeft; // break; // case Gravity.LEFT: // dx = childLeft - parentLeft; // break; // } // } // // int dy = 0; // if (position == 0 || position == childCount - 1){ // // Favor bringing the top into view over the bottom. If top is already visible and // // we should scroll to make bottom visible, make sure top does not go out of bounds. // dy = offScreenTop != 0 ? offScreenTop // : Math.min(childTop - parentTop, offScreenBottom); // }else { // switch (Gravity.CENTER_VERTICAL){ // case Gravity.CENTER_VERTICAL: // case Gravity.CENTER: // dy = childTop - centerTop; // break; // } // } // // if (dx != 0 || dy != 0) { // if (immediate) { // scrollBy(dx, dy); // } else { // smoothScrollBy(dx, dy); // } // return true; // } // return false; // } @Override public boolean requestChildRectangleOnScreen(View child, Rect rect, boolean immediate) { final int parentLeft = getPaddingLeft(); final int parentTop = getPaddingTop(); final int parentRight = getWidth() - getPaddingRight(); final int parentBottom = getHeight() - getPaddingBottom(); final int childLeft = child.getLeft() + rect.left; final int childTop = child.getTop() + rect.top; final int childRight = childLeft + rect.width(); final int childBottom = childTop + rect.height(); final int offScreenLeft = Math.min(0, childLeft - parentLeft ); final int offScreenTop = Math.min(0, childTop - parentTop ); final int offScreenRight = Math.max(0, childRight - parentRight ); final int offScreenBottom = Math.max(0, childBottom - parentBottom ); final boolean canScrollHorizontal = getLayoutManager().canScrollHorizontally(); final boolean canScrollVertical = getLayoutManager().canScrollVertically(); // Favor the "start" layout direction over the end when bringing one side or the other // of a large rect into view. If we decide to bring in end because start is already // visible, limit the scroll such that start won't go out of bounds. int dx; if(canScrollHorizontal) { if (ViewCompat.getLayoutDirection(this) == ViewCompat.LAYOUT_DIRECTION_RTL) { dx = offScreenRight != 0 ? offScreenRight : Math.max(offScreenLeft, childRight - parentRight); } else { dx = offScreenLeft != 0 ? offScreenLeft : Math.min(childLeft - parentLeft, offScreenRight); } //增加预滚动 if(dx > 0){ dx += dx/2; }else if(dx <0) { dx += dx/2; } } else { dx = 0; } // Favor bringing the top into view over the bottom. If top is already visible and // we should scroll to make bottom visible, make sure top does not go out of bounds. int dy; if(canScrollVertical) { dy = offScreenTop != 0 ? offScreenTop : Math.min(childTop - parentTop, offScreenBottom); //增加预滚动 } else { dy = 0; } if (dx != 0 || dy != 0) { if (immediate) { scrollBy(dx, dy); } else { smoothScrollBy(dx, dy); } return true; } // 重绘是为了选中item置顶,具体请参考getChildDrawingOrder方法 // postInvalidate(); return false; } }