解析一個Github上的項(xiàng)目ListViewFilter之二

代碼解析

IPinnedHeader.java

該接口的設(shè)計目的主要是建立一個顯示在頂部的標(biāo)頭并添加其狀態(tài)屬性。該狀態(tài)屬性主要用于輔助屏幕滾動時設(shè)置相關(guān)行為。代碼的解析如下:

import android.view.View;

/**

 * Adapter interface. The list adapter must implement this interface.

 */

public interface IPinnedHeader {

/**

 * Pinned header state: don't show the header.

 */
//頂部已經(jīng)顯示該標(biāo)頭時或者當(dāng)ListView中item的數(shù)量為0時,不動態(tài)載入標(biāo)頭布局。此時頂部標(biāo)頭的狀態(tài)為@PINNED_HEADER_GONE
public static final int PINNED_HEADER_GONE = 0;

/**

 * Pinned header state: show the header at the top of the list.

 */
//標(biāo)頭的狀態(tài)為可見
public static final int PINNED_HEADER_VISIBLE = 1;

/**

 * Pinned header state: show the header. If the header extends beyond

 * the bottom of the first shown element, push it up and clip.

 */
//頂部的標(biāo)頭的下一行是另一個標(biāo)頭時,頂部標(biāo)頭的狀態(tài)為@PINNED_HEADER_PUSHED_UP
public static final int PINNED_HEADER_PUSHED_UP = 2;

/**

 * Computes the desired state of the pinned header for the given

 * position of the first visible list item. Allowed return values are

 * {@link #PINNED_HEADER_GONE}, {@link #PINNED_HEADER_VISIBLE} or

 * {@link #PINNED_HEADER_PUSHED_UP}.

 */
//獲取頂部標(biāo)頭狀態(tài)
int getPinnedHeaderState(int position);

/**

 * Configures the pinned header view to match the first visible list item.

 *

 * @param header pinned header view.

 * @param position position of the first visible list item.

 * @param alpha fading of the header view, between 0 and 255.

 */
//配置頂部標(biāo)頭
void configurePinnedHeader(View header, int position);

}

代碼解析

IIndexBarFilter.java

該接口的設(shè)計用于輔助左邊索引條的檢索,按下索引條時,顯示相應(yīng)位置的預(yù)覽字母。手指離開時,Listview顯示相應(yīng)位置的內(nèi)容。

public interface IIndexBarFilter {

void filterList(float sideIndexY,int position,String previewText);

}

代碼解析

PinnedHeaderListView .java

該類用于建立ListView,并實(shí)現(xiàn)頂部實(shí)現(xiàn)分組標(biāo)頭的功能。

/*

 * A ListView that maintains a header pinned at the top of the list. The

 * pinned header can be pushed up and dissolved as needed.

 */

public class PinnedHeaderListView extends ListView implements IIndexBarFilter {

// interface object that configure pinned header view position in list view

IPinnedHeader mAdapter;

// view objects

View mHeaderView,mIndexBarView,mPreviewTextView;

// flags that decide view visibility

boolean mHeaderVisibility=false;

boolean mPreviewVisibility=false;

// initially show index bar view with it's content

boolean mIndexBarVisibility=true;

// context object

Context mContext;

// view height and width

int mHeaderViewWidth,

mHeaderViewHeight,

mIndexBarViewWidth,

mIndexBarViewHeight,

mIndexBarViewMargin,

mPreviewTextViewWidth,

mPreviewTextViewHeight;

// touched index bar Y axis position used to decide preview text view position

float mIndexBarY;

public PinnedHeaderListView(Context context) {

super(context);

this.mContext = context;

}

public PinnedHeaderListView(Context context, AttributeSet attrs) {

super(context, attrs);

this.mContext = context;

}

public PinnedHeaderListView(Context context, AttributeSet attrs, int defStyle) {

super(context, attrs, defStyle);

this.mContext = context;

}

//為ListView配置適配器
@Override

public void setAdapter(ListAdapter adapter) {

this.mAdapter = (PinnedHeaderAdapter)adapter;

super.setAdapter(adapter);

}

public void setPinnedHeaderView(View headerView) {

this.mHeaderView = headerView;

// Disable vertical fading when the pinned header is present

// TODO change ListView to allow separate measures for top and bottom fading edge;

// in this particular case we would like to disable the top, but not the bottom edge.
//FadingEdge用于暗示ListView上方或者下方還有更多內(nèi)容。因?yàn)檫@里頂部標(biāo)頭滾定,所以將其長度設(shè)置為0
if (mHeaderView != null) {

setFadingEdgeLength(0);

}

}

public void setIndexBarView(View indexBarView) {

mIndexBarViewMargin = (int)mContext.getResources().getDimension(R.dimen.index_bar_view_margin);

this.mIndexBarView = indexBarView;

}

public void setPreviewView(View previewTextView) {

this.mPreviewTextView=previewTextView;

}
//重寫@onMeasure方法,測量ListView中各組件的大小。
@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

if (mHeaderView != null) {

measureChild(mHeaderView, widthMeasureSpec, heightMeasureSpec);

mHeaderViewWidth = mHeaderView.getMeasuredWidth();

mHeaderViewHeight = mHeaderView.getMeasuredHeight();

}

if (mIndexBarView != null && mIndexBarVisibility) {

measureChild(mIndexBarView, widthMeasureSpec, heightMeasureSpec);

mIndexBarViewWidth = mIndexBarView.getMeasuredWidth();

mIndexBarViewHeight = mIndexBarView.getMeasuredHeight();

}

if (mPreviewTextView != null && mPreviewVisibility) {

measureChild(mPreviewTextView, widthMeasureSpec, heightMeasureSpec);

mPreviewTextViewWidth = mPreviewTextView.getMeasuredWidth();

mPreviewTextViewHeight = mPreviewTextView.getMeasuredHeight();

}

}
//重寫@onLayout方法,將測量后的組件放置在指定位置。
@Override

protected void onLayout(boolean changed, int left, int top, int right, int bottom) {

super.onLayout(changed, left, top, right, bottom);

if (mHeaderView != null) {

mHeaderView.layout(0, 0, mHeaderViewWidth, mHeaderViewHeight);

configureHeaderView(getFirstVisiblePosition());

}

if (mIndexBarView != null && mIndexBarVisibility) {

mIndexBarView.layout(getMeasuredWidth()- mIndexBarViewMargin - mIndexBarViewWidth, mIndexBarViewMargin

, getMeasuredWidth()- mIndexBarViewMargin, getMeasuredHeight()- mIndexBarViewMargin);

}

if (mPreviewTextView != null && mPreviewVisibility) {

mPreviewTextView.layout(mIndexBarView.getLeft()-mPreviewTextViewWidth, (int)mIndexBarY-(mPreviewTextViewHeight/2)

, mIndexBarView.getLeft(), (int)(mIndexBarY-(mPreviewTextViewHeight/2))+mPreviewTextViewHeight);

}

}

public void setIndexBarVisibility(Boolean isVisible) {

if(isVisible) {

mIndexBarVisibility=true;

}

else {

mIndexBarVisibility=false;

}

}

private void setPreviewTextVisibility(Boolean isVisible) {

if(isVisible) {

mPreviewVisibility=true;

}

else {

mPreviewVisibility=false;

}

}

public void configureHeaderView(int position) {

if (mHeaderView == null) {

return;

}

int state = mAdapter.getPinnedHeaderState(position);

switch (state) {

case IPinnedHeader.PINNED_HEADER_GONE: 

mHeaderVisibility = false;

break;

case IPinnedHeader.PINNED_HEADER_VISIBLE: 

if (mHeaderView.getTop() != 0) {

mHeaderView.layout(0, 0, mHeaderViewWidth, mHeaderViewHeight);

}

mAdapter.configurePinnedHeader(mHeaderView, position);

mHeaderVisibility = true;

break;

case IPinnedHeader.PINNED_HEADER_PUSHED_UP: 

View firstView = getChildAt(0);

int bottom = firstView.getBottom();

// int itemHeight = firstView.getHeight();

int headerHeight = mHeaderView.getHeight();

int y;

if (bottom < headerHeight) {

y = (bottom - headerHeight);

}

else {

y = 0;

}

if (mHeaderView.getTop() != y) {

mHeaderView.layout(0, y, mHeaderViewWidth, mHeaderViewHeight + y);

}

mAdapter.configurePinnedHeader(mHeaderView, position);

mHeaderVisibility = true;

break;

}

}

//由于ListView是ViewGroup的子類,須重寫dispathDraw方法
@Override

protected void dispatchDraw(Canvas canvas) {

super.dispatchDraw(canvas);// draw list view elements (zIndex == 1)

if (mHeaderView != null && mHeaderVisibility) {

drawChild(canvas, mHeaderView, getDrawingTime()); // draw pinned header view (zIndex == 2)

}

if (mIndexBarView != null && mIndexBarVisibility) {

drawChild(canvas, mIndexBarView, getDrawingTime()); // draw index bar view (zIndex == 3)

}

if (mPreviewTextView != null && mPreviewVisibility) {

drawChild(canvas, mPreviewTextView, getDrawingTime()); // draw preview text view (zIndex == 4)

}

}

//重寫onTouchEvent方法
@Override

public boolean onTouchEvent(MotionEvent ev) {

if (mIndexBarView != null && ((IndexBarView)mIndexBarView).onTouchEvent(ev)) {

setPreviewTextVisibility(true);

return true;

}

else {

setPreviewTextVisibility(false);

return super.onTouchEvent(ev);

}

}

@Override

public void filterList(float indexBarY, int position,String previewText) {

this.mIndexBarY=indexBarY;

if(mPreviewTextView instanceof TextView)

((TextView)mPreviewTextView).setText(previewText);

setSelection(position);

}

}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容