- android:descendantFocusability屬性,其中翻譯成中文意思是子孫焦點(diǎn)旁蔼,也就是當(dāng)前 viewgroup 和其子控件誰獲取當(dāng)前焦點(diǎn)的意思。常用在 listview 和 recyclerView 中,當(dāng) listView 每個(gè)條目需要監(jiān)聽點(diǎn)擊事件,同時(shí)每個(gè)條目里的子控件例如:button够吩、checkbox 等也需要點(diǎn)擊焦點(diǎn)的時(shí)候。
此屬性對應(yīng)的值有三個(gè)丈氓,分別是
beforeDescendants:viewgroup會優(yōu)先其子類控件而獲取到焦點(diǎn)
afterDescendants:viewgroup只有當(dāng)其子類控件不需要獲取焦點(diǎn)時(shí)才獲取焦點(diǎn)
blocksDescendants:viewgroup會覆蓋子類控件而直接獲得焦點(diǎn)
官方文檔對此說明是:
android:descendantFocusabilityDefines the relationship between the ViewGroup and its descendants when looking for a View to take focus.Must be one of the following constant values.
對應(yīng)的值.jpg
- Android 里 canvas.draw() 方法需要注意的:
當(dāng)畫矩形 canvas.drawRect() 時(shí)如果是空心的矩形周循,即設(shè)置了 paint.setStyle(Paint.Style.STROKE) 和 paint.setStrokeWidth(20) 屬性强法,則要注意矩形起始點(diǎn)和右下角坐標(biāo)位置應(yīng)該分別減去線條寬度的一半,即
canvas.drawRect(strokeWidth/2湾笛,strokeWidth/2饮怯,width-strokeWidth/2,height-strokeWidth/2,paint); //左上右下,畫筆
舉個(gè)例子 參考來源
如果在上圖位置畫一個(gè) 50*100dp 的矩形(見下圖)嚎研,其中線條寬度是20dp,起始左上角坐標(biāo)和結(jié)束右下角坐標(biāo)不是(0蓖墅,0)和 (100,50)临扮,此時(shí)應(yīng)該注意線條寬度也占據(jù)了位置置媳,起始位置應(yīng)該加上線條寬度的一半,終點(diǎn)位置應(yīng)該減去線條寬度的一半公条,也就是取線條的中間拇囊。這里就是
canvas.drawRect(10,10靶橱,90, 40, paint); //這里暫不考慮 dp 轉(zhuǎn) px 的分辨率問題寥袭,都當(dāng)成 px 處理。
延伸
①.如果畫矩形不設(shè)置 stroke 屬性关霸,直接設(shè)置 paint.setStyle(Style.FILL)传黄,則直接從紅色矩形左上角坐標(biāo)點(diǎn)開始即可;
②.如果畫圓队寇,也設(shè)置了描邊膘掰,如下圖,那么畫圓的時(shí)候半徑就是布局的一半減去線條寬度的一半佳遣。
③.如果畫線识埋,即 canvas.drawLine(),如下圖所示零渐,如果設(shè)置 paint.setStrokeWidth(20)窒舟,
則表示畫線的線條粗細(xì)為 20px ,那么畫的時(shí)候坐標(biāo)點(diǎn)就是圖中紅點(diǎn)诵盼,即左邊界線條的中間點(diǎn)惠豺,即(0,10)這個(gè)點(diǎn);
- 全面屏手機(jī)顯示 view 的時(shí)候风宁,部分手機(jī)底部有留白或者黑邊洁墙,也就是沒有鋪滿屏幕顯示。
其實(shí)只要設(shè)置項(xiàng)目的 targetSdkVersion > 24戒财,即大于 7.0热监,則默認(rèn)支持全面屏,也就不會有黑邊顯示固翰。如果項(xiàng)目是比較老的版本狼纬,并且 targetSdkVersion < 24 且不好隨便更改羹呵,也可以在 manifest 文件里配置以下內(nèi)容:
<meta-data
android:name="android.max_aspect"
android:value="2.4" />
這樣也可以做到全屏展示。為什么這里 value 是 2.4疗琉,其實(shí)這是計(jì)算出來的一個(gè)預(yù)估值冈欢,因?yàn)閭鹘y(tǒng)屏幕:ratio_float = 16/9 = 1.778 ;像小米的 MIX2 是 18 / 9 =2 的盈简,mix3 是 19.5 / 9 = 2.16凑耻,越來越長可以寫稍微大點(diǎn)留一些余地,所以直接寫成 2.4 更保險(xiǎn)一些柠贤。以后開發(fā)估計(jì)都會支持全面屏香浩,并且 Google 支持把 targetSdkVersion 寫成最新版本,所以基本上以后的項(xiàng)目不會涉及到全面屏顯示不全的問題臼勉,因?yàn)?targetSdkVersion 大于 24 已經(jīng)默認(rèn)支持了全面屏顯示邻吭。
- 安卓中三個(gè)獲取定義的 dimens 值的方法:
getDimension、getDimensionPixelOffset 和 getDimensionPixelSize
在開發(fā)中宴霸,在代碼里動(dòng)態(tài)設(shè)置布局的間距囱晴、尺寸等數(shù)值時(shí),最好使用 /res/values/dimens.xml 里的自定義尺寸瓢谢,這樣可以做到不同分辨率的屏幕適配畸写,因?yàn)榭梢远x不同的 dimens 文件對應(yīng)不同的分辨率。現(xiàn)在就看下上邊三種方法對應(yīng)獲取的值的區(qū)別氓扛。
首先說明三個(gè)方法返回的都是對應(yīng)的像素值枯芬,也就是不管定義的是 dp 還是 sp 或者 px,返回的都是 px 單位的值,可以通過以下的例子來看:
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="dp_value">17dp</dimen>
<dimen name="sp_value">17sp</dimen>
<dimen name="px_value">17px</dimen>
</resources>
//獲取屏幕信息
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int width = displayMetrics.widthPixels;
int height = displayMetrics.heightPixels;
float density = displayMetrics.density;
int densityDpi = displayMetrics.densityDpi;
System.out.println("屏幕寬:"+ width + "屏幕高:"+height);
System.out.println("屏幕密度:"+ density + "屏幕密度 DPI:" + densityDpi);
float a1 = getResources().getDimension(R.dimen.px_value);
float a2 = getResources().getDimension(R.dimen.dp_value);
float a3 = getResources().getDimension(R.dimen.sp_value);
System.out.println("getDimension 中 px值是:" + a1);
System.out.println("getDimension 中 dp值是:" + a2);
System.out.println("getDimension 中 sp值是:" + a3);
int b1 = getResources().getDimensionPixelSize(R.dimen.px_value);
int b2 = getResources().getDimensionPixelSize(R.dimen.dp_value);
int b3 = getResources().getDimensionPixelSize(R.dimen.sp_value);
System.out.println("getDimensionPixelSize 中 px值是:" + b1);
System.out.println("getDimensionPixelSize 中 dp值是:" + b2);
System.out.println("getDimensionPixelSize 中 sp值是:" + b3);
int c1 = getResources().getDimensionPixelOffset(R.dimen.px_value);
int c2 = getResources().getDimensionPixelOffset(R.dimen.dp_value);
int c3 = getResources().getDimensionPixelOffset(R.dimen.sp_value);
System.out.println("getDimensionPixelOffset 中 px值是:" + c1);
System.out.println("getDimensionPixelOffset 中 dp值是:" + c2);
System.out.println("getDimensionPixelOffset 中 sp值是:" + c3);
打印數(shù)據(jù)是:
2019-07-28 17:43:27.469 23912-23912/com.ispring.gameplane I/System.out: 屏幕寬:1080 屏幕高:2030
2019-07-28 17:43:27.470 23912-23912/com.ispring.gameplane I/System.out: 屏幕密度:2.75屏幕密度 DPI:440
2019-07-28 17:43:27.470 23912-23912/com.ispring.gameplane I/System.out: getDimension 中 px值是:17.0
2019-07-28 17:43:27.470 23912-23912/com.ispring.gameplane I/System.out: getDimension 中 dp值是:46.75
2019-07-28 17:43:27.470 23912-23912/com.ispring.gameplane I/System.out: getDimension 中 sp值是:46.75
2019-07-28 17:43:27.470 23912-23912/com.ispring.gameplane I/System.out: getDimensionPixelSize 中 px值是:17
2019-07-28 17:43:27.470 23912-23912/com.ispring.gameplane I/System.out: getDimensionPixelSize 中 dp值是:47
2019-07-28 17:43:27.470 23912-23912/com.ispring.gameplane I/System.out: getDimensionPixelSize 中 sp值是:47
2019-07-28 17:43:27.470 23912-23912/com.ispring.gameplane I/System.out: getDimensionPixelOffset 中 px值是:17
2019-07-28 17:43:27.470 23912-23912/com.ispring.gameplane I/System.out: getDimensionPixelOffset 中 dp值是:46
2019-07-28 17:43:27.470 23912-23912/com.ispring.gameplane I/System.out: getDimensionPixelOffset 中 sp值是:46
通過結(jié)果可以看出采郎,獲取某個(gè) dimen 的值千所,如果單位是 dp 或者 sp ,需要乘以 density (屏幕密度),如果是 px ,則不需要尉剩。
不同點(diǎn):
getDimension:返回的是 float 類型的值真慢。
getDimensionPixelSize: 返回的是 int 類型的值,并且由浮點(diǎn)型轉(zhuǎn)成整型時(shí)是四舍五入的方式理茎。
getDimensionPixelOffset : 返回的是 int 類型的值,并且由浮點(diǎn)型轉(zhuǎn)成整型時(shí)管嬉,原則是忽略小數(shù)點(diǎn)部分皂林。
- textView 在代碼中設(shè)置粗體可以這樣設(shè)置:
TextView tv = (TextView)findViewById(R.id.TextView01);
TextPaint tp = tv.getPaint();
tp.setFakeBoldText(true);
取消加粗效果的話設(shè)置
TextPaint tp = tv.getPaint();
tp.setFakeBoldText(false);
- android:clipToPadding屬性的用法
在使用 ListView 或者 RecycleView、ScrollView 等滑動(dòng)控件時(shí)候有一個(gè)強(qiáng)大但隱秘的屬性蚯撩,在android 的布局 XML 文件中础倍,android:clipToPadding=“boolean”,該屬性值可設(shè)為 true 或者false胎挎。表示控件的繪制區(qū)域是否在 padding 里面沟启,true 的情況下如果你設(shè)置了 padding 那么繪制的區(qū)域就往里縮忆家,false 則表示滑動(dòng)時(shí)忽略 padding 的值。系統(tǒng)默認(rèn)是 true德迹。
屬性的作用就是當(dāng)你對 ListView 等滑動(dòng)控件設(shè)置了 padding 屬性后芽卿,四周會有縮進(jìn)的效果,正常會與屏幕四邊有空白間距胳搞,然后滑動(dòng)的時(shí)候此間距一直顯示卸例。如果設(shè)置 android:clipToPadding=“false” ,則在滑動(dòng)的時(shí)候間距自動(dòng)隨著滑動(dòng)布局上滑以致不會顯示空白間距,此時(shí)也就有了比較好的用戶體驗(yàn)肌毅。
效果就是下邊兩張圖所示:第一張為默認(rèn)情況筷转,即 android:clipToPadding =“true”,第二張為 false 時(shí)的結(jié)果。
- ColorStateList 可以設(shè)置文字顏色在不同狀態(tài)下切換的功能悬而,不需要手動(dòng)根據(jù)不同狀態(tài)設(shè)置不同的顏色值呜舒,使用方法如下:
首先,定義一個(gè) selector 的選擇器
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/color_ffffff" android:state_enabled="true" android:state_selected="true" />
<item android:color="@color/color_2f9cf6"/>
</selector>
在代碼中使用方法如下:
ColorStateList csl=(ColorStateList)getResources().getColorStateList(R.color.button_text);
Button btn = new Button(mContext);
btn.setTextColor(csl);
也可以直接在布局文件中設(shè)置 android:textColor = "@color/button_text" 來實(shí)現(xiàn)笨奠。
此外袭蝗,還有個(gè) StateListDrawable 與 ColorStateList 類似,只不過它是設(shè)置 drawable 類型的資源文件艰躺,并且設(shè)置的資源文件是放在 res/drawable/ 文件夾下呻袭,靜態(tài)使用方法如下:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:drawable="@drawable/button_pressed" /> <!-- pressed -->
<item android:state_focused="true"
android:drawable="@drawable/button_focused" /> <!-- focused -->
<item android:state_hovered="true"
android:drawable="@drawable/button_focused" /> <!-- hovered -->
<item android:drawable="@drawable/button_normal" /> <!-- default -->
</selector>
<Button
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:background="@drawable/button" />
也可以動(dòng)態(tài)代碼構(gòu)造一個(gè) StateListDrawable ,例如:
//初始化一個(gè)空對象
StateListDrawable stalistDrawable = new StateListDrawable();
//獲取對應(yīng)的屬性值 Android框架自帶的屬性 attr
int pressed = android.R.attr.state_pressed;
int window_focused = android.R.attr.state_window_focused;
int focused = android.R.attr.state_focused;
int selected = android.R.attr.state_selected;
stalistDrawable.addState(newint []{pressed , window_focused}, getResources().getDrawable(R.drawable.pic1));
//負(fù)值表示對應(yīng)的屬性是 false, 下邊的屬性即按下狀態(tài)但沒有獲取焦點(diǎn)的時(shí)候
stalistDrawable.addState(newint []{pressed , -focused}, getResources().getDrawable(R.drawable.pic2);
stalistDrawable.addState(newint []{selected }, getResources().getDrawable(R.drawable.pic3);
stalistDrawable.addState(newint []{focused }, getResources().getDrawable(R.drawable.pic4);
//沒有任何狀態(tài)時(shí)顯示的圖片腺兴,我們給它設(shè)置我空集合
stalistDrawable.addState(newint []{}, getResources().getDrawable(R.drawable.pic5);
動(dòng)態(tài)使用方法:
StateListDrawable states = new StateListDrawable();
states.addState(new int[] {-android.R.attr.state_pressed}, INTERSTITIAL_CLOSE_BUTTON_NORMAL.createDrawable( getContext()));
states.addState(new int[] {android.R.attr.state_pressed}, INTERSTITIAL_CLOSE_BUTTON_PRESSED.createDrawable(
getContext()));
mImageView.setImageDrawable(states);
- 異常的處理和拋出:throw與throws以及捕捉異常try左电、catch、finally
1页响、throws出現(xiàn)在方法函數(shù)頭篓足;而throw出現(xiàn)在函數(shù)體。
2闰蚕、throws表示出現(xiàn)異常的一種可能性栈拖,并不一定會發(fā)生這些異常;throw則是拋出了異常没陡,執(zhí)行throw則一定拋出了某種異常對象涩哟。
3、兩者都是消極處理異常的方式(這里的消極并不是說這種方式不好)盼玄,只是拋出或者可能拋出異常贴彼,但是不會由函數(shù)去處理異常,真正的處理異常由函數(shù)的上層調(diào)用處理埃儿。
4器仗、throws說明你有那個(gè)可能,傾向。throw的話精钮,那就是你把那個(gè)傾向變成真實(shí)的了威鹿。
5、舉例:throws E1,E2,E3只是告訴程序這個(gè)方法可能會拋出這些異常轨香,方法的調(diào)用者可能要處理這些異常忽你,而這些異常E1,E2弹沽,E3可能是該函數(shù)體產(chǎn)生的檀夹。
throw則是明確了這個(gè)地方要拋出這個(gè)異常。
舉個(gè)例子:
void function_throws(int a,int b) throws Exception1,Exception3{
try{
......
}catch(Exception1 e){
throw e;
}catch(Exception2 e){
System.out.println("出錯(cuò)了策橘!");
}
if(a!=b)
throw new Exception3("自定義異常");
}
代碼塊中可能會產(chǎn)生3個(gè)異常炸渡,(Exception1,Exception2,Exception3)。
如果產(chǎn)生 Exception1 異常丽已,則捕獲之后再拋出蚌堵,由該方法的調(diào)用者去處理。
如果產(chǎn)生 Exception2 異常沛婴,則該方法自己處理了(即System.out.println("出錯(cuò)了吼畏!");)。所以該方法就不會再向外拋出 Exception2 異常了嘁灯,即 throws Exception1,Exception3 里面不用寫 Exception2 異常泻蚊。
拋出異常后的語句都不會執(zhí)行,try catch finally 里 finally 不管怎樣都會執(zhí)行丑婿。
- 申請權(quán)限時(shí)性雄,在 Fragment 中申請權(quán)限,不要使用這種方式
ActivityCompat.requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE);
直接使用 Fragment 的 requestPermissions 方法羹奉,即
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE);
否則會回調(diào)到 Activity 的 onRequestPermissionsResult ,使用第二種方法會直接在 Fragment 里回調(diào)秒旋。
如果在 Fragment 中嵌套 Fragment,在子 Fragment 中使用 requestPermissions 方法诀拭,onRequestPermissionsResult 不會回調(diào)回來迁筛,建議在子 Fragment 中使用 getParentFragment().requestPermissions 方法,
這個(gè)方法會回調(diào)到父 Fragment 中的 onRequestPermissionsResult()耕挨,加入以下代碼可以把回調(diào)透傳到子 Fragment细卧。
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
List<Fragment> fragments = getChildFragmentManager().getFragments();
if (fragments != null) {
for (Fragment fragment : fragments) {
if (fragment != null) {
fragment.onRequestPermissionsResult(requestCode,permissions,grantResults);
}
}
}
}