Android開發(fā)之UI常用屬性
介紹控件和布局中的一些屬性和片段
屬性篇
1.屬性android:visibility
(所有控件中都具有的屬性,在progressbar中較常用)
可選值有三種:visible、invisible、gone
invisible表示控件不可見,但它仍然占據(jù)著原來的位置和大小
gone表示控件不可見&控件不占用屏幕空間
還可以在代碼中設(shè)置控件的可見性:
setVisibility(View.VISIBLE);傳入View.VISIBLE、View.INVISIBLE或View.GONE三種值
- 關(guān)于android中調(diào)用某個(gè)樣式或者屬性時(shí)應(yīng)該用@還是用?的問題,例如:
style="?android:attr/progressBarStyleHorizontal"
關(guān)于用@還是用?的問題,具體解釋請(qǐng)點(diǎn)這里
2.dp和sp、dip、px、pt之間的換算問題
- dp(密度無關(guān)的像素),一種基于屏幕密度的抽象單位,2英寸3英寸的320像素480像素中,屏幕密度為320/2=160dip。即在每英寸160點(diǎn)的顯示器上,1dp=1px。
(密度為160時(shí),1dp=1px;密度為320時(shí),1dp=2px) - sp(與刻度無關(guān)的像素,指定文字大?。号cdp類似,但是可以根據(jù)用戶的字體大小首選項(xiàng)進(jìn)行縮放。
- dip 與dp相同
- px 分辨率
- pt(磅),1/72英寸。
一般Android設(shè)置長寬多用dip,設(shè)置字體多用sp,在屏幕密度為160時(shí),說明每英寸有160個(gè)px,即160px=1in。又因?yàn)榇藭r(shí)有1sp=1dip=1px(在屏幕密度160的特定條件下),所以有160sp=1in,再加上1pt=1/72in,即72pt=1in,所以72pt=160sp,化簡得1pt≈2.22sp(是一道換算題哦(/▽\))
PS:分辨率與密度的概念:分辨率指相對(duì)于軟件來說的顯示像素,以px為單位;密度表示每英寸有多少個(gè)像素,density=240->用hdpi標(biāo)簽的資源,density=160->mdpi,density=120->ldpi
3. 點(diǎn)9圖
左和上繪制的線代表拉伸區(qū)域,右和下繪制的線代表內(nèi)容被放置區(qū)域
4.碎片(Fragment)
屬于UI片段
讓程序更加合理地利用大屏幕的空間
像這樣:


Amazing!??!

Fragment的用法
導(dǎo)包問題
創(chuàng)建Fragment類所繼承的包使用support-v4,因?yàn)樗梢宰屗槠谒蠥ndroid系統(tǒng)版本中保持功能一致性;
而且不需要將該包的依賴添加到build.gradle,因?yàn)閎uild.gradle中添加的appcompat-v7庫會(huì)將support-v4庫一起引入進(jìn)來。Activity布局文件中引入fragment時(shí)
需要在xml文件中的<fragment>標(biāo)簽中添加name屬性用來指定Fragment的類,如下:

-
動(dòng)態(tài)添加碎片的用法
關(guān)鍵步驟:

R.id.right_layout表示界面中的一塊布局區(qū)域的id,如FrameLayout布局的id。
具體步驟為:
- 創(chuàng)建待添加的碎片實(shí)例
- 獲取FragmentManager,在活動(dòng)中可直接通過
getSupportFragmentManager()方法得到 - 開啟一個(gè)事務(wù),通過調(diào)用
beginTransaction()方法開啟 - 向容器內(nèi)添加或替換碎片
- 提交事務(wù),調(diào)用
commit()方法來完成
這里有個(gè)大坑:
需要讓每個(gè)自定義的Fragment類繼承自android.support.v4.app.Fragment類。
切記??! android.support.v4.app.Fragment與android.app.Fragment不要混用。
MainActivity類要繼承FragmentActivity類或者AppCompatActivity類,不然在第二步的getSupportFragmentManager()方法找不到,會(huì)報(bào)Cannot resolve method 'getSupportFragmentManager()'錯(cuò)誤。
如果使用的是AppCompatActivity類,則需要將theme改成Theme.AppCompat或其派生類,否則會(huì)報(bào)以下錯(cuò)誤:
You need to use a Theme.AppCompat theme (or descendant) with this activity.
- 在碎片中模擬返回棧(按下返回鍵不是直接退出程序,而是返回上一個(gè)fragment中)

其中的參數(shù)是用于描述返回棧狀態(tài)的名字
- 碎片和活動(dòng)之間進(jìn)行通信
- 在碎片中獲取活動(dòng)的實(shí)例:
MainActivity activity=(MainActivity)getActivity();
- 在活動(dòng)中獲取碎片的實(shí)例:
RightFragment rightFragment=(RightFragment)getFragmentManager().findFragmentById(R.id.right_fragment);
- 碎片和碎片之間互相調(diào)用:
先在碎片中調(diào)用相關(guān)聯(lián)的活動(dòng),在用這個(gè)活動(dòng)去調(diào)用碎片
-
fragment的生命周期
運(yùn)行狀態(tài):可見&&關(guān)聯(lián)的活動(dòng)在運(yùn)行
暫停狀態(tài):活動(dòng)進(jìn)入暫停狀態(tài)時(shí)
停止?fàn)顟B(tài):活動(dòng)進(jìn)入停止?fàn)顟B(tài)||通過調(diào)用FragmentTransaction的remove()、replace()方法從活動(dòng)中移除&&事務(wù)提交之前用了addToBackStack()方法
銷毀狀態(tài):活動(dòng)被銷毀時(shí)||通過調(diào)用FragmentTransaction的remove()、replace()方法從活動(dòng)中移除&&事務(wù)提交之前沒有用用addToBackStack()方法
- 其它回調(diào):
onAttach()---碎片和活動(dòng)建立關(guān)聯(lián)
onCreateView()---為碎片創(chuàng)建視圖(加載布局)時(shí)調(diào)用
onActivityCreated()---與之關(guān)聯(lián)的活動(dòng)已創(chuàng)建完畢時(shí)
onDestroyView()---碎片關(guān)聯(lián)的視圖被移除時(shí)
onDetach()--碎片和活動(dòng)解除關(guān)聯(lián)時(shí)
上一個(gè)糊糊的圖:(????)

- 動(dòng)態(tài)加載布局的技巧
- 使用限定符
Qualifier:在運(yùn)行時(shí),根據(jù)屏幕大小判斷是使用單頁模式還是雙頁模式
使用步驟:
- 在layout目錄下的main_activity.xml中只寫一個(gè)
<fragment>,在res目錄下再寫一個(gè)layout-large目錄,寫兩個(gè)<fragment>,代表雙頁模式,“l(fā)arge”就是限定符,屏幕被認(rèn)為是large的設(shè)備就會(huì)自動(dòng)加載layout-large文件夾下的布局,而小屏幕的設(shè)備還是會(huì)加載layout文件夾下的布局。

-
碎片的屏幕適配
判斷單頁和雙頁:
在onActivityCreated()方法中判斷:
getActivity().findViewById(R.id....)!=null
判斷能否找到對(duì)應(yīng)id的View,來設(shè)置是單頁模式還是雙頁模式,能找到則說明在xml文件中定義了該View,這時(shí)可以刷新對(duì)應(yīng)的fragment中的內(nèi)容:
RightFragment fragment=(RightFragment)getFragmentManager().findFragmentById(R.id....);
fragment.refresh(String stra,String strb);
如果找不到則可以開啟單獨(dú)的Activity來顯示內(nèi)容:
SecondActivity.actionStart(getActivity(),str1,str2...);
actionStart是SecondActivity中的一個(gè)靜態(tài)方法,在該方法中打開另一個(gè)Activity的話,需要將MainActivity的Context用參數(shù)的方式傳遞過去,而且還需要為SecondActivity添加flag,使SecondActivity放到另一個(gè)獨(dú)立的任務(wù)棧中,具體關(guān)于flag的筆記將寫在《Android開發(fā)藝術(shù)探索》筆記中。
fragment相關(guān)的代碼點(diǎn)這里
5. android:layout_weight屬性
android:layout_width="0dp"
android:layout_weight="1"
如果多個(gè)同級(jí)控件一起定義了這兩個(gè)屬性,而父布局是android:layout_width="match_parent"或android:layout_width="wrap_content"時(shí),兩個(gè)控件在水平方向上平分寬度,原理是系統(tǒng)按照該屬性指定的值(上面的例子是“1”)在水平方向上所有控件的layout_weight值的比例劃分寬度,值越大,劃分寬度越大。
如果是如下情況:
<LinearLayout>
<EditText
...
android:layout_width="0dp"
android:layout_weight="1"
/>
<Button
...
android:layout_width="wrap_content"
/>
</LinearLayout>
表明Button的寬度仍然按照wrap_content來計(jì)算,而EditText會(huì)占滿屏幕所有的剩余空間。
6. gravity和layout_gravity屬性
android:gravity用于設(shè)置View中內(nèi)容相對(duì)于View組件的對(duì)齊方式;
android:layout_gravity用于設(shè)置View組件相對(duì)于Container的對(duì)齊方式。
說的再直白點(diǎn),就是android:gravity只對(duì)該組件內(nèi)的東西有效,android:layout_gravity只對(duì)組件自身有效。
android:layout_gravity 只在 LinearLayout 和 FrameLayout 中有效
在LinearLayout中:
android:orientation=vertical (垂直) 時(shí),只有水平方向的left,right,center_horizontal是生效的。
android:orientation=horizontal (水平) 時(shí),只有垂直方向的top,bottom,center_vertical是生效的。
在FrameLayout布局中:
任意android:layout_gravity屬性都有效
到這里UI的屬性和片段介紹就記完了,后續(xù)對(duì)這部分有所領(lǐng)悟還會(huì)繼續(xù)添加內(nèi)容(^^ゞ