一個RecyclerView實現QQ空間相簿佈局
看到這佈局自然會想到用RecyclerView來做,用ItemDecoration繪製日期那條分割線,每行3列的GridLayoutManager
但是有個問題,如果不是正好3列、怎麼去控制末尾的留白呢?
我的實現思路是這樣的:
GridLayoutManager中有個setSpanSizeLookup方法,getSpanSize返回值就是控制每行有幾列的
gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
return setSpanSize(position, mAdapter.getDatas());
}
});
不瞭解的可以轉至RecyclerView通過GridLayoutManager實現多樣式佈局
也就是說使用該方法我可以控制每一行的列數、只要我再控制其長度就OK了
在資料實體中新增一個value、用來記錄當前圖片和前面差了幾個空白,從而確定留白的距離
private int setSpanSize(int position, List<AlbumBean> listEntities) {
int count;
int d;
if ((position + 1 < listEntities.size()) && position > 0) {
if (!listEntities.get(position).getSubId().equals(listEntities.get(position + 1).getSubId())) {
mAdapter.getItem(position + 1).value = 2 - (mAdapter.getItem(position).value + position) % 3
+ mAdapter.getItem(position).value;
d = 2 - (mAdapter.getItem(position).value + position) % 3;
if (d == 2) {
count = 3;
} else if (d == 1) {
count = 2;
} else {
count = 1;
}
} else {
mAdapter.getItem(position + 1).value = mAdapter.getItem(position).value;
count = 1;
}
} else if (position == 0) {
if (mAdapter.getDatas().size() > 1) {
if ((!listEntities.get(position).getSubId().equals(listEntities.get(position + 1).getSubId()))) {
mAdapter.getItem(1).value = 2;
count = 3;
} else {
count = 1;
mAdapter.getItem(1).value = 0;
}
} else {
count = 1;
}
} else {
count = 1;
}
return count;
}
public class EaseItemDecoration extends RecyclerView.ItemDecoration {
private final Drawable mDivider;
private List<? extends AlbumBean> mDatas;
private Paint mPaint;
private Rect mBounds;
private int mTitleHeight;
private static int COLOR_TITLE_BG = Color.parseColor("#ffffff");
private static int COLOR_TITLE_FONT = Color.parseColor("#333333");
private static int mTitleFontSize;
private int width;
private static final int[] ATTRS = new int[]{
android.R.attr.listDivider
};
public EaseItemDecoration(Context context, List<? extends AlbumBean> datas) {
super();
mDatas = datas;
mPaint = new Paint();
mBounds = new Rect();
final TypedArray a = context.obtainStyledAttributes(ATTRS);
mDivider = a.getDrawable(0);
mTitleHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 90, context.getResources().getDisplayMetrics());
mTitleFontSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 16, context.getResources().getDisplayMetrics());
mPaint.setTextSize(mTitleFontSize);
mPaint.setAntiAlias(true);
width = SmallUtil.getScreenWidth(context) / 3;
}
public void setmDatas(List<? extends AlbumBean> mDatas) {
this.mDatas = mDatas;
}
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDraw(c, parent, state);
final int left = parent.getPaddingLeft();
final int right = parent.getWidth() - parent.getPaddingRight();
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
.getLayoutParams();
int position = params.getViewLayoutPosition();
//我記得Rv的item position在重置時可能為-1.保險點判斷一下吧
if (position > -1) {
if (position == 0) {
drawTitleArea(c, left, right, child, params, position);
} else {
if (null != mDatas.get(position).getSubId() && !mDatas.get(position).getSubId().equals(mDatas.get(position - 1).getSubId())) {
//不為空 且跟前一個tag不一樣了,說明是新的分類,也要title
drawTitleArea(c, left, right, child, params, position);
} else {
}
}
}
}
}
/**
* 繪製Title區域背景和文字的方法
*/
private void drawTitleArea(Canvas c, int left, int right, View child, RecyclerView.LayoutParams params, int position) {//最先呼叫,繪製在最下層
mPaint.setColor(COLOR_TITLE_BG);
c.drawRect(left, child.getTop() - params.topMargin - mTitleHeight, right, child.getTop() - params.topMargin, mPaint);
mPaint.setColor(COLOR_TITLE_FONT);
mPaint.setTextSize(SmallUtil.sp2px(17));
String date = mDatas.get(position).getTitle();
mPaint.getTextBounds(date, 0, date.length(), mBounds);
c.drawText(date, (width * 3) / 2 - mBounds.width() / 2, child.getTop() - params.topMargin - mTitleHeight / 2, mPaint);
}
@Override
public void onDrawOver(Canvas c, final RecyclerView parent, RecyclerView.State state) {//最後呼叫 繪製在最上層
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
int position = ((RecyclerView.LayoutParams) view.getLayoutParams()).getViewLayoutPosition();
if (position > -1 && position < mDatas.size()) {
if (position + 1 < mDatas.size()) {
if (null != mDatas.get(position).getSubId() && !mDatas.get(position).getSubId().equals(mDatas.get(position + 1).getSubId())) {
int d = 2 - (mDatas.get(position).value + position) % 3;
if (isNewLine(position, mDatas)) {
outRect.set(0, mTitleHeight, width * d + mDivider.getIntrinsicHeight(), mDivider.getIntrinsicHeight());
} else {
outRect.set(0, 0, width * d + mDivider.getIntrinsicHeight(), mDivider.getIntrinsicHeight());
}
} else {
if (isNewLine(position, mDatas)) {
outRect.set(0, mTitleHeight, mDivider.getIntrinsicHeight(), mDivider.getIntrinsicHeight());
} else {
outRect.set(0, 0, mDivider.getIntrinsicHeight(), mDivider.getIntrinsicHeight());
}
}
} else {
if (isNewLine(position, mDatas)) {
outRect.set(0, mTitleHeight, mDivider.getIntrinsicHeight(), mDivider.getIntrinsicHeight());
} else {
outRect.set(0, 0, mDivider.getIntrinsicHeight(), mDivider.getIntrinsicHeight());
}
}
}
}
private boolean isNewLine(int position, List<? extends AlbumBean> mDatas) {
boolean isNew = false;
if (position == 0 || position == 1 || position == 2)
return true;
int size = position > 2 ? position - 3 : 0;
for (int i = size; i < position; i++) {
if (null != mDatas.get(i).getSubId() && !mDatas.get(i).getSubId().equals(mDatas.get(i + 1).getSubId())) {
isNew = true;
break;
}
}
return isNew;
}
}
完成效果:
Github地址:https://github.com/forvv231/QQAlbum
安裝包下載:https://fir.im/QQAlbum
相關文章
- QQ空間相簿批量下載【原圖】
- 一個好用簡單的佈局空間EasyUIUI
- Android實現RecyclerView巢狀流式佈局AndroidView巢狀
- 如何批量把下載QQ空間相簿圖片
- 使用 yogaKit 實現一個資訊流佈局
- 使用 Flutter 實現一個走馬燈佈局Flutter
- 10-記憶體空間佈局記憶體
- 詳解RecyclerView的預佈局View
- Android 實現一個通用的圓角佈局Android
- 多人對抗類遊戲的10個空間佈局原則遊戲
- 基於Python的QQ空間相簿中的所有照片下載器Python
- QQ空間前端工程前端
- 聯合辦公空間,平臺化佈局
- 佈局總結-水平居中佈局的實現
- css佈局,左右固定中間自適應實現CSS
- 快速利用RecyclerView的LayoutManager搭建流式佈局View
- 聖盃佈局進階版-flex佈局實現Flex
- 一種子圖佈局方法的實現
- 一個常用的佈局
- QQ正式推出“超級QQ秀”佈局元宇宙元宇宙
- 「前端面試題系列2」如何實現一個聖盃佈局?前端面試題
- CSS佈局–聖盃佈局和雙飛翼佈局以及使用Flex實現聖盃佈局CSSFlex
- CSS多種佈局方式自我實現-水平佈局(二)CSS
- 支援粘性Item的RecyclerView佈局管理器View
- 爬蟲實戰 -- QQ空間自動點贊爬蟲
- 一個RecyclerView實現多級摺疊列表(二)View
- 一個RecyclerView實現多級摺疊列表(TreeRecyclerView)View
- jQuery實現瀑布流佈局jQuery
- Grid 拖拽佈局實現
- 第十五篇:C程式的儲存空間佈局C程式
- 三種免費批量下載QQ空間相簿方法-2018.05.20親測有效
- qq相簿批量下載
- 如何實現兩欄佈局,右側自適應?三欄佈局中間自適應呢?
- canvas打造QQ空間低俗廣告Canvas
- 進一步瞭解flex佈局—來實現這些常見佈局吧Flex
- css佈局-實現左中右佈局的5種方式CSS
- 使用 CSS columns 佈局來實現自動分組佈局CSS
- RecyclerView進階(一)RecyclerView實現雙列表聯動View