一起撸个朋友圈吧 图片浏览(上)【图片点击前景色】
項目地址:github.com/razerdp/Fri… (能弱弱的求個star或者fork么QAQ)
-
上篇鏈接:一起擼個朋友圈吧 (Step6)- 評論對齊(點擊評論對齊)【下】
-
下篇鏈接:一起擼個朋友圈吧 - 圖片瀏覽(中)【圖片瀏覽器】
前言
終于,這個系列的文章進(jìn)入了全新的篇章,咱們的朋友圈系列進(jìn)入研磨階段,目前我們可以成功展示數(shù)據(jù),可以進(jìn)行點贊或者取消點贊,可以進(jìn)行評論。
但完成這些基本功能是不夠的。
一款產(chǎn)品之所以深入人心,是因為**“用著舒服”,說是“用著舒服”倒不如說是“看著舒服”**,而視覺交互,或者說交互動畫,正是一款A(yù)pp打動人的最重要的地方。
在之前的文章里,我其實一直很注重這些小細(xì)節(jié)的,而這些小細(xì)節(jié),也是微信現(xiàn)在所擁有的,或許你平常沒怎么留意,但倘若取消掉這些動畫,相信你很快就會發(fā)覺**“這他喵的這么生硬”**
在本系列之前的文章里,我們有留意到并實現(xiàn)了以下的動畫:
-
下拉刷新時那個朋友圈的icon隨著listview滑動而滑動并自身旋轉(zhuǎn)
- 傳送門
-
點贊時,popup的彈出動畫
- 傳送門
-
點贊的時候,點贊的心心放大縮小動畫
- 傳送門 在Step 4
-
評論時,當(dāng)輸入法彈上來,輸入框自動對齊評論或者動態(tài)的底部
- 傳送門 - 動態(tài)底部對齊
- 傳送門 - 評論底部對齊
-
點擊評論或者點贊時,對應(yīng)的名字背景色改變
- 傳送門
或許您想不到,一個小小的朋友圈看似簡單,卻有著這么多小動畫。
好的,說了這么多東西,除了總結(jié)外,實際上就是為了推銷文章←_←,我不知道是否真的有人會看,也許會有人僅僅是為了拿源碼伸伸手而已。
但,我認(rèn)為,跟同一圈子的人交流自己的思想,分享自己的經(jīng)驗,不是一件很美妙的事情嗎?所以,即使沒什么人看,我也會堅持把這個開源項目完成的以及在簡書堅持更新所有思路的-V-
正文
正如前言那一堆廢話所說,今天我們要實現(xiàn)的是這么一個效果:
如您所見,當(dāng)我們點擊圖片的時候,你會發(fā)現(xiàn),圖片會有一個灰色的蒙層疊加在上面,看起來就像是我們選中了圖片一樣。
如果要實現(xiàn)這個效果,按照我們的平時習(xí)慣,肯定是“selector走起”,奈何,當(dāng)我們真的去試了一下之后,發(fā)現(xiàn),貌似不管用啊0.0
于是百度一番,或者谷歌一番,發(fā)現(xiàn)又是設(shè)置clickable啊,又是selector什么亂七八糟的順序問題啊。。。。
與其執(zhí)著于這些,倒不如咱們自定義一個出來以應(yīng)付一切的imageview。
關(guān)于Selector
如果硬要解釋這個東東,我想,我應(yīng)該重新寫一篇文章來專門講解一下這個東東(事實上我也打算這么做)
但在這里我只會簡單的說說Selector到底是如何實現(xiàn)view的視圖變化的:
-
無論是什么Selector,實際上最終都是Drawable,而Drawable可以理解為圖片,但如果需要更好的描述它,我覺得將其理解為ps可能會更好,因為Drawable是一個抽象類,它提供了**“something that can be drawn”**的方法,其實弄來弄去,都是draw()方法
-
Selector在java中具體化的說,其實就是StateListDrawable。
-
Drawable有一個mState數(shù)組,它維護(hù)了不同狀態(tài)下的drawable,當(dāng)view接收到touch事件,會調(diào)用refreshDrawableState來更新狀態(tài),一般來說通過Drawable的isStateful()函數(shù)來得知是否與上次的狀態(tài)不同,如果是,則進(jìn)行draw方法來改變view的視圖,在我們的眼中看起來就是顏色的改變。
上面很簡單的講述了selector的實現(xiàn)過程,從中我們不難得到以下信息:
- 維護(hù)不同狀態(tài)對應(yīng)的drawable的數(shù)組
- 根據(jù)狀態(tài)是否改變來得到對應(yīng)狀態(tài)的drawable
- draw方法
##實現(xiàn)
梳理了一遍過程之后,我們只需要對癥下藥就好了。
于是我們正式開工:
首先還是我的習(xí)慣,在自定義一個view之前,先配置attrs,在這里我們就只配置一個屬性用來改變前景色。
attrs:
<!--ForceClickImageView--><declare-styleable name="ForceClickImageView"><attr name="foregroundColor" format="reference|color"/></declare-styleable> 復(fù)制代碼然后新建一個ForceClickImageView類,繼承本項目的SuperImageView(實際上就是普通的imageview,封裝了glide的加載方法)
/*** Created by 大燈泡 on 2016/4/11.* 朋友圈的imageview,包含點擊動作*/ public class ForceClickImageView extends SuperImageView {//前景層private Drawable mForegroundDrawable;private Rect mCachedBounds = new Rect();public ForceClickImageView(Context context) {this(context, null);}public ForceClickImageView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public ForceClickImageView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init(context, attrs);}} 復(fù)制代碼我們可以看到,在這里我加了兩個成員,一個自然是drawable,另一個則是一個矩形,這個矩形主要是用來規(guī)定我們的drawable繪制的范圍,在這里我們主要是用來緩存這個view的范圍。
接下來在初始化方法里面我們補充一下代碼:
/*** 初始化*/private void init(Context context, AttributeSet attrs) {final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ForceClickImageView);mForegroundDrawable = a.getDrawable(R.styleable.ForceClickImageView_foregroundColor);if (mForegroundDrawable instanceof ColorDrawable) {int foreGroundColor = a.getColor(R.styleable.ForceClickImageView_foregroundColor, 0x55c6c6c6);mForegroundDrawable = new StateListDrawable();ColorDrawable forceDrawable = new ColorDrawable(foreGroundColor);ColorDrawable normalDrawable = new ColorDrawable(Color.TRANSPARENT);((StateListDrawable) mForegroundDrawable).addState(new int[] { android.R.attr.state_focused },forceDrawable);((StateListDrawable) mForegroundDrawable).addState(new int[] { android.R.attr.state_pressed },forceDrawable);((StateListDrawable) mForegroundDrawable).addState(new int[] { android.R.attr.state_enabled },normalDrawable);((StateListDrawable) mForegroundDrawable).addState(new int[] {}, normalDrawable);}if (mForegroundDrawable != null) mForegroundDrawable.setCallback(this);a.recycle();} 復(fù)制代碼首先我們獲取到我們定義的attrs屬性集,然后得到drawable,在這里值得注意的是:
我們的attr允許傳入的參數(shù)除了reference外,還允許color
所以如果傳入的是一個selector,那么getDrawable將會得到StateListDrawable
如果傳入的是color值,那么getDrawable將會得到ColorDrawable,而ColorDrawable無論是什么狀態(tài),都只會有一個顏色。
所以如果傳入的是ColorDrawable,我們就需要手動new出一個StateListDrawable并設(shè)置我們不同狀態(tài)下的drawable了。
在上述代碼中,如果我們得到的是ColorDrawable,我們就new出StateListDrawable,然后分別對應(yīng)添加下述狀態(tài)和對應(yīng)的drawable
- focused狀態(tài) - 則是我們的前景色drawable
- pressed狀態(tài) - 同上
- enable狀態(tài) - 透明色的drawable
- 無狀態(tài) - 同上
因為我們也不了解到底是會觸發(fā)哪種狀態(tài),所以就直接扔了大概會觸發(fā)的狀態(tài)進(jìn)去,因為在改變的時候,系統(tǒng)會從數(shù)組中遍歷直到找出與狀態(tài)符合的drawable為止。
哦,不要忘了setCallback(this),因為View已經(jīng)實現(xiàn)了該接口,所以我們把this傳入就好了。
最重要的部分完成后后,接下來就是一些方法的覆寫了。
protected void drawableStateChanged() {super.drawableStateChanged();if (mForegroundDrawable != null && mForegroundDrawable.isStateful()) {mForegroundDrawable.setState(getDrawableState());}invalidate();}protected void onDraw(Canvas canvas) {super.onDraw(canvas);if (mForegroundDrawable != null) {mForegroundDrawable.setBounds(mCachedBounds);mForegroundDrawable.draw(canvas);}}protected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);if (mForegroundDrawable != null) mCachedBounds.set(0, 0, w, h);} } 復(fù)制代碼首先我們覆寫drawableStateChanged,這個方法在view的狀態(tài)有發(fā)生改變的時候(比如從無焦點->有焦點),就會回調(diào)。
在這里,我們直接給調(diào)用 mForegroundDrawable.setState(getDrawableState());
因為getDrawableState()方法在view里面已經(jīng)是封裝好的了,它一共執(zhí)行了兩個動作:
- 判斷上一次的drawable狀態(tài),如果上一次的狀態(tài)不變,就返回上一次的
- 否則,執(zhí)行onCreateDrawableState獲取符合的狀態(tài)
- 最終返回與drawablestate長度一致的int數(shù)組
在setState之后,我們直接調(diào)用invalidate();要求這個view刷新。
在draw方法里面,父類的draw方法執(zhí)行之后,也就是圖片展示之后,我們調(diào)用drawable的draw方法,此時就會將colorDrawable繪制到圖片的上層,表現(xiàn)起來就是有selector的效果了。
最后在xml布局里面添加我們的參數(shù)就可以了:
<razerdp.friendcircle.widget.imageview.ForceClickImageViewandroid:id="@+id/img"android:scaleType="centerCrop"android:layout_width="match_parent"android:layout_height="match_parent"app:foregroundColor="@color/img_foregroundColor"/> 復(fù)制代碼其中img_foregroundColor的色值為: "#85414141"
總結(jié)
以上是生活随笔為你收集整理的一起撸个朋友圈吧 图片浏览(上)【图片点击前景色】的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一次性通过软考网工方案
- 下一篇: swift3 0 流控制