一起擼個(gè)朋友圈吧 - 圖片瀏覽(上)【圖片點(diǎn)擊前景色】

項(xiàng)目地址:https://github.com/razerdp/FriendCircle (能弱弱的求個(gè)star或者fork么QAQ)
《一起擼個(gè)朋友圈吧》 這是本文所處文集随珠,所有更新都會在這個(gè)文集里面哦帅刊,歡迎關(guān)注


上篇鏈接:http://www.reibang.com/p/4be8daaef3ca
下篇鏈接:http://www.reibang.com/p/4c5b5d7dc856


前言

終于码泞,這個(gè)系列的文章進(jìn)入了全新的篇章逛薇,咱們的朋友圈系列進(jìn)入研磨階段刹泄,目前我們可以成功展示數(shù)據(jù)外里,可以進(jìn)行點(diǎn)贊或者取消點(diǎn)贊,可以進(jìn)行評論特石。

但完成這些基本功能是不夠的盅蝗。

一款產(chǎn)品之所以深入人心,是因?yàn)?strong>“用著舒服”姆蘸,說是“用著舒服”倒不如說是“看著舒服”墩莫,而視覺交互,或者說交互動畫逞敷,正是一款A(yù)pp打動人的最重要的地方贼穆。

在之前的文章里,我其實(shí)一直很注重這些小細(xì)節(jié)的兰粉,而這些小細(xì)節(jié)故痊,也是微信現(xiàn)在所擁有的,或許你平常沒怎么留意玖姑,但倘若取消掉這些動畫愕秫,相信你很快就會發(fā)覺“這他喵的這么生硬”

在本系列之前的文章里,我們有留意到并實(shí)現(xiàn)了以下的動畫:

或許您想不到,一個(gè)小小的朋友圈看似簡單畏腕,卻有著這么多小動畫缴川。

好的,說了這么多東西描馅,除了總結(jié)外把夸,實(shí)際上就是為了推銷文章←_←,我不知道是否真的有人會看铭污,也許會有人僅僅是為了拿源碼伸伸手而已恋日。

但,我認(rèn)為嘹狞,跟同一圈子的人交流自己的思想岂膳,分享自己的經(jīng)驗(yàn),不是一件很美妙的事情嗎磅网?所以谈截,即使沒什么人看,我也會堅(jiān)持把這個(gè)開源項(xiàng)目完成的以及在簡書堅(jiān)持更新所有思路的-V-


正文

正如前言那一堆廢話所說,今天我們要實(shí)現(xiàn)的是這么一個(gè)效果:

preview - size:8.0M傻盟,流量黨請注意

如您所見速蕊,當(dāng)我們點(diǎn)擊圖片的時(shí)候,你會發(fā)現(xiàn)娘赴,圖片會有一個(gè)灰色的蒙層疊加在上面规哲,看起來就像是我們選中了圖片一樣。

如果要實(shí)現(xiàn)這個(gè)效果诽表,按照我們的平時(shí)習(xí)慣唉锌,肯定是“selector走起”,奈何竿奏,當(dāng)我們真的去試了一下之后袄简,發(fā)現(xiàn),貌似不管用啊0.0

于是百度一番泛啸,或者谷歌一番绿语,發(fā)現(xiàn)又是設(shè)置clickable啊,又是selector什么亂七八糟的順序問題啊候址。吕粹。。岗仑。

與其執(zhí)著于這些匹耕,倒不如咱們自定義一個(gè)出來以應(yīng)付一切的imageview。


關(guān)于Selector

如果硬要解釋這個(gè)東東荠雕,我想稳其,我應(yīng)該重新寫一篇文章來專門講解一下這個(gè)東東(事實(shí)上我也打算這么做)

但在這里我只會簡單的說說Selector到底是如何實(shí)現(xiàn)view的視圖變化的:

  • 無論是什么Selector,實(shí)際上最終都是Drawable炸卑,而Drawable可以理解為圖片既鞠,但如果需要更好的描述它,我覺得將其理解為ps可能會更好矾兜,因?yàn)镈rawable是一個(gè)抽象類损趋,它提供了“something that can be drawn”的方法,其實(shí)弄來弄去椅寺,都是draw()方法

  • Selector在java中具體化的說,其實(shí)就是StateListDrawable蒋失。

  • Drawable有一個(gè)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的實(shí)現(xiàn)過程,從中我們不難得到以下信息:

  • 維護(hù)不同狀態(tài)對應(yīng)的drawable的數(shù)組
  • 根據(jù)狀態(tài)是否改變來得到對應(yīng)狀態(tài)的drawable
  • draw方法

實(shí)現(xiàn)

梳理了一遍過程之后敞峭,我們只需要對癥下藥就好了踊谋。

于是我們正式開工:

首先還是我的習(xí)慣,在自定義一個(gè)view之前旋讹,先配置attrs殖蚕,在這里我們就只配置一個(gè)屬性用來改變前景色。

attrs:

<!--ForceClickImageView-->
    <declare-styleable name="ForceClickImageView">
        <attr name="foregroundColor" format="reference|color"/>
    </declare-styleable>

然后新建一個(gè)ForceClickImageView類沉迹,繼承本項(xiàng)目的SuperImageView(實(shí)際上就是普通的imageview睦疫,封裝了glide的加載方法)

/**
 * Created by 大燈泡 on 2016/4/11.
 * 朋友圈的imageview,包含點(diǎn)擊動作
 */
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);
    }
   
}

我們可以看到鞭呕,在這里我加了兩個(gè)成員蛤育,一個(gè)自然是drawable,另一個(gè)則是一個(gè)矩形葫松,這個(gè)矩形主要是用來規(guī)定我們的drawable繪制的范圍缨伊,在這里我們主要是用來緩存這個(gè)view的范圍。

接下來在初始化方法里面我們補(bǔ)充一下代碼:

    /**
     * 初始化
     */
    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();
    }

首先我們獲取到我們定義的attrs屬性集进宝,然后得到drawable刻坊,在這里值得注意的是:

我們的attr允許傳入的參數(shù)除了reference外,還允許color

所以如果傳入的是一個(gè)selector党晋,那么getDrawable將會得到StateListDrawable

如果傳入的是color值谭胚,那么getDrawable將會得到ColorDrawable,而ColorDrawable無論是什么狀態(tài)未玻,都只會有一個(gè)顏色灾而。

所以如果傳入的是ColorDrawable,我們就需要手動new出一個(gè)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) - 同上

因?yàn)槲覀円膊涣私獾降资菚|發(fā)哪種狀態(tài)锡搜,所以就直接扔了大概會觸發(fā)的狀態(tài)進(jìn)去,因?yàn)樵诟淖兊臅r(shí)候瞧掺,系統(tǒng)會從數(shù)組中遍歷直到找出與狀態(tài)符合的drawable為止耕餐。

哦,不要忘了setCallback(this)辟狈,因?yàn)閂iew已經(jīng)實(shí)現(xiàn)了該接口肠缔,所以我們把this傳入就好了夏跷。

最重要的部分完成后后,接下來就是一些方法的覆寫了明未。

 @Override
    protected void drawableStateChanged() {
        super.drawableStateChanged();

        if (mForegroundDrawable != null && mForegroundDrawable.isStateful()) {
            mForegroundDrawable.setState(getDrawableState());
        }
        invalidate();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        if (mForegroundDrawable != null) {
            mForegroundDrawable.setBounds(mCachedBounds);
            mForegroundDrawable.draw(canvas);
        }
    }

    @Override
    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);
    }
}

首先我們覆寫drawableStateChanged槽华,這個(gè)方法在view的狀態(tài)有發(fā)生改變的時(shí)候(比如從無焦點(diǎn)->有焦點(diǎn)),就會回調(diào)趟妥。

在這里猫态,我們直接給調(diào)用 mForegroundDrawable.setState(getDrawableState());

因?yàn)間etDrawableState()方法在view里面已經(jīng)是封裝好的了,它一共執(zhí)行了兩個(gè)動作:

  • 判斷上一次的drawable狀態(tài)煮纵,如果上一次的狀態(tài)不變懂鸵,就返回上一次的
  • 否則,執(zhí)行onCreateDrawableState獲取符合的狀態(tài)
  • 最終返回與drawablestate長度一致的int數(shù)組

在setState之后行疏,我們直接調(diào)用invalidate();要求這個(gè)view刷新匆光。

在draw方法里面,父類的draw方法執(zhí)行之后酿联,也就是圖片展示之后终息,我們調(diào)用drawable的draw方法,此時(shí)就會將colorDrawable繪制到圖片的上層贞让,表現(xiàn)起來就是有selector的效果了周崭。

最后在xml布局里面添加我們的參數(shù)就可以了:

    <razerdp.friendcircle.widget.imageview.ForceClickImageView
        android:id="@+id/img"
        android:scaleType="centerCrop"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:foregroundColor="@color/img_foregroundColor"
        />

其中img_foregroundColor的色值為:
"#85414141"

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市喳张,隨后出現(xiàn)的幾起案子续镇,更是在濱河造成了極大的恐慌,老刑警劉巖销部,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件摸航,死亡現(xiàn)場離奇詭異,居然都是意外死亡舅桩,警方通過查閱死者的電腦和手機(jī)酱虎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來擂涛,“玉大人读串,你說我怎么就攤上這事∪雎瑁” “怎么了恢暖?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長踩身。 經(jīng)常有香客問我胀茵,道長,這世上最難降的妖魔是什么挟阻? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上附鸽,老公的妹妹穿的比我還像新娘脱拼。我一直安慰自己,他們只是感情好坷备,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布熄浓。 她就那樣靜靜地躺著,像睡著了一般省撑。 火紅的嫁衣襯著肌膚如雪赌蔑。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天竟秫,我揣著相機(jī)與錄音娃惯,去河邊找鬼。 笑死肥败,一個(gè)胖子當(dāng)著我的面吹牛趾浅,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播馒稍,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼皿哨,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了纽谒?” 一聲冷哼從身側(cè)響起证膨,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎鼓黔,沒想到半個(gè)月后央勒,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡请祖,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年订歪,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片肆捕。...
    茶點(diǎn)故事閱讀 38,163評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡刷晋,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出慎陵,到底是詐尸還是另有隱情眼虱,我是刑警寧澤,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布席纽,位于F島的核電站捏悬,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏润梯。R本人自食惡果不足惜过牙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一甥厦、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧寇钉,春花似錦刀疙、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至撵溃,卻和暖如春疚鲤,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背缘挑。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工集歇, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人卖哎。 一個(gè)月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓鬼悠,卻偏偏與公主長得像,于是被迫代替她去往敵國和親亏娜。 傳聞我的和親對象是個(gè)殘疾皇子焕窝,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評論 2 344

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