編輯:關於Android編程
ps:好久都沒有寫博客了,今天正好比較空,就來寫一篇,好像這才是第二篇,不過不要在意這些細節啦。
:
美女圖片都是 熊(百)掌(度)找的,如果有涉及到您的權益,請及時聯系我進行刪除。
就是這樣的效果,這張圖片因為某些原因,已經經過ps修改,請見諒我ps功底差!
第二個Item因為需要,固定添加了paddingTZ喎?/kf/ware/vc/" target="_blank" class="keylink">vcKGjPC9wPg0KPGgyIGlkPQ=="一些說明">一些說明
剛開始在網上找這種效果的實現,也在論壇上提過問。都沒有能解決問題。
其實瀑布流是很好實現的。主要是中間圓點讓人十分蛋疼。
最開始有考慮過幾種解決方式
發現都是用使用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布局:
Activity/Fragment:
<framelayout android:background="#DDD" android:clipchildren="false" android:cliptopadding="false" android:layout_height="match_parent" android:layout_width="match_parent">
</framelayout>
這裡在在FrameLayout和RecyclerView上添加android:clipChildren=”false”屬性是很有必要的,不然Item中的效果可能發揮不出來。
Item:
標准Item:
YearItem:
<framelayout android:clipchildren="false" android:cliptopadding="false" android:layout_height="wrap_content" android:layout_width="match_parent" android:paddingbottom="@dimen/dp10" android:paddingtop="@dimen/dp10" xmlns:android="http://schemas.android.com/apk/res/android">
</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 {
private LayoutInflater mInflater;
private final ArrayList datas;
public BigEventAdapter(Context mCtx, ArrayList 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方法實現的有點丑陋,並且影響了效率,如果你有更好的歡迎留言建議。
前言最近Android studio(下文簡稱AS)官方發布了正式版,目前火得不行。個人認為主要是因為android是google自家的產品,AS也是他自己搞的IDE,以
0 史前階段: Android操作系統最早的一個版本是2007年11月5日發布的Android beta,作為一個面向開發者的軟件開發
Android快捷方式解密Android快捷方式作為Android設備的殺手锏技能,一直都是非常重要的一個功能,也正是如此,各種流氓App也不斷通過快捷方式霸占著這樣一個
本文實例講述了Android編程實現自定義toast。分享給大家供大家參考,具體如下:效果圖:代碼://自定義布局的toastcustomViewToast.setOnC