網(wǎng)上的城市選擇器很多蔼水,但還是親自動手實現(xiàn)一下,效果如下圖所示
思路:使用RecyclerView的吸附式ItemDecoration(覆寫onDrawOver方法),將分好組的城市的拼音首字母繪制到上面蚤假。觸摸右側(cè)的字母指示器IndicatorView控制RecyclerView滾動到哪個位置栏饮。
所以我們要解決的問題有:
1.RecyclerView吸附式ItemDdecoration
2.獲取漢字拼音的首字母
3.根據(jù)觸摸到的字母,指定Recycler View滾動到對應(yīng)的位置
4.自定義View繪制“熱門磷仰、A抡爹、B······Z”,重寫繪制方法芒划、測量方法冬竟,和觸摸方法。
一:吸附式ItemDecoration民逼。
在滑動的時候會依次調(diào)用onDraw和onDrawOver泵殴,其中onDraw是在ItemView的下層繪制,onDrawOver是在ItemView的上層繪制拼苍⌒ψ纾可以在onDraw中給每一個ItemView繪制分割線,繪制區(qū)域是一個矩形疮鲫,即ItemView的底邊距頂部的高度吆你,以及底邊的offset。在DrawOver中繪制每一組的標(biāo)題俊犯,標(biāo)題的高度會在getItemOffsets中設(shè)置妇多,為rect.top。標(biāo)題位置分為三種情況燕侠,1.跟隨Group第一個View移動者祖。2.在頂部不動。3.頂部的標(biāo)題被下一組的標(biāo)題頂上去绢彤,即跟隨該組最后一個View的底部移動七问。具體情況具體分析。
public class StickyItemDecoration extends RecyclerView.ItemDecoration {
private final Paint mPaint;
private final Paint mDividerPaint;
private OnDrawOverListener mSticky;
private int mGroupTitleHeight;
public StickyItemDecoration(Context context, OnDrawOverListener sticky) {
mSticky = sticky;
mPaint = new Paint();
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(Color.BLUE);
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setTextSize(dp2px(context, 16));
mGroupTitleHeight = dp2px(context, 20);
mDividerPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
}
@Override
public void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
super.onDraw(c, parent, state);
int childCount=parent.getChildCount();
RecyclerView.LayoutManager manager = parent.getLayoutManager();
for (int i = 0; i < childCount; i++) {
View child=parent.getChildAt(i);
int left=parent.getPaddingLeft() + manager.getLeftDecorationWidth(child);
int right=parent.getWidth()-parent.getPaddingRight() - manager.getRightDecorationWidth(child);
int top=child.getTop()-1;
int bottom=child.getTop();
//Item分割線
c.drawRect(left,top,right,bottom,mDividerPaint);
}
}
@Override
public void onDrawOver(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
super.onDrawOver(c, parent, state);
RecyclerView.LayoutManager manager = parent.getLayoutManager();
int childCount = parent.getChildCount();
String preGroupName;
String groupName = "";
for (int i = 0; i < childCount; i++) {
View child = parent.getChildAt(i);
int childAdapterPosition = parent.getChildAdapterPosition(child);
preGroupName = groupName;
groupName = mSticky.getGroupName(childAdapterPosition);
//和上一個標(biāo)題做對比茫舶,不一樣就需要繪制
if (preGroupName == groupName) {
continue;
}
int startX = parent.getPaddingLeft() + (manager != null ? manager.getLeftDecorationWidth(child) : 0);
Paint.FontMetricsInt fontMetrics = mPaint.getFontMetricsInt();
//標(biāo)題跟隨整個Group滑動
if (child.getTop() > mGroupTitleHeight) {
int startY = child.getTop() - (mGroupTitleHeight + fontMetrics.descent + fontMetrics.ascent) / 2;
c.drawText(groupName, startX, startY, mPaint);
} else {
//位于頂部的GroupTitle械巡,在頂部不用動,除非下邊的標(biāo)題頂上來了
Log.e("TAG", "....." + childAdapterPosition);
if (childAdapterPosition + 1 <= state.getItemCount()) {
//child后面的View的是下一組的第一個饶氏,并且這個child底部露出的高度已經(jīng)小于標(biāo)題高度了讥耗,這時候標(biāo)題會被頂上去
if (mSticky.isGroupFirst(childAdapterPosition + 1) && child.getBottom() < mGroupTitleHeight) {
int startY = (child.getBottom() - (mGroupTitleHeight + fontMetrics.descent + fontMetrics.ascent) / 2);
c.drawText(groupName, startX, startY, mPaint);
} else {
//在頂部不用動
int startY = (mGroupTitleHeight - fontMetrics.descent - fontMetrics.ascent) / 2;
c.drawText(groupName, startX, startY, mPaint);
}
}
}
}
}
@Override
public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
Log.e("TAG", "getItemOffsets");
int childAdapterPosition = parent.getChildAdapterPosition(view);
if (mSticky.isGroupFirst(childAdapterPosition)) outRect.top = mGroupTitleHeight;
outRect.bottom = 1;
}
public interface OnDrawOverListener {
String getGroupName(int position);
boolean isGroupFirst(int position);
}
public static int dp2px(Context context, int dp) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.getResources().getDisplayMetrics());
}
}
二:獲取漢字拼音的首字
https://www.cnblogs.com/pxblog/p/10604003.html
import java.io.UnsupportedEncodingException;
/**
* 取得給定漢字串的首字母串,即聲母串
* Title: ChineseCharToEn
*
* @date 注:只支持GB2312字符集中的漢字
*/
public final class ChineseCharToEn {
private final static int[] li_SecPosValue = {1601, 1637, 1833, 2078, 2274,
2302, 2433, 2594, 2787, 3106, 3212, 3472, 3635, 3722, 3730, 3858,
4027, 4086, 4390, 4558, 4684, 4925, 5249, 5590};
private final static String[] lc_FirstLetter = {"a", "b", "c", "d", "e",
"f", "g", "h", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s",
"t", "w", "x", "y", "z"};
/**
* 取得給定漢字串的首字母串,即聲母串
*
* @param str 給定漢字串
* @return 聲母串
*/
public static String getAllFirstLetter(String str) {
if (str == null || str.trim().length() == 0) {
return "";
}
String _str = "";
for (int i = 0; i < str.length(); i++) {
_str = _str + getFirstLetter(str.substring(i, i + 1));
}
return _str;
}
/**
* 取得給定漢字的首字母,即聲母
*
* @param chinese 給定的漢字
* @return 給定漢字的聲母
*/
public static String getFirstLetter(String chinese) {
if (chinese == null || chinese.trim().length() == 0) {
return "";
}
chinese = conversionStr(chinese, "GB2312", "ISO8859-1");
if (chinese.length() > 1) // 判斷是不是漢字
{
int li_SectorCode = (int) chinese.charAt(0); // 漢字區(qū)碼
int li_PositionCode = (int) chinese.charAt(1); // 漢字位碼
li_SectorCode = li_SectorCode - 160;
li_PositionCode = li_PositionCode - 160;
int li_SecPosCode = li_SectorCode * 100 + li_PositionCode; // 漢字區(qū)位碼
if (li_SecPosCode > 1600 && li_SecPosCode < 5590) {
for (int i = 0; i < 23; i++) {
if (li_SecPosCode >= li_SecPosValue[i]
&& li_SecPosCode < li_SecPosValue[i + 1]) {
chinese = lc_FirstLetter[i];
break;
}
}
} else // 非漢字字符,如圖形符號或ASCII碼
{
chinese = conversionStr(chinese, "ISO8859-1", "GB2312");
chinese = chinese.substring(0, 1);
}
}
return chinese;
}
/**
* 字符串編碼轉(zhuǎn)換
*
* @param str 要轉(zhuǎn)換編碼的字符串
* @param charsetName 原來的編碼
* @param toCharsetName 轉(zhuǎn)換后的編碼
* @return 經(jīng)過編碼轉(zhuǎn)換后的字符串
*/
private static String conversionStr(String str, String charsetName, String toCharsetName) {
try {
str = new String(str.getBytes(charsetName), toCharsetName);
} catch (UnsupportedEncodingException ex) {
System.out.println("字符串編碼轉(zhuǎn)換異常:" + ex.getMessage());
}
return str;
}
public static void main(String[] args) {
System.out.println("獲取拼音首字母:" + getAllFirstLetter("大中國南昌中大china"));
}
}
三:RecyclerView滾動到指定位置pos
http://www.reibang.com/p/6d5ecfdbb615
四:自定義字母指示器IndicatorView
1.繪制data中的字符串:熱門、A嚷往、B葛账、C······Z
2.測量大小onMeasure
3.重寫onTouch方法,通過觸摸的位置的坐標(biāo)皮仁,計算出觸摸的是哪個字母,并傳入回調(diào)接口中
package com.app.cityselector.view;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;
import java.util.List;
public class IndicatorView extends View {
private Context context;
private List<String> data;
private Paint paint;
private float ascent;
private float descent;
private float textHeight;
private float textGap;
private float charWidth;
private int paddingLeft;
private int paddingRight;
public IndicatorView(Context context) {
this(context, null);
}
public IndicatorView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public IndicatorView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.context = context;
initView();
}
private void initView() {
paint = new Paint();
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
paint.setTextSize(9 * metrics.density);
ascent = paint.getFontMetrics().ascent;
descent = paint.getFontMetrics().descent;
textHeight = Math.abs(ascent - descent);
charWidth = paint.measureText("A");
}
public void setData(List<String> data) {
this.data = data;
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
float y = 0;
y = -ascent + textGap / 2;
float x = (getWidth() - paddingLeft - paddingRight - charWidth) / 2;
for (int i = 0; i < data.size(); i++) {
canvas.drawText(data.get(i), i == 0 ? 0 : x, y, paint);
y += textHeight + textGap;
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int width = widthSize;
int height = heightSize;
paddingLeft = getPaddingLeft();
paddingRight = getPaddingRight();
//wrap_content:計算得出最小的寬高,
//match_content或具體值:撐滿父容器贷祈,空出來的地方作為item間隔平均分布到item之間
if (widthMode == MeasureSpec.EXACTLY) {
width = widthSize;
} else {
width = (int) paint.measureText("熱門") + paddingLeft + paddingRight;
}
if (heightMode == MeasureSpec.EXACTLY) {
height = heightSize;
textGap = (height - textHeight * data.size()) / data.size();
} else {
height = (int) (Math.abs(paint.getFontMetrics().ascent - paint.getFontMetrics().descent) * data.size());
}
setMeasuredDimension(width, height);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float y = event.getY();
int index = (int) (y / (textGap + textHeight));
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
if (onItemTouched != null) {
onItemTouched.onTouched(data.get(index), index);
}
break;
case MotionEvent.ACTION_UP:
if (onItemTouched != null) {
onItemTouched.onTouchedUp(data.get(index), index);
}
break;
}
return true;
}
OnItemTouched onItemTouched;
public void setOnItemTouched(OnItemTouched onItemTouched) {
this.onItemTouched = onItemTouched;
}
public interface OnItemTouched {
void onTouched(String s, int pos);
void onTouchedUp(String s, int pos);
}
}
以上三步做好后趋急,就完成了準(zhǔn)備工作。
CitySelectorView中使用RecyclerView展示數(shù)據(jù)势誊,根據(jù)右側(cè)的字母指示器指定RecyclerView滾動到指定pos呜达。
實體類:
public class CityBean {
private int id;
private String code;
private String name;
//getter and setter
......
}
CityAdapter:展示的數(shù)據(jù)有熱門城市和普通城市Item,所以要區(qū)分兩類itemType
package com.app.cityselector.view.adapter;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.app.cityselector.R;
import com.app.cityselector.bean.CityBean;
import java.util.List;
public class CityAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
public static final int TYPE_HOT_CITY = 1;
public static final int TYPE_CITY_ITEM = 2;
private final LayoutInflater inflater;
Context context;
//熱門城市
List<CityBean> hotCitys;
//全部城市
List<CityBean> allCitys;
public CityAdapter(Context context) {
this.context = context;
inflater = LayoutInflater.from(context);
}
public void setHotCitys(List<CityBean> hotCitys) {
this.hotCitys = hotCitys;
}
public void setAllCitys(List<CityBean> allCitys) {
this.allCitys = allCitys;
}
@Override
public int getItemViewType(int position) {
if (hotCitys != null && position == 0) {
return TYPE_HOT_CITY;
} else {
return TYPE_CITY_ITEM;
}
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int type) {
if (type == TYPE_HOT_CITY) {
return new HotCityViewHolder(inflater.inflate(R.layout.item_hot_city, viewGroup, false));
} else if (type == TYPE_CITY_ITEM) {
return new CityItemViewHolder(inflater.inflate(R.layout.item_city, viewGroup, false));
}
return null;
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int i) {
if (viewHolder instanceof HotCityViewHolder) {
HotCityViewHolder hotCityViewHolder = (HotCityViewHolder) viewHolder;
hotCityViewHolder.bindData(hotCitys);
} else if (viewHolder instanceof CityItemViewHolder) {
CityItemViewHolder cityItemViewHolder = (CityItemViewHolder) viewHolder;
CityBean cityBean = allCitys.get(hotCitys != null ? i - 1 : i);
cityItemViewHolder.bindData(cityBean);
}
}
@Override
public int getItemCount() {
int count = 0;
if (hotCitys != null) {
count++;
}
if (allCitys != null) {
count += allCitys.size();
}
return count;
}
static class CityItemViewHolder extends RecyclerView.ViewHolder {
private TextView tvCityName;
public CityItemViewHolder(@NonNull View itemView) {
super(itemView);
tvCityName = itemView.findViewById(R.id.tv_city_name);
}
public void bindData(CityBean cityBean) {
tvCityName.setText(cityBean.getName());
}
}
static class HotCityViewHolder extends RecyclerView.ViewHolder {
private LinearLayout llHotCityContainer;
//熱門城市的列數(shù)
int hotColumn = 3;
public void setHotColumn(int hotColumn) {
this.hotColumn = hotColumn;
}
public HotCityViewHolder(@NonNull View itemView) {
super(itemView);
llHotCityContainer = itemView.findViewById(R.id.gl_hot_city_container);
}
//展示熱門城市
public void bindData(List<CityBean> cityBeans) {
llHotCityContainer.removeAllViews();
Context context = itemView.getContext();
int halfMargin = context.getResources().getDimensionPixelSize(R.dimen.base_margin_half);
int paddingVertical = context.getResources().getDimensionPixelSize(R.dimen.padding_vertical);
int row = cityBeans.size() / hotColumn;
for (int i = 0; i < row + 1; i++) {
LinearLayout llRow = new LinearLayout(context);
llRow.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
llRow.setPadding(halfMargin, halfMargin, halfMargin, halfMargin);
for (int j = 0; j < hotColumn; j++) {
int index = row * i + j;
if (index < cityBeans.size()) {
CityBean cityBean = cityBeans.get(index);
TextView textView = new TextView(context);
textView.setText(cityBean.getName());
textView.setBackgroundResource(R.drawable.bg_hot_city);
textView.setClickable(true);
textView.setPadding(0, paddingVertical, 0, paddingVertical);
textView.setGravity(Gravity.CENTER);
textView.setTextColor(context.getResources().getColor(R.color.colorText));
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14);
//setLayoutParams
LinearLayout.LayoutParams textLayoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
textLayoutParams.weight = 1;
textLayoutParams.leftMargin = halfMargin;
textLayoutParams.rightMargin = halfMargin;
textView.setLayoutParams(textLayoutParams);
llRow.addView(textView);
}
}
llHotCityContainer.addView(llRow);
}
}
}
}
重點來了粟耻,當(dāng)觸摸右邊的字母指示器時查近,根據(jù)字母獲取RecyclerView中的城市名稱的拼音的出現(xiàn)該字母的第一個位置,如果找不到挤忙,就定位到上一個字母出現(xiàn)的位置霜威。
/**
* 根據(jù)ABC...Z獲取第一次出現(xiàn)的pos
*
* @param s
* @return
*/
private int getFirstPos(String s) {
if ("熱門".equals(s)) {
return 0;
}
int pos = 0;
if (hotCity != null) {
pos++;
}
int firstPos = 0;
for (int i = 0; i < allCity.size(); i++) {
//相等
String firstLetter = ChinessToEn.getFirstLetter(allCity.get(i).getName()).toUpperCase();
int compare = firstLetter.compareToIgnoreCase(s);
if (compare == 0) {
firstPos = i;
break;
} else if (compare < 0) {
if (i > 1 && !allCity.get(i).getName().equals(allCity.get(i - 1).getName())) {
firstPos = i;
}
} else {
break;
}
}
pos += firstPos;
return pos;
}
獲取到位置后,就可以混動RecyclerView了
public static void moveToPosition(LinearLayoutManager manager, RecyclerView mRecyclerView, int n) {
int firstItem = manager.findFirstVisibleItemPosition();
int lastItem = manager.findLastVisibleItemPosition();
if (n <= firstItem) {
mRecyclerView.scrollToPosition(n);
} else if (n <= lastItem) {
int top = mRecyclerView.getChildAt(n - firstItem).getTop();
mRecyclerView.scrollBy(0, top);
} else {
mRecyclerView.scrollToPosition(n);
}
}
CitySelectorView完成代碼:
public class CitySelectorView extends FrameLayout implements View.OnClickListener {
private Context context;
private RecyclerView recyclerView;
private IndicatorView indicatorView;
private TextView tvCenter;
private LinearLayoutManager layoutManager;
private CityAdapter adapter;
private List<CityBean> hotCity;
private List<CityBean> allCity;
private String[] indecatorData = new String[]{"熱門", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"};
public void setHotCity(List<CityBean> hotCity) {
this.hotCity = hotCity;
}
public void setAllCity(List<CityBean> allCity) {
this.allCity = allCity;
}
public void notifyDataSetChanged() {
adapter.setHotCitys(hotCity);
adapter.setAllCitys(allCity);
adapter.notifyDataSetChanged();
}
public CitySelectorView(@NonNull Context context) {
this(context, null);
}
public CitySelectorView(@NonNull Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public CitySelectorView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.context = context;
init();
}
private void init() {
LayoutInflater.from(context).inflate(R.layout.view_city_selector, this, true);
recyclerView = findViewById(R.id.recycler_city);
tvCenter = findViewById(R.id.tv_center);
indicatorView = findViewById(R.id.indicator);
//set RecyclerView
layoutManager = new LinearLayoutManager(context);
recyclerView.setLayoutManager(layoutManager);
//吸附式
recyclerView.addItemDecoration(new StickyItemDecoration(context, new ISticky() {
@Override
public boolean isGroupFirst(int pos) {
if (hotCity != null) {
if (pos == 0) return true;
if (allCity != null && allCity.size() != 0) {
if (pos == 1) {
return true;
} else {
return !ChinessToEn.getFirstLetter(allCity.get(pos - 1).getName()).equals(ChinessToEn.getFirstLetter(allCity.get(pos - 2).getName()));
}
}
return false;
} else {
if (pos == 0) return true;
if (allCity != null && allCity.size() != 0) {
return !ChinessToEn.getFirstLetter(allCity.get(pos).getName()).equals(ChinessToEn.getFirstLetter(allCity.get(pos - 1).getName()));
}
return false;
}
}
@Override
public String getGroupTitle(int pos) {
if (hotCity != null) {
if (pos == 0) return "熱門";
if (allCity != null && allCity.size() != 0) {
return ChinessToEn.getFirstLetter(allCity.get(pos - 1).getName()).toUpperCase();
}
} else {
if (allCity != null && allCity.size() != 0) {
return ChinessToEn.getFirstLetter(allCity.get(pos).getName()).toUpperCase();
}
}
return null;
}
}));
adapter = new CityAdapter(context);
recyclerView.setAdapter(adapter);
indicatorView.setData(Arrays.asList(indecatorData));
indicatorView.setOnItemTouched(new IndicatorView.OnItemTouched() {
@Override
public void onTouched(String s, int pos) {
tvCenter.setVisibility(VISIBLE);
tvCenter.setText(s);
int firstPos = getFirstPos(s);
L.e(firstPos);
moveToPosition(layoutManager, recyclerView, firstPos);
}
@Override
public void onTouchedUp(String s, int pos) {
tvCenter.setVisibility(INVISIBLE);
}
});
}
@Override
public void onClick(View v) {
}
/**
* 根據(jù)ABC...Z獲取第一次出現(xiàn)的pos
*
* @param s
* @return
*/
private int getFirstPos(String s) {
if ("熱門".equals(s)) {
return 0;
}
int pos = 0;
if (hotCity != null) {
pos++;
}
int firstPos = 0;
for (int i = 0; i < allCity.size(); i++) {
//相等
String firstLetter = ChinessToEn.getFirstLetter(allCity.get(i).getName()).toUpperCase();
int compare = firstLetter.compareToIgnoreCase(s);
if (compare == 0) {
firstPos = i;
break;
} else if (compare < 0) {
if (i > 1 && !allCity.get(i).getName().equals(allCity.get(i - 1).getName())) {
firstPos = i;
}
} else {
break;
}
}
pos += firstPos;
return pos;
}
/**
* RecyclerView 移動到當(dāng)前位置册烈,
*
* @param manager 設(shè)置RecyclerView對應(yīng)的manager
* @param mRecyclerView 當(dāng)前的RecyclerView
* @param n 要跳轉(zhuǎn)的位置
*/
public static void moveToPosition(LinearLayoutManager manager, RecyclerView mRecyclerView, int n) {
int firstItem = manager.findFirstVisibleItemPosition();
int lastItem = manager.findLastVisibleItemPosition();
if (n <= firstItem) {
mRecyclerView.scrollToPosition(n);
} else if (n <= lastItem) {
int top = mRecyclerView.getChildAt(n - firstItem).getTop();
mRecyclerView.scrollBy(0, top);
} else {
mRecyclerView.scrollToPosition(n);
}
}
}