自定義控件要想徹底的把握,掌握Android各種座標系及一些API的座標含義毫無疑問是不可忽視的技能,對於控件的擺放位置、觸摸點、控件繪製等都離不開座標系,所以學習自定義控件之前我們就先來談一下Android座標系。
一、Android屏幕座標系和數學座標系的區別
(1)、在數學座標系中以xy軸的交點爲座標原點,x軸向右爲正方向,y軸向上爲正方向,這對於童鞋們來說已經再熟悉不過了,如圖:
(2)、而在手機屏幕上的座標系與數學座標系還是有差別的,移動設備一般定義屏幕左上角爲座標原點,x軸向右爲正方向,y軸向下爲正方向,如圖:
二、Android屏幕區域的劃分
Android屏幕區域主要劃分爲五個區域分別爲:狀態欄區域、ActionBar區域、View佈局區域、應用程序App區域、屏幕區域,相互之間又存在嵌套關係。如圖所示:
下面我們來看看各個區域高度的獲取:
(1)、狀態欄區域高度獲取:
//第一種方式,使用此方法一定要等界面渲染結束
Rect rect = new Rect();
getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
int statusBarHeight = rect.top;
//第二種方式,獲取狀態欄高度
Resources resources = this.getResources();
int resourceId = resources.getIdentifier("status_bar_height", "dimen", "android");
int height = resources.getDimensionPixelSize(resourceId);//此次獲取狀態欄高度
//第三種方式,通過反射方式獲取狀態欄高度
int statusHeight = -1;
try {
Class clazz = Class.forName("com.android.internal.R$dimen");
Object object = clazz.newInstance();
int intheight = Integer.parseInt(clazz.getField("status_bar_height")
.get(object).toString());
//獲取狀態欄高度
statusHeight = this.getResources().getDimensionPixelSize(intheight);
} catch (Exception e) {
e.printStackTrace();
}
(2)、ActionBar區域高度獲取:
//第一種方式,此方法要等界面渲染結束
int actionBarHeight = getSupportActionBar().getHeight();
//第二種方式
TypedValue tv = new TypedValue();
if (this.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)) {
int actionBarHeightOther = TypedValue.complexToDimensionPixelSize(
tv.data, this.getResources().getDisplayMetrics());
}
(3)、View佈局區域高度獲取:
//第一種方式
Rect rect = new Rect();
getWindow().findViewById(Window.ID_ANDROID_CONTENT).getDrawingRect(rect);
//第二種方式
//可見當執行onResume和onPause時,onWindowFocusChanged都會被調用。此時界面已渲染結束
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
int width = view.getMeasuredWidth();//獲得寬度
int height = view.getMeasuredHeight();//獲得高度
}
}
//第三種方式
view.post(new Runnable() {
@Override
public void run() {
int width=view.getMeasuredWidth();
int height=view.getMeasuredHeight();
}
})
//第四種方式
view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
int width=view.getMeasuredWidth();
int height=view.getMeasuredHeight();
}
});
(4)、應用程序App區域高度獲取:
Rect rect = new Rect();
getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
(5)、屏幕區域高度獲取:
//第一種方式,該方式在4.1版本後已過時。
Display display = getWindowManager().getDefaultDisplay();
int width = display.getWidth();
int height = display.getHeight();
//第二種方式
Display defaultDisplay = getWindowManager().getDefaultDisplay();
Point point = new Point();
defaultDisplay.getSize(point);
int x = point.x;
int y = point.y;
//第三種方式
Rect outSize = new Rect();
getWindowManager().getDefaultDisplay().getRectSize(outSize);
int left = outSize.left;
int top = outSize.top;
int right = outSize.right;
int bottom = outSize.bottom;
//第四種方式
DisplayMetrics outMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(outMetrics);
int widthPixels = outMetrics.widthPixels;
int heightPixels = outMetrics.heightPixels;
//第五種方式
Point outSizeOther = new Point();
getWindowManager().getDefaultDisplay().getRealSize(outSizeOther);
int x1 = outSizeOther.x;
int y1 = outSizeOther.y;
//第六種方式
DisplayMetrics outMetrics1 = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getRealMetrics(outMetrics1);
int widthPixel = outMetrics1.widthPixels;
int heightPixel = outMetrics1.heightPixels;
特別注意:上面這些方法最好在Activity的onWindowFocusChanged()方法或者之後調用,因爲只有這時候纔是真正的顯示完全。
三、Android座標系的分類
上面我們分析了Android屏幕區域的劃分,接着我們分析一下與區域相關的Android座標系,在Android座標系中可以分爲:屏幕座標系,視圖座標系。
(1)、屏幕座標系
屏幕座標系我們前面在和數學座標系的區別已經介紹過了,以屏幕左上角爲座標原點,x軸向右爲正方向,y軸向下爲正方向,如圖所示:
(2)、視圖座標系
視圖座標系在View繪製過程中,繪製的內容將以座標系作爲參考,最後確定繪製內容在View裏面的位置。
下面我們來看看常用的座標方法,注意這些方法是相對父容器而言的:
View相關方法 : 方法說明
view.getLeft(): 當前View的左邊緣與它父View的左邊緣的距離(視圖座標);
view.getRight(): 當前View的右邊緣與它父View的左邊緣的距離(視圖座標);
view.getTop(): 當前View的上邊緣與它父View的上邊緣(頂部)的距離(視圖座標);
view.getBottom(): 當前View的下邊緣與它父View的上邊緣(頂部)的距離(視圖座標);
View.getTranslationX(): 當前View在X軸的偏移量。初始值爲0,向左偏移值爲負,向右偏移值爲正;(常見於屬性動畫中)
View.getTranslationY(): 當前View在Y軸的偏移量。初始值爲0,向上偏移爲負,向下偏移爲正;(常見於屬性動畫中)
View.getX: 當前View在X軸的偏移量。初始值爲0,向左偏移值爲負,向右偏移值爲正;返回值爲getLeft()+getTranslationX(),當setTranslationX()變getLeft()不變時,getX()變。
View.getY: 當前View在Y軸的偏移量。初始值爲0,向上偏移爲負,向下偏移爲正;返回值爲getTop()+getTranslationY(),當setTranslationY()變getTop()不變時,getY()變。
爲了解釋清楚這些方法,準備了張圖,如圖所示:
此時我們可以獲取視圖(View)寬高的方法:
View寬高方法 : 方法說明
getWidth(): 當前View的寬度,即getRight()-getLeft()
getHeight(): 當前View寬度,即getBottom()-getTop()
需要注意的是使用以上方法的過程中要在View測量結束即渲染完成後,不然獲取到的值爲0。
我們再來看看手指觸摸屏幕時MotionEvent提供的一些方法解釋:
MotionEvent座標方法: 方法說明
getX(): 觸摸中心點與該View左邊緣的距離(相對座標)
getY(): 觸摸中心點與該View上邊緣的距離(相對座標)
getRawX(): 觸摸中心點與屏幕左邊緣的距離(絕對座標)
getRawY(): 觸摸中心點與屏幕上邊緣的距離(絕對座標)
爲了解釋清楚這些方法,準備了張圖,如圖所示:
今天的內容就到這啦,本文主要就是闡述View裏常用方法及座標相關的概念,也是爲後期的內容做鋪墊。歡迎關注公衆號【龍旋】能獲取最新更新內容哦。