标签:
ps:好久都没有写博客了,今天正好比较空,就来写一篇,好像这才是第二篇,不过不要在意这些细节啦。
转载请注明出处:http://blog.csdn.net/qq_15736263/article/details/51941066
:
美女图片都是 熊(百)掌(度)找的,如果有涉及到您的权益,请及时联系我进行删除。
就是这样的效果,这张图片因为某些原因,已经经过ps修改,请见谅我ps功底差!
第二个Item因为需要,固定添加了paddingTop。
刚开始在网上找这种效果的实现,也在论坛上提过问。都没有能解决问题。
其实瀑布流是很好实现的。主要是中间圆点让人十分蛋疼。
最开始有考虑过几种解决方式
发现都是用使用GridView或者是ListView或者ViewGroup实现的,使用的都是类似LinnearLayout的布局方式,修改起来比较困难,牵扯面较多,然后放弃了。
其实这个是最好的实现方式,但是因为时间太赶,加上网络上相关资源太少。只好去参考官方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;
}
}
mPendingScrollPosition = NO_POSITION;
mPendingScrollPositionOffset = INVALID_OFFSET;
}
mLastLayoutFromEnd = anchorInfo.mLayoutFromEnd;
mLastLayoutRTL = isLayoutRTL();
mPendingSavedState = null; // we don‘t need this anymore
if (hasGaps) {
onLayoutChildren(recycler, state, false);
}
}
这里牵扯的东西非常多,因为StaggeredGridLayoutManager不单单考虑两列的情况。这个类的代码量在3000行,牵扯的到的同包的类也很多,这么算下来,代码量就远远不止3000行了,得需要点时间进行研究了。但是真的时间太赶了,只能另寻它路了。ps:加上水平有点烂啦。
代码:
XML布局:
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#DDD"
android:clipChildren="false"
android:clipToPadding="false">
<View
android:layout_width="1dp"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal"
android:background="#DFDAD7" />
<android.support.v7.widget.RecyclerView
android:id="@+id/view1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false" />
</FrameLayout>
这里在在FrameLayout和RecyclerView上添加android:clipChildren=”false”属性是很有必要的,不然Item中的效果可能发挥不出来。
Item:
标准Item:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipChildren="false"
android:clipToPadding="false"
android:orientation="horizontal">
<ImageView
android:id="@+id/view1"
android:layout_width="30dp"
android:layout_height="20dp"
android:layout_marginLeft="@dimen/_dp8"
android:layout_marginTop="30dp"
android:clipChildren="false"
android:clipToPadding="false"
android:contentDescription="@string/app_name"
android:src="@mipmap/right" />
<ImageView
android:id="@+id/view3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/dp10"
android:layout_marginTop="@dimen/dp10"
android:layout_weight="1"
android:background="@drawable/progress_dialog"
android:contentDescription="@string/app_name"
android:scaleType="fitCenter" />
<ImageView
android:id="@+id/view2"
android:layout_width="30dp"
android:layout_height="20dp"
android:layout_marginRight="@dimen/_dp8"
android:layout_marginTop="30dp"
android:clipChildren="false"
android:clipToPadding="false"
android:contentDescription="@string/app_name"
android:src="@mipmap/letf" />
</LinearLayout>
YearItem:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipChildren="false"
android:clipToPadding="false"
android:paddingBottom="@dimen/dp10"
android:paddingTop="@dimen/dp10">
<ImageView
android:id="@id/view1"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_gravity="left"
android:layout_marginLeft="-10dp"
android:clipChildren="false"
android:clipToPadding="false"
android:contentDescription="@string/app_name"
android:src="@mipmap/year" />
<TextView
android:id="@id/textV1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="30dp"
android:layout_marginRight="30dp"
android:background="@drawable/year"
android:gravity="center"
android:minHeight="20dp"
android:paddingBottom="5dp"
android:paddingLeft="20dp"
android:paddingRight="20dp"
android:paddingTop="5dp"
android:textColor="@color/colorPrimary" />
<ImageView
android:id="@id/view2"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_gravity="right"
android:layout_marginRight="-10dp"
android:clipChildren="false"
android:clipToPadding="false"
android:contentDescription="@string/app_name"
android:src="@mipmap/year" />
</FrameLayout>
这里的view1和View2代表了左右两个箭头及圆点。中间的View3可以替换成任意的View(Layout也行),@dimen/_dp8是-8dp,让View位置超出父View的可见位置。
Java:
Activity/Fragment:
public class Activity_Fragment {
private RecyclerView mRecyclerView;
private Adapter mAdapter;
onCreate/onCreateView(){
mRecyclerView = (RecyclerView) rootView.findViewById(R.id.view1);
mRecyclerView.setAdapter(adapter);
StaggeredGridLayoutManager df = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
df.invalidateSpanAssignments();
//↑↑↑这里很重要,不然Item会自动换位置,会导致圆圈和箭头的方向不对
mRecyclerView.setLayoutManager(df);
mAdapter= new Adapter(Context,List);
mRecyclerView.setAdaper(mAdapter);
}
}
Adapter:
public class Adapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private LayoutInflater mInflater;
private final ArrayList<Data> datas;
public BigEventAdapter(Context mCtx, ArrayList<Data> dataList) {
super();
mInflater = LayoutInflater.from(mCtx);
this.datas= dataList;
}
@Override
public int getItemViewType(int position) {
return datas.get(position).getDtype().ordinal();
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewgroup, int viewType) {
if (type == DTYPE.ITEM.ordinal()) {
rootView = mInflater.inflate(R.layout.view_item_add, viewgroup, false);
return new ItemViewHolder(rootView);
}
if (type == DTYPE.YEAR.ordinal()) {
rootView = mInflater.inflate(R.layout.view_item_year, viewgroup, false);
return new TextViewHolder(rootView);
}
}
/**
* 判读左右显示相应的圆圈及箭头
*/
private void isLeftOfRight(final CardViewHolder viewHolder) {
((ViewGroup) viewHolder.itemView).setClipChildren(false);
viewHolder.itemView.post(new Runnable() {
@Override
public void run() {
int left = viewHolder.itemView.getLeft();
if (left == 0) {
viewHolder.itemArrow_Left.setVisibility(View.VISIBLE);
viewHolder.itemArrow_Right.setVisibility(View.INVISIBLE);
if (viewHolder.itemView instanceof FrameLayout) {
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) ((FrameLayout) viewHolder.itemView).getChildAt(1).getLayoutParams();
params.gravity = Gravity.RIGHT;
((FrameLayout) viewHolder.itemView).getChildAt(1).setLayoutParams(params);
}
} else {
if (viewHolder.itemView instanceof FrameLayout) {
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) ((FrameLayout) viewHolder.itemView).getChildAt(1).getLayoutParams();
params.gravity = Gravity.LEFT;
((FrameLayout) viewHolder.itemView).getChildAt(1).setLayoutParams(params);
}
viewHolder.itemArrow_Left.setVisibility(View.INVISIBLE);
viewHolder.itemArrow_Right.setVisibility(View.VISIBLE);
}
}
});
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
isLeftOfRight((CardViewHolder) viewHolder);
......
}
public class CardViewHolder extends RecyclerView.ViewHolder {
public ImageView itemArrow_Left;
public ImageView itemArrow_Right;
CardViewHolder(View layout) {
super(layout);
itemArrow_Left = (ImageView) layout.findViewById(R.id.view2);
itemArrow_Right = (ImageView) layout.findViewById(R.id.view1);
}
}
public class ItemViewHolder extends CardViewHolder {
public ImageView icon;
ItemViewHolder (View layout) {
super(layout);
icon = (ImageView) layout.findViewById(R.id.view3);
}
}
public class TextViewHolder extends CardViewHolder {
public TextView time;
TextViewHolder(View layout) {
super(layout);
time = (TextView) layout.findViewById(R.id.textV1);
}
}
}
Data.getDtype获取到的是一个枚举类型
现在唯一的问题是isLeftOfRight方法实现的有点丑陋,并且影响了效率,如果你有更好的欢迎留言建议。
标签:
原文地址:http://blog.csdn.net/qq_15736263/article/details/51941066