Android自定義ViewGroup之仿制一個(gè)Windows桌面

前段時(shí)間寫過一個(gè)Android自定義View的文章瓷产,是高仿的QQ健康,還沒有看過的可以去看看柳洋,所以一直都計(jì)劃著在寫個(gè)自定義ViewGroup相關(guān)的文章傻挂。我知道網(wǎng)上關(guān)于這方面的文章已經(jīng)是一搜一大堆的那種了,所以我想一定要找個(gè)與網(wǎng)上的不同的來做Demo检碗,還是要稍微有點(diǎn)新意据块,由于一直找不到所以就一直拖著了,最近也是突然間想到Windows的桌面不錯(cuò)折剃,我可以拿這個(gè)作為一個(gè)自定ViewGroup的Demo啊另假,于是就著手寫了這么一個(gè)。本文比較簡單怕犁,適合那些還不太會自定義ViewGroup的同學(xué)看看边篮。先來看看最后的效果圖

自定義一個(gè)ViewGroup,其實(shí)真的并不太難奏甫,主要就在onMeasure和onLayout這兩個(gè)方法上下功夫戈轿,無非就是去把子View的大小測量出來然后再把子View按照一定的規(guī)則放置到相應(yīng)的位置上,只要把測量和布局的邏輯和思想弄懂了阵子,自定義ViewGroup就是小Case了思杯。

下面就來說說上面的這個(gè)自定義ViewGroup怎么做吧。
先來說說思路挠进,整個(gè)ViewGroup分為兩個(gè)區(qū)域色乾,上面是內(nèi)容區(qū),下面是底部狀態(tài)欄领突,我這個(gè)自定義ViewGroup的做法就是默認(rèn)的把最后添加的那一個(gè)View來作為底部狀態(tài)欄暖璧。至于彈出來的那個(gè)就是個(gè)PopWondow,與自定義ViewGroup是沒有什么關(guān)系的攘须,是在使用的時(shí)候添加的漆撞。

來看看代碼實(shí)現(xiàn)

1.onMeasure方法

onMeasure

與自定義View唯一不同的就是,在ViewGroup的onMeasure方法里還需對他所包含的View的大小進(jìn)行測量于宙,里面的measureChildren是調(diào)用的系統(tǒng)的測量方法浮驳,他是將父布局的測量規(guī)格作為參數(shù)傳遞到這個(gè)方法中,然后根據(jù)父布局的測量規(guī)格去測量子View的大欣炭(感興趣可以去源碼查看至会,還是比較簡單的,這里我們完全可以自己去做這個(gè)測量谱俭,既然系統(tǒng)已經(jīng)提供了奉件,就不用去那些重復(fù)的事了)。最后就是setMeasuredDimension設(shè)置ViewGroup本身的大小昆著,這里我對ViewGroup是大小是wrap_content的情況县貌,就直接將其大小設(shè)置為0了,在這個(gè)自定義ViewGroup中wrap_content也沒多大的意義凑懂。

2.onLayout方法

當(dāng)測量完成之后就是對ViewGroup中的子View進(jìn)行放置了煤痕,View的layout方法就是用來去將View放到某個(gè)位置用的,來看看onLayout方法的實(shí)現(xiàn)接谨。


onLayout

這里簡單說一下摆碉,onLayout方法中的那幾個(gè)參數(shù)的含義

  • changed:默認(rèn)這個(gè)值都是為false,如果這個(gè)ViewGroup的位置改變了脓豪,導(dǎo)致了被重新布局巷帝,這個(gè)值就為true,
  • l:ViewGroup left的位置
  • t:ViewGroup top的位置
  • r:ViewGroup right的位置
  • b:ViewGroup bottom的位置

我們都知道扫夜,一般知道了一個(gè)View的left楞泼,top,right历谍,bottom就決定了這個(gè)View的位置现拒。

代碼中大部分我注釋的還是比較清楚了,這里只來看看for循環(huán)里面的實(shí)現(xiàn),里面的邏輯就是去計(jì)算將要放置的View的位置的望侈。
注意到印蔬,if(cb>contentHeight) 這句,就是如果當(dāng)前將要放置的View的bottom位置已經(jīng)超過了內(nèi)容區(qū)的高度脱衙,那么我們就將列數(shù)加1侥猬,將之放到下一列中去。

整個(gè)自定義ViewGroup就完了捐韩,就是這么簡單退唠。我們來看看怎么在布局文件中去使用。


 <ren.solid.materialdesigndemo.view.WindowsLayout
        android:id="@+id/windows_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#6b6b6b">

        <LinearLayout
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:gravity="center"
            android:orientation="vertical">

            <ImageView
                android:layout_width="50dp"
                android:layout_height="50dp"
                android:src="@drawable/icon_folder" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="文件夾" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:gravity="center"
            android:orientation="vertical">

            <ImageView
                android:layout_width="50dp"
                android:layout_height="50dp"
                android:src="@drawable/icon_folder" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="文件夾" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:gravity="center"
            android:orientation="vertical">

            <ImageView
                android:layout_width="50dp"
                android:layout_height="50dp"
                android:src="@drawable/icon_folder" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="文件夾" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:gravity="center"
            android:orientation="vertical">

            <ImageView
                android:layout_width="50dp"
                android:layout_height="50dp"
                android:src="@drawable/icon_folder" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="文件夾" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:gravity="center"
            android:orientation="vertical">

            <ImageView
                android:layout_width="50dp"
                android:layout_height="50dp"
                android:src="@drawable/icon_folder" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="文件夾" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:gravity="center"
            android:orientation="vertical">

            <ImageView
                android:layout_width="50dp"
                android:layout_height="50dp"
                android:src="@drawable/icon_folder" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="文件夾" />
        </LinearLayout>


        <LinearLayout
            android:id="@+id/ll_bottom"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:background="#e0000000"
            android:gravity="center_vertical"
            android:orientation="horizontal"
            android:paddingLeft="10dp">

            <ImageView
                android:layout_width="30dp"
                android:layout_height="30dp"
                android:src="@drawable/icon_windows" />
        </LinearLayout>


    </ren.solid.materialdesigndemo.view.WindowsLayout>

在這個(gè)自定義的ViewGroup中荤胁,前面放置的都是內(nèi)容區(qū)的瞧预,最后一個(gè)是底部狀態(tài)欄。就這樣就可以實(shí)現(xiàn)最開始那個(gè)動態(tài)圖中的效果。對于點(diǎn)擊左下角的徽標(biāo)垢油,可以彈出一個(gè)層盆驹,我使用的是PopWindow,代碼如下:

LinearLayout ll_bottom = customFindViewById(R.id.ll_bottom);
        ll_bottom.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                int[] location = new int[2];
                v.getLocationOnScreen(location);

                View popupView = LayoutInflater.from(getMContext()).inflate(R.layout.pop_windows, null);
                PopupWindow popupWindow = new PopupWindow(popupView, ViewGroup.LayoutParams.WRAP_CONTENT,
                        ViewGroup.LayoutParams.WRAP_CONTENT, true);
                popupView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
                popupWindow.setBackgroundDrawable(new ColorDrawable(Color.parseColor("#e0000000")));
                popupWindow.setOutsideTouchable(true);
                popupWindow.setFocusable(true);
                int height=popupView.getMeasuredHeight();
                popupWindow.showAtLocation(v, Gravity.NO_GRAVITY, location[0], location[1]-height);
            }
        });

源碼附上:源碼

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末滩愁,一起剝皮案震驚了整個(gè)濱河市躯喇,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌硝枉,老刑警劉巖廉丽,帶你破解...
    沈念sama閱讀 221,406評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異妻味,居然都是意外死亡正压,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,395評論 3 398
  • 文/潘曉璐 我一進(jìn)店門责球,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蔑匣,“玉大人,你說我怎么就攤上這事棕诵〔昧迹” “怎么了?”我有些...
    開封第一講書人閱讀 167,815評論 0 360
  • 文/不壞的土叔 我叫張陵校套,是天一觀的道長价脾。 經(jīng)常有香客問我,道長笛匙,這世上最難降的妖魔是什么侨把? 我笑而不...
    開封第一講書人閱讀 59,537評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮妹孙,結(jié)果婚禮上秋柄,老公的妹妹穿的比我還像新娘。我一直安慰自己蠢正,他們只是感情好骇笔,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,536評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著嚣崭,像睡著了一般笨触。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上雹舀,一...
    開封第一講書人閱讀 52,184評論 1 308
  • 那天芦劣,我揣著相機(jī)與錄音,去河邊找鬼说榆。 笑死虚吟,一個(gè)胖子當(dāng)著我的面吹牛寸认,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播串慰,決...
    沈念sama閱讀 40,776評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼废麻,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了模庐?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,668評論 0 276
  • 序言:老撾萬榮一對情侶失蹤油宜,失蹤者是張志新(化名)和其女友劉穎掂碱,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體慎冤,經(jīng)...
    沈念sama閱讀 46,212評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡疼燥,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,299評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蚁堤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片醉者。...
    茶點(diǎn)故事閱讀 40,438評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖披诗,靈堂內(nèi)的尸體忽然破棺而出撬即,到底是詐尸還是另有隱情,我是刑警寧澤呈队,帶...
    沈念sama閱讀 36,128評論 5 349
  • 正文 年R本政府宣布剥槐,位于F島的核電站,受9級特大地震影響宪摧,放射性物質(zhì)發(fā)生泄漏粒竖。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,807評論 3 333
  • 文/蒙蒙 一几于、第九天 我趴在偏房一處隱蔽的房頂上張望蕊苗。 院中可真熱鬧,春花似錦沿彭、人聲如沸朽砰。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,279評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽锅移。三九已至,卻和暖如春饱搏,著一層夾襖步出監(jiān)牢的瞬間非剃,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,395評論 1 272
  • 我被黑心中介騙來泰國打工推沸, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留备绽,地道東北人券坞。 一個(gè)月前我還...
    沈念sama閱讀 48,827評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像肺素,于是被迫代替她去往敵國和親恨锚。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,446評論 2 359

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