解析一個Github上的項目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,并實現(xiàn)頂部實現(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)容铃彰。因為這里頂部標(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)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市无拗,隨后出現(xiàn)的幾起案子带到,更是在濱河造成了極大的恐慌,老刑警劉巖英染,帶你破解...
    沈念sama閱讀 217,542評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件揽惹,死亡現(xiàn)場離奇詭異被饿,居然都是意外死亡,警方通過查閱死者的電腦和手機搪搏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評論 3 394
  • 文/潘曉璐 我一進店門狭握,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人慕嚷,你說我怎么就攤上這事哥牍。” “怎么了喝检?”我有些...
    開封第一講書人閱讀 163,912評論 0 354
  • 文/不壞的土叔 我叫張陵嗅辣,是天一觀的道長。 經(jīng)常有香客問我挠说,道長澡谭,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,449評論 1 293
  • 正文 為了忘掉前任损俭,我火速辦了婚禮蛙奖,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘杆兵。我一直安慰自己雁仲,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,500評論 6 392
  • 文/花漫 我一把揭開白布琐脏。 她就那樣靜靜地躺著攒砖,像睡著了一般。 火紅的嫁衣襯著肌膚如雪日裙。 梳的紋絲不亂的頭發(fā)上吹艇,一...
    開封第一講書人閱讀 51,370評論 1 302
  • 那天,我揣著相機與錄音昂拂,去河邊找鬼受神。 笑死,一個胖子當(dāng)著我的面吹牛格侯,可吹牛的內(nèi)容都是我干的鼻听。 我是一名探鬼主播,決...
    沈念sama閱讀 40,193評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼联四,長吁一口氣:“原來是場噩夢啊……” “哼撑碴!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起碎连,我...
    開封第一講書人閱讀 39,074評論 0 276
  • 序言:老撾萬榮一對情侶失蹤灰羽,失蹤者是張志新(化名)和其女友劉穎驮履,沒想到半個月后鱼辙,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體廉嚼,經(jīng)...
    沈念sama閱讀 45,505評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,722評論 3 335
  • 正文 我和宋清朗相戀三年倒戏,在試婚紗的時候發(fā)現(xiàn)自己被綠了怠噪。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,841評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡杜跷,死狀恐怖傍念,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情葛闷,我是刑警寧澤憋槐,帶...
    沈念sama閱讀 35,569評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站淑趾,受9級特大地震影響阳仔,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜扣泊,卻給世界環(huán)境...
    茶點故事閱讀 41,168評論 3 328
  • 文/蒙蒙 一近范、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧延蟹,春花似錦评矩、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至俯萌,卻和暖如春果录,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背咐熙。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評論 1 269
  • 我被黑心中介騙來泰國打工弱恒, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人棋恼。 一個月前我還...
    沈念sama閱讀 47,962評論 2 370
  • 正文 我出身青樓返弹,卻偏偏與公主長得像,于是被迫代替她去往敵國和親爪飘。 傳聞我的和親對象是個殘疾皇子义起,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,781評論 2 354

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