Android 中轴时光轴
ps:好久都没有写博客了,今天正好比较空,就来写一篇,好像这才是第二篇,不过不要在意这些细节啦。
转载请注明出处:http://blog.youkuaiyun.com/qq_15736263/article/details/51941066
效果图
:
美女图片都是 熊(百)掌(度)找的,如果有涉及到您的权益,请及时联系我进行删除。
就是这样的效果,这张图片因为某些原因,已经经过ps修改,请见谅我ps功底差!
第二个Item因为需要,固定添加了paddingTop。
一些说明
刚开始在网上找这种效果的实现,也在论坛上提过问。都没有能解决问题。
其实瀑布流是很好实现的。主要是中间圆点让人十分蛋疼。
最开始有考虑过几种解决方式
使用网络上开源的瀑布流控件,然后进行重写:
发现都是用使用GridView或者是ListView或者ViewGroup实现的,使用的都是类似LinnearLayout的布局方式,修改起来比较困难,牵扯面较多,然后放弃了。
使用RecyclerView然后自定义LayoutManager:
其实这个是最好的实现方式,但是因为时间太赶,加上网络上相关资源太少。只好去参考官方StaggeredGridLayoutManager了。
然后就源码旅游了。
@Override
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
onLayoutChildren(recycler, state, true);
}
private void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state,
boolean shouldCheckForGaps) {
final AnchorInfo anchorInfo = mAnchorInfo;
anchorInfo.reset();
if (mPendingSavedState != null || mPendingScrollPosition != NO_POSITION) {
if (state.getItemCount() == 0) {
removeAndRecycleAllViews(recycler);
return;
}
}
if (mPendingSavedState != null) {
applyPendingSavedState(anchorInfo);
} else {
resolveShouldLayoutReverse();
anchorInfo.mLayoutFromEnd = mShouldReverseLayout;
}
updateAnchorInfoForLayout(state, anchorInfo);
if (mPendingSavedState == null) {
if (anchorInfo.mLayoutFromEnd != mLastLayoutFromEnd ||
isLayoutRTL() != mLastLayoutRTL) {
mLazySpanLookup.clear();
anchorInfo.mInvalidateOffsets = true;
}
}
if (getChildCount() > 0 && (mPendingSavedState == null ||
mPendingSavedState.mSpanOffsetsSize < 1)) {
if (anchorInfo.mInvalidateOffsets) {
for (int i = 0; i < mSpanCount; i++) {
// Scroll to position is set, clear.
mSpans[i].clear();
if (anchorInfo.mOffset != INVALID_OFFSET) {
mSpans[i].setLine(anchorInfo.mOffset);
}
}
} else {
for (int i = 0; i < mSpanCount; i++) {
mSpans[i].cacheReferenceLineAndClear(mShouldReverseLayout, anchorInfo.mOffset);
}
}
}
detachAndScrapAttachedViews(recycler);
mLayoutState.mRecycle = false;
mLaidOutInvalidFullSpan = false;
updateMeasureSpecs(mSecondaryOrientation.getTotalSpace());
updateLayoutState(anchorInfo.mPosition, state);
if (anchorInfo.mLayoutFromEnd) {
// Layout start.
setLayoutStateDirection(LAYOUT_START);
fill(recycler, mLayoutState, state);
// Layout end.
setLayoutStateDirection(LAYOUT_END);
mLayoutState.mCurrentPosition = anchorInfo.mPosition + mLayoutState.mItemDirection;
fill(recycler, mLayoutState, state);
} else {
// Layout end.
setLayoutStateDirection(LAYOUT_END);
fill(recycler, mLayoutState, state);
// Layout start.
setLayoutStateDirection(LAYOUT_START);
mLayoutState.mCurrentPosition = anchorInfo.mPosition + mLayoutState.mItemDirection;
fill(recycler, mLayoutState, state);
}
repositionToWrapContentIfNecessary();
if (getChildCount() > 0) {
if (mShouldReverseLayout) {
fixEndGap(recycler, state, true);
fixStartGap(recycler, state, false);
} else {
fixStartGap(recycler, state, true);
fixEndGap(recycler, state, false);
}
}
boolean hasGaps = false;
if (shouldCheckForGaps && !state.isPreLayout()) {
final boolean needToCheckForGaps = mGapStrategy != GAP_HANDLING_NONE
&& getChildCount() > 0
&& (mLaidOutInvalidFullSpan || hasGapsToFix() != null);
if (needToCheckForGaps) {
removeCallbacks(mCheckForGapsRunnable);
if (checkForGaps()) {
hasGaps = true;
}