技術(shù)總結(jié)-2015.10.24

這倆周在做發(fā)表的相冊改版敢伸,今天總結(jié)一下其中用到的一些技術(shù)點(diǎn)

1袜匿、android:clipToPadding屬性的妙用

屬性的解釋:

Defines?whether?the?ViewGroup?will?clip?its?drawing?surface?so?as?to?exclude?the?padding?area.

定義了是否允許ViewGroup在padding中繪制醋拧。

該屬性的默認(rèn)值是true,即不允許艘绍。

使用場景:

1、設(shè)置ListView(或GridView等)首行或尾行距離頂部或底部有一段距離(padding)跟继,且在滑動時padding部分仍看到ListView內(nèi)容的效果密浑。

例:

android:layout_width="match_parent"

android:layout_height=“match_parent"

android:clipToPadding="false"

android:paddingTop="70dip"

android:paddingBottom="70dip"

/>

若不設(shè)置clipPadding為false,我們會直接看到ListView頭部和尾部占有70dp的padding,且在滑動過程中padding始終存在蛙婴,且在padding部分看不到ListView的內(nèi)容。

若設(shè)置clipPadding為false,滑動過程中在padding部分可以看到ListView的內(nèi)容,且有滑動到頂部才出現(xiàn)paddingTop 70dp,滑動到底部才出現(xiàn)paddingBottom 70dp的效果尔破。

以前為了達(dá)到這個效果街图,解決方法可能是在首行或尾行加上一個隱藏的View,或者是加HeaderView\FooterView來實現(xiàn)背传。比較麻煩。

2台夺、與ViewPager結(jié)合實現(xiàn)畫廊效果

畫廊效果:每次滑動只滑動一頁+ 滑動item居中 + 一屏顯示多個item

//緩存?3屏 ?左右拖動可以看到前后的圖片mViewPager.setOffscreenPageLimit(3);

//設(shè)置item之間的間距

//int?pageMargin?=?ScreenTools.instance(this).dip2px(-15);

//mViewPager.setPageMargin(pageMargin);

intpadding?=?ScreenTools.instance(this).dip2px(40);

mViewPager.setPadding(padding,0,padding,0);

mViewPager.setClipToPadding(false);

效果圖如下:

3径玖、網(wǎng)上有用android:clipChildren實現(xiàn)畫廊效果http://www.trinea.cn/android/viewpager-multi-fragment-effect/

android:clipChildren

屬性解釋:

Defines whether a child is limited to draw inside of its bounds or not.

用來定義他的子控件是否要在他應(yīng)有的邊界內(nèi)進(jìn)行繪制。

默認(rèn)值為true,即不允許進(jìn)行擴(kuò)展繪制颤介。

2梳星、ViewDragHelper

ViewDragHelper 是v4包中提供的一個用于解決界面控件拖拽移動問題的類,用這個類編寫自定義的ViewGroup,可很大程度上簡化了手勢處理過于復(fù)雜的問題滚朵。自己去處理onInterceptTouchEvent和onTouchEvent這兩個方法真的是一件很不容易的事

ViewDragHelper is a utility class for writing custom ViewGroups. It offers a number

of useful operations and state tracking for allowing a user to drag and reposition

views within their parent ViewGroup.

ViewDragHepler基本用法:

1冤灾、獲取ViewDragHelper的實例

ViewDragHelper.create(ViewGroup forParent, float sensitivity, ViewDragHelper.Callback cb);

參數(shù)1: 一個ViewGroup, 也就是ViewDragHelper將要用來拖拽誰下面的子view

參數(shù)2:靈敏度辕近,一般設(shè)置為1.0f就行

參數(shù)3:一個回調(diào)韵吨,用來處理拖動到位置

2、繼承ViewDragHelper.Callback類移宅,該類有個抽象方法:tryCaptureView(View view, int pointerId) 表示嘗試捕獲子view归粉,這里一定要返回true, 返回true表示允許漏峰。

3糠悼、重寫兩個方法Callback中int?clampViewPositionHorizontal(View child, int left, int dx)和intclampViewPositionVertical(View child, int left, int dx) 這兩個方法分別用來處理x方向和y方向的拖動的,返回值該child現(xiàn)在的位置浅乔。使用時要具體處理例如防止view超出邊界等倔喂。

4、重寫了Callback中的onViewReleased,處理放手后的操作靖苇,例根據(jù)滑動方向及滑動距離等調(diào)用settleCapturedViewAt方法回到指定的位置席噩,settleCapturedViewAt后要調(diào)用invalidate,因為其內(nèi)部使用的是mScroller.startScroll,所以別忘了需要invalidate()以及結(jié)合computeScroll方法一起贤壁。

5悼枢、重寫Callback中g(shù)etViewHorizontalDragRange和getViewVerticalDragRange,只有這兩個方法返回大于0view的onClick事件才能執(zhí)行芯砸。(如果子View不消耗事件萧芙,那么整個手勢(DOWN-MOVE*-UP)都是直接進(jìn)入onTouchEvent给梅,在onTouchEvent的DOWN的時候就確定了captureView假丧。如果消耗事件,那么就會先走onInterceptTouchEvent方法动羽,判斷是否可以捕獲包帚,而在判斷的過程中會去判斷另外兩個回調(diào)的方法:getViewHorizontalDragRange和getViewVerticalDragRange,只有這兩個方法返回大于0的值才能正常的捕獲运吓。)

6渴邦、重寫ViewGroup的onInterceptTouchEvent(MotionEvent ev)用來攔截事件

7疯趟、重寫ViewGroup的onTouchEvent(MotionEvent event) 在這里面只要做兩件事:mDragHelper.processTouchEvent(event);處理攔截到的事件,這個方法會在返回前分發(fā)事件谋梭;return true 表示消費(fèi)了事件信峻。

簡單的幾步就可以實現(xiàn)一個可以任意拖動到view了。

例子:

相片選擇模塊中底部的上下拖動抽屜效果及畫廊中圖片的拖動上滑刪除功能都是用ViewDragHelper來實現(xiàn)的

效果圖:畫廊拖動上滑刪除圖片

效果圖:底部上拉抽屜

3瓮床、PopupWindow?setBackgroundDrawbale()

PopupWindow大家經(jīng)常用盹舞,類似這樣

效果:點(diǎn)擊Popwindow外部區(qū)域可讓其消失

mAlbumPopupWindow=newPopupWindow(contentView,ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT,true);

mAlbumPopupWindow.setBackgroundDrawable(newColorDrawable(Color.TRANSPARENT));//加上這行的效果是點(diǎn)popupwindow的外邊也能dismiss

mAlbumPopupWindow.setOutsideTouchable(true);//外部區(qū)域可點(diǎn)擊

mAlbumPopupWindow.setTouchable(true);//window?可點(diǎn)擊

mAlbumPopupWindow.setFocusable(true);//獲得焦點(diǎn)?內(nèi)部可點(diǎn)擊

有個點(diǎn):PopupWindow setBackgroundDrawbale() 有什么作用?

為什么去掉這行隘庄,點(diǎn)擊外部區(qū)域踢步,Popupwindow就不會消失呢?

解惑:

如果有背景mBackground丑掺,則會在contentView外面包一層PopupViewContainer之后作為mPopupView获印,如果沒有背景,則直接用contentView作為mPopupView街州。

而這個PopupViewContainer是一個內(nèi)部私有類兼丰,它繼承了FrameLayout,在其中重寫了Key和Touch事件的分發(fā)處理唆缴。如果不設(shè)背景地粪,由于PopupView本身并沒有重寫Key和Touch事件的處理,所以如果沒有包這個外層容器類琐谤,點(diǎn)擊Back鍵或者外部區(qū)域是不會導(dǎo)致彈框消失的蟆技。

見源碼:

/**

*

Prepare?the?popup?by?embedding?in?into?a?new?ViewGroup?if?the

*?background?drawable?is?not?null.?If?embedding?is?required,?the?layout

*?parameters'?height?is?modified?to?take?into?account?the?background's

*?padding.

*

*@parampthe?layout?parameters?of?the?popup's?content?view

*/

private?voidpreparePopup(WindowManager.LayoutParams?p)?{

if(mContentView==null||mContext==null||mWindowManager==null)?{

throw?newIllegalStateException("You?must?specify?a?valid?content?view?by?"

+"calling?setContentView()?before?attempting?to?show?the?popup.");

}

if(mBackground!=null)?{

finalViewGroup.LayoutParams?layoutParams?=mContentView.getLayoutParams();

intheight?=?ViewGroup.LayoutParams.MATCH_PARENT;

if(layoutParams?!=null&&

layoutParams.height==?ViewGroup.LayoutParams.WRAP_CONTENT)?{

height?=?ViewGroup.LayoutParams.WRAP_CONTENT;

}

//?when?a?background?is?available,?we?embed?the?content?view

//?within?another?view?that?owns?the?background?drawable

PopupViewContainer?popupViewContainer?=newPopupViewContainer(mContext);

PopupViewContainer.LayoutParams?listParams?=newPopupViewContainer.LayoutParams(

ViewGroup.LayoutParams.MATCH_PARENT,height

);

popupViewContainer.setBackground(mBackground);

popupViewContainer.addView(mContentView,listParams);

mPopupView=?popupViewContainer;

}else{

mPopupView=mContentView;

}

mPopupView.setElevation(mElevation);

mPopupViewInitialLayoutDirectionInherited=

(mPopupView.getRawLayoutDirection()?==?View.LAYOUT_DIRECTION_INHERIT);

mPopupWidth=?p.width;

mPopupHeight=?p.height;

}

private?classPopupViewContainerextendsFrameLayout?{

private?static?finalStringTAG="PopupWindow.PopupViewContainer";

publicPopupViewContainer(Context?context)?{

super(context);

}

@Override

protected?int[]?onCreateDrawableState(intextraSpace)?{

if(mAboveAnchor)?{

//?1?more?needed?for?the?above?anchor?state

final?int[]?drawableState?=super.onCreateDrawableState(extraSpace?+1);

View.mergeDrawableStates(drawableState,ABOVE_ANCHOR_STATE_SET);

returndrawableState;

}else{

return?super.onCreateDrawableState(extraSpace);

}

}

@Override

public?booleandispatchKeyEvent(KeyEvent?event)?{

if(event.getKeyCode()?==?KeyEvent.KEYCODE_BACK)?{

if(getKeyDispatcherState()?==null)?{

return?super.dispatchKeyEvent(event);

}

if(event.getAction()?==?KeyEvent.ACTION_DOWN

&&?event.getRepeatCount()?==0)?{

KeyEvent.DispatcherState?state?=?getKeyDispatcherState();

if(state?!=null)?{

state.startTracking(event,this);

}

return?true;

}else?if(event.getAction()?==?KeyEvent.ACTION_UP)?{

KeyEvent.DispatcherState?state?=?getKeyDispatcherState();

if(state?!=null&&?state.isTracking(event)?&&?!event.isCanceled())?{

dismiss();

return?true;

}

}

return?super.dispatchKeyEvent(event);

}else{

return?super.dispatchKeyEvent(event);

}

}

@Override

public?booleandispatchTouchEvent(MotionEvent?ev)?{

if(mTouchInterceptor!=null&&mTouchInterceptor.onTouch(this,ev))?{

return?true;

}

return?super.dispatchTouchEvent(ev);

}

@Override

public?booleanonTouchEvent(MotionEvent?event)?{

final?intx?=?(int)?event.getX();

final?inty?=?(int)?event.getY();

if((event.getAction()?==?MotionEvent.ACTION_DOWN)

&&?((x?<0)?||?(x?>=?getWidth())?||?(y?<0)?||?(y?>=?getHeight())))?{

dismiss();

return?true;

}else?if(event.getAction()?==?MotionEvent.ACTION_OUTSIDE)?{

dismiss();

return?true;

}else{

return?super.onTouchEvent(event);

}

}

@Override

public?voidsendAccessibilityEvent(inteventType)?{

//?clinets?are?interested?in?the?content?not?the?container,?make?it?event?source

if(mContentView!=null)?{

mContentView.sendAccessibilityEvent(eventType);

}else{

super.sendAccessibilityEvent(eventType);

}

}

}

}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市斗忌,隨后出現(xiàn)的幾起案子质礼,更是在濱河造成了極大的恐慌,老刑警劉巖织阳,帶你破解...
    沈念sama閱讀 211,817評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件眶蕉,死亡現(xiàn)場離奇詭異,居然都是意外死亡唧躲,警方通過查閱死者的電腦和手機(jī)造挽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來弄痹,“玉大人饭入,你說我怎么就攤上這事「卣妫” “怎么了谐丢?”我有些...
    開封第一講書人閱讀 157,354評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我乾忱,道長讥珍,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,498評論 1 284
  • 正文 為了忘掉前任窄瘟,我火速辦了婚禮衷佃,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蹄葱。我一直安慰自己纲酗,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,600評論 6 386
  • 文/花漫 我一把揭開白布新蟆。 她就那樣靜靜地躺著觅赊,像睡著了一般。 火紅的嫁衣襯著肌膚如雪琼稻。 梳的紋絲不亂的頭發(fā)上吮螺,一...
    開封第一講書人閱讀 49,829評論 1 290
  • 那天,我揣著相機(jī)與錄音帕翻,去河邊找鬼鸠补。 笑死,一個胖子當(dāng)著我的面吹牛嘀掸,可吹牛的內(nèi)容都是我干的紫岩。 我是一名探鬼主播,決...
    沈念sama閱讀 38,979評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼睬塌,長吁一口氣:“原來是場噩夢啊……” “哼泉蝌!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起揩晴,我...
    開封第一講書人閱讀 37,722評論 0 266
  • 序言:老撾萬榮一對情侶失蹤勋陪,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后硫兰,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體诅愚,經(jīng)...
    沈念sama閱讀 44,189評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,519評論 2 327
  • 正文 我和宋清朗相戀三年劫映,在試婚紗的時候發(fā)現(xiàn)自己被綠了违孝。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,654評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡泳赋,死狀恐怖雌桑,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情摹蘑,我是刑警寧澤筹燕,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站衅鹿,受9級特大地震影響撒踪,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜大渤,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,940評論 3 313
  • 文/蒙蒙 一制妄、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧泵三,春花似錦耕捞、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至较曼,卻和暖如春磷斧,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背捷犹。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評論 1 266
  • 我被黑心中介騙來泰國打工弛饭, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人萍歉。 一個月前我還...
    沈念sama閱讀 46,382評論 2 360
  • 正文 我出身青樓侣颂,卻偏偏與公主長得像,于是被迫代替她去往敵國和親枪孩。 傳聞我的和親對象是個殘疾皇子憔晒,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,543評論 2 349

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