Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 中軸時光軸

Android 中軸時光軸

編輯:關於Android編程

ps:好久都沒有寫博客了,今天正好比較空,就來寫一篇,好像這才是第二篇,不過不要在意這些細節啦。

效果圖

效果圖
美女圖片都是 熊(百)掌(度)找的,如果有涉及到您的權益,請及時聯系我進行刪除。
就是這樣的效果,這張圖片因為某些原因,已經經過ps修改,請見諒我ps功底差!
第二個Item因為需要,固定添加了paddingTZ喎?/kf/ware/vc/" target="_blank" class="keylink">vcKGjPC9wPg0KPGgyIGlkPQ=="一些說明">一些說明

剛開始在網上找這種效果的實現,也在論壇上提過問。都沒有能解決問題。
其實瀑布流是很好實現的。主要是中間圓點讓人十分蛋疼。

最開始有考慮過幾種解決方式

使用網絡上開源的瀑布流控件,然後進行重寫:

發現都是用使用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;
            }
        }
        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:加上水平有點爛啦。

我的實現方式:

簡述:
因為上面的各種問題,主要是項目時間不夠,想想用low的方法好了。直接用RecyclerView和StaggeredGridLayoutManager實現他,在onBindViewHolder用ViewHolder.post(Runnable) 在頂層用RelativeLayout動態添加View,並且綁定RecyclerView的滑動監聽,進行滑動管理,自己進行維護生成的View的各種狀態,包括進行緩存。但是這種效率真的是太低了,而且滑動的View復用處理不好的話,很容易就添加了N個圓點,只是不在屏幕內而且,而且這麼寫,圓點基本上就只能做成一種。項目中又需要不止一種類的圓點,存在一種年份的Item,和正常的Item帶箭頭的、顏色、大小都不一樣的。
後來想起來一個神奇的屬性,這個屬性經常被人遺忘,因為他確實用的不多,但是確實好用。‘android:clipChildren=”false”’與之相配套的是’ android:clipToPadding=”false”’關於這兩個屬性這裡就不多做介紹了,相關效果請自行熊(百)掌(度)。

代碼:

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方法實現的有點丑陋,並且影響了效率,如果你有更好的歡迎留言建議。
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved