嗨,你終於來啦 ~ 等你很久啦~ 喜歡的小夥伴歡迎關注,我會按期分享Android知識點及解析,還會不斷更新的BATJ面試專題,歡迎你們前來探討交流,若有好的文章也歡迎投稿android
RecyclerView是Google在API 21下support.V7包裏的控件,用來替代ListView。
官網對RecycleView的描述爲:A flexible view for providing a limited window into a large data set。面試
想使用RecycleView,必定要在build.gradle中引入compile 'com.android.support:recyclerview-v7:24.0.0'依賴。數組
不過我認爲Recycleview的ItemDecoration很是強大,你可使用它實現listview的分割線,懸浮窗,甚至一些很是炫的動畫~bash
Goods goods1 = new Goods("人氣TOP", "正果拿鐵1", "Y27", "默認:大/單糖/熱");
Goods goods99 = new Goods("人氣TOP", "正果拿鐵2", "Y27", "默認:大/單糖/熱");
Goods goods91 = new Goods("人氣TOP", "正果拿鐵3", "Y27", "默認:大/單糖/熱");
Goods goods2 = new Goods("大師咖啡", "拿鐵", "Y27", "默認:大/單糖/熱");
Goods goods3 = new Goods("大師咖啡", "香草拿鐵", "Y24", "默認:大/單糖/熱");
Goods goods4 = new Goods("大師咖啡", "焦糖拿鐵", "Y26", "默認:大/半糖/熱");
List<Goods> list = new ArrayList<>();複製代碼
第一個必須預留,當前位置的name和前一個不相等則爲預留空間
@Override
public boolean isParent(int position) {
if (position == 0) return true;
if (!list.get(position).getType().equals(list.get(position - 1).getType()))
return true;
return false;
}
//是否爲當前最後一個item
protected boolean lastOneInGroup(int position) {
String parentName = mDecorListener.parentName(position);
String nextGroupName;
try {
nextGroupName = mDecorListener.parentName(position + 1);
} catch (Exception e) {
nextGroupName = null;
}
if (nextGroupName == null) {
return false;
}
return !TextUtils.equals(parentName, nextGroupName);//與下一行的name不同說明當前是最後一行
}
由上isParent判斷是第一個的返回你要預留的高度大小,不然爲不須要空間0
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
int position = parent.getChildAdapterPosition(view);
if (parent.getLayoutManager() instanceof LinearLayoutManager && mDecorListener.isParent(position)) {
outRect.top = decorationHeight;
return;
}
outRect.top = 0;
}
複製代碼
@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDrawOver(c, parent, state);
final int itemCount = state.getItemCount(); 所有item的數量
final int childCount = parent.getChildCount(); 可看見的排除懸停的分割線的個數
final int left = parent.getPaddingLeft();
final int right = parent.getWidth() - parent.getPaddingRight();
for (int i = 0; i < childCount; i++) {
View childView = parent.getChildAt(i);
int position = parent.getChildAdapterPosition(childView);//就是當前可見每一行的position,從0開始
//默認第一個就是有個Group
if (mDecorListener.isParent(position) || i == 0) {//中第一個位置和可見的第一個纔有這個懸停
//繪製懸浮,
int bottom = Math.max(decorationHeight, (childView.getTop() + parent.getPaddingTop()));
//決定當前頂部第一個懸浮Group的bottom,拿到item高度和規定高度對比,只是選擇一個合適的高度定義分割線
if (position + 1 < itemCount) {
//下一組的第一個View接近頭部
int viewBottom = childView.getBottom();
if (lastOneInGroup(position) && viewBottom < bottom) {
bottom = viewBottom; //若是這個關掉,會覆蓋,頂上去效果失去,其實viewBottom逐漸變爲0,這樣動態的放置即將消失的懸浮攔,看上去就是下一個懸浮攔頂上來的
}
}
drawDecoration(c, position, left, right, bottom, parent);
stickyHeaderPosArray.put(position, bottom);
}
}
}
private void drawDecoration(Canvas c, int position, int left, int right, int bottom, RecyclerView parent) {
c.drawRect(left, bottom - decorationHeight, right, bottom, mGroutPaint);
Paint.FontMetrics fm = mTextPaint.getFontMetrics();
//文字豎直居中顯示
float baseLine = bottom - (decorationHeight - (fm.bottom - fm.top)) / 2 - fm.bottom;
//獲取文字寬度
mSideMargin = Math.abs(mSideMargin);
c.drawText(mDecorListener.parentName(position), left + mSideMargin, baseLine, mTextPaint);//x軸,baseLine
Rect rect = new Rect();//爲了獲得當前text的屬性
mTextPaint.getTextBounds(mDecorListener.parentName(position), 0, mDecorListener.parentName(position).length(), rect);
//繪製那條橫線
c.drawLine(left + mSideMargin * 2 + rect.width(), baseLine - rect.height() / 2, parent.getWidth() -
mSideMargin, baseLine - rect.height() / 2, mTextPaint);
}
複製代碼