【Android】坐標體系锰悼、控件寬高、控件滑動

一团赏、View 坐標體系

以下方法獲取的是相對于父控件的坐標箕般,是在回調 onLayout 方法時 view.layout(t,l,b,r) 方法設置的 mLeft、mTop舔清、mBottom丝里、mRight 等屬性,mRight = mLeft + 控件自身寬度体谒,mBottom = mTop + 控件自身高度杯聚,除非調用 layout、setLeft抒痒、setFrame 等方法幌绍,否則是不會改變的;

getTop()        //獲取子 View 頂邊距父 View 頂邊的距離
getLeft()      //獲取子 View 左邊距父 View 左邊的距離
getBottom()    //獲取子 View 底邊距父 View 頂邊的距離
getRight()     //獲取子 View 右邊距父 View 左邊的距離

getTranslationX 方法和 getTranslationY 方法獲取的是 View 相對于父控件的偏移量故响,初始時為 0纷捞,向左(上)偏移為負,向右(下)偏移為正被去;
getX 和 getY 獲取的是 View 左邊或上邊距離父 View 左邊和上邊的實際距離主儡,是移動后的值;

getX()    //返回值為getLeft()+getTranslationX()惨缆,當setTranslationX()時getLeft()不變糜值,getX()變
getY()    //返回值為getTop()+getTranslationY()丰捷,當setTranslationY()時getTop()不變,getY()變

二寂汇、MotionEvent 單點觸控中的坐標

Android 將所有的輸入事件都放在了 MotionEvent 中病往,MotionEvent 負責集中處理所有類型設備的輸入事件,

單點觸控主要涉及以下幾個事件

  • ACTION_DOWN 手指初次接觸到屏幕時觸發(fā)
  • ACTION_MOVE 手指在屏幕上滑動時觸發(fā)骄瓣,會多次觸發(fā)
  • ACTION_UP 手指離開屏幕時觸發(fā)
  • ACTION_CANCEL 事件被上層攔截時觸發(fā)
  • ACTION_OUTSIDE 手指不在控件區(qū)域時觸發(fā)

這里的坐標指的是觸摸點的坐標

getAction()   //獲取事件類型
getX()        //觸摸點相對于 View 的 X 軸坐標
getY()        //觸摸點相對于 View 的 Y 軸坐標
getRawX()     //觸摸點在整個屏幕的 X 坐標
getRawY()      //觸摸點在整個屏幕的 Y 坐標

三停巷、View 在屏幕中位置

//獲取 View 自身可見的矩形坐標區(qū)域,坐標以自己的左上角為原點(0,0)榕栏,另一點為可見區(qū)域右下角相對自己(0,0)點的坐標畔勤,返回 View 所在矩形區(qū)域
getLocalVisibleRect()  
// 獲取 View 在屏幕絕對坐標系中的可視區(qū)域,坐標以屏幕左上角為原點(0,0)扒磁,另一個點為可見區(qū)域右下角相對屏幕原點(0,0)點的坐標庆揪,返回 View 所在矩形區(qū)域
getGlobalVisibleRect()  
//坐標是相對整個屏幕而言,坐標為 View 左上角到屏幕左端和頂部的距離妨托,返回的是左上角的坐標
getLocationOnScreen() 
//如果為普通 Activity 則 Y 坐標為 View 左上角到屏幕頂部(此時 Window 與屏幕一樣大)缸榛;如果為對話框式的 Activity 則Y坐標為當前 Dialog 模式 Activity 的標題欄頂部到 View 左上角的距離。兰伤,返回左上角的坐標
getLocationInWindow()  

四内颗、獲取 View 寬高的方法

getMeasuredWidth()     //返回measure過程得到的mMeasuredWidth值,供layout參考敦腔,或許沒用均澳。 
getMeasuredHeight()     //返回measure過程得到的mMeasuredHeight值,供layout參考会烙,或許沒用负懦。
getWidth()     //layout后有效,返回值是 mRight - mLeft柏腻,一般會參考 measure 的寬度(measure 可能沒用),但不是必須的五嫂。 
getHeight()     //layout后有效颗品,返回值是 mBottom - mTop,一般會參考 measure 的高度(measure 可能沒用)躯枢,但不是必須的锄蹂。 

一般在 onCreate 方法里面獲取的控件寬高都為 0水慨。使用下面的方法可以獲得控件的寬高。

方法一啥箭、Activity/View#onWindowFocusChanged

當 Activity 窗口得到焦點和失去焦點時侮邀,onWindowFocusChanged 方法均會被調用一次陕悬。

方法二、view.post(Runnable)

將一個消息投遞到消息隊列尾部唯绍,等待 Looper 調用此 Runnable 對象時绝骚, View 已經初始化完畢了压汪。

方法三落君、手動對 View 進行 measure
int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(0,MeasureSpec.UNSPECIFIED);
int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(0,MeasureSpec.UNSPECIFIED);
view.measure(widthMeasureSpec,heightMeasureSpec);
int width = view.getMeasureSpec();
int height = view.getMeasureHeight();
方法四洒宝、使用 ViewTreeObserver 的回調
ViewTreeObserver vto = view.getViewTreeObserver();  
vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {  
      public boolean onPreDraw() {  
                int height = view.getMeasuredHeight();  
                int width = view.getMeasuredWidth();  
                return true;  
       }  
 });  
方法五将宪、使用 ViewTreeObserver 的回調
ViewTreeObserver vto = view.getViewTreeObserver();    
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener(){  
        @Override    
        public void onGlobalLayout() {  
              view.getViewTreeObserver().removeOnGlobalLayoutListener(this);    
              int height = view.getHeight();  
              int width = view.getWidth();  
       }    
 });

五印蔗、屏幕尺寸

1法竞、屏幕寬高
//方法一
WindowManager windowManager = getWindowManager();  
Display display = windowManager.getDefaultDisplay();  
int screenWidth = display.getWidth();  
int screenHeight = display.getHeight();  

//方法二
DisplayMetrics displayMetrics = new DisplayMetrics();   
context.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);//this指當前activity  
screenWidth =displayMetrics.widthPixels;  
screenHeight =displayMetrics.heightPixels
2型宝、獲取整個應用程序區(qū)域(除狀態(tài)欄之外的區(qū)域)
Rect rect = new Rect();
getWindow().getDecorWindow().getWindowVisibleDisplayFrame(rect);
3、除了狀態(tài)欄和標題欄之外的View繪制的區(qū)域
 Rect outRect = new Rect();  
 context.getWindow().findViewById(Window.ID_ANDROID_CONTENT).getDrawingRect(outRect);
4渊涝、狀態(tài)欄高度
//方法一
Rect frame = new Rect();  
context.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);  
int statusBarHeight = frame.top;

//方法二
int resourceId=getResources().getIdentifier("status_bar_height","dimen","android");
if(resourceId>0){
     int statusBarHeight=getResources().getDimensionPixelSize(resourceId);
}
5、標題欄高度
 int contentTop = getWindow().findViewById(Window.ID_ANDROID_CONTENT).getTop();  
    //statusBarHeight是上面所求的狀態(tài)欄的高度  
    int titleBarHeight = contentTop - statusBarHeight  

六、View滑動

1暖侨、scrollTo和scrollBy滑動

只改變View內容的位置葫掉,實際上View的坐標沒有變化户魏,left叼丑,top笤休,x店雅,y等布局參數(shù)沒有變

getScrollX()    //獲得View內容在x軸方向的偏移量闹啦,View內容的左邊緣在View左邊緣左側時為正窍奋,反之為負
getScrollY()    //獲得View內容在y軸方向的偏移量,View內容的上邊緣在View上邊緣上側時為正,反之為負

scrollBy為相對滑動,View內容從左往右滑時為負音同,從右往左滑時為正蛇尚;從上往下滑時為負取劫,從下往上滑時為正

2、使用屬性動畫

改變的是 View 本身的位置
屬性動畫改變的是 translationX 和 translationY 代表的是 View
的偏移量,而不是top迅栅,left等初始參數(shù)

3读存、改變布局參數(shù)

直接對 View 的位置參數(shù)進行改變
實際上改變的是 View 的 left为流,top,right让簿,bottom 四個初始坐標

View在繪制完成后這四個初始值是不會改變的敬察,實際上setLayoutParams()對布局參數(shù)的改變,會觸發(fā)View的重新測繪拜英、布局静汤、繪制這三個流程,那么這四個值也就隨之改變

4、使用 layout

View在繪制的時候會調用layout()來確定View本身的位置虫给,那么我們可以直接調用這個方法來繪制View:

viwe.layout(int left,int top,int right,int bottom);

以上都是view相對于父容器的坐標藤抡,View的位置的確定依賴于這四個坐標,如果這四個坐標不按照view自身的縮放比例設置抹估,會造成View制圖的縮放缠黍。
所以如果為了View的正常滑動药蜻,一般可以將以上代碼修改成如下:

view.layout(view.getLeft()+offsetX,view.getTop()+offsetY,view.getRight()+offsetX,view.getBottom()+offsetY);

5瓷式、使用 offsetLeftAndRight 和 offsetTopAndBottom

直接調用View的offsetLeftAndRight(int offsetX)或者offsetTopAndBottom(int offsetY)能對view的四個坐標直接進行偏移,以達到移動view的目的语泽。

七贸典、彈性滑動

1、Scroller

Scroller常用模板

//實例化Scroller對象踱卵,在自定義View中廊驼,mContext 可以在自定義View的構造方法中獲取
Scroller mScroller = new Scroller(mContext);

//在一個自定義View中實現(xiàn)該方法,方法名可以自定義
public void smoothScrollTo(int destX,int destY){
    int scrollX = getScrollX();
    int scrollY  = getScrollY();
    int dx = destX - scrollX;
    int dy = destY - scrollY;
    //前兩個參數(shù)表示起始位置惋砂,第三第四個參數(shù)表示位移量妒挎,最后一個參數(shù)表示時間
    mScroller.startScroll(scrollX,scrollY,dx,dy,1000);
    invalidate();
}

//自定義View中重寫該方法
@Override
public void computeScroll(){
    if(mScroller.computeScrollOffset()){
       scrollTo(mScroller.getCurrX(),mScroller.getCurrY());
       postInvalidate();
    }
}

2、ValueAnimator

ValueAnimator animator = ValueAnimator.ofXXX();
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                animation.getAnimatedValue();
            }
});
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末西饵,一起剝皮案震驚了整個濱河市酝掩,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌眷柔,老刑警劉巖期虾,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異闯割,居然都是意外死亡彻消,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進店門宙拉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人丙笋,你說我怎么就攤上這事谢澈。” “怎么了御板?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵锥忿,是天一觀的道長。 經常有香客問我怠肋,道長敬鬓,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮钉答,結果婚禮上础芍,老公的妹妹穿的比我還像新娘。我一直安慰自己数尿,他們只是感情好仑性,可當我...
    茶點故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著右蹦,像睡著了一般诊杆。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上何陆,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天晨汹,我揣著相機與錄音,去河邊找鬼贷盲。 笑死宰缤,一個胖子當著我的面吹牛,可吹牛的內容都是我干的晃洒。 我是一名探鬼主播慨灭,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼球及!你這毒婦竟也來了氧骤?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤吃引,失蹤者是張志新(化名)和其女友劉穎筹陵,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體镊尺,經...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡朦佩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了庐氮。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片语稠。...
    茶點故事閱讀 38,605評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡夕冲,死狀恐怖乓序,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情廉邑,我是刑警寧澤音婶,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布慨畸,位于F島的核電站,受9級特大地震影響衣式,放射性物質發(fā)生泄漏寸士。R本人自食惡果不足惜檐什,卻給世界環(huán)境...
    茶點故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望弱卡。 院中可真熱鬧乃正,春花似錦、人聲如沸谐宙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽凡蜻。三九已至搭综,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間划栓,已是汗流浹背兑巾。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留忠荞,地道東北人蒋歌。 一個月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像委煤,于是被迫代替她去往敵國和親堂油。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,472評論 2 348

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,747評論 25 707
  • 6碧绞、View的繪制 (1)當測量好一個View之后府框,我們就可以簡單的重寫 onDraw()方法,并在 Canvas...
    b5e7a6386c84閱讀 1,890評論 0 3
  • ¥開啟¥ 【iAPP實現(xiàn)進入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個線程讥邻,因...
    小菜c閱讀 6,365評論 0 17
  • 有人說:一個人迫靖,想要優(yōu)秀,就必須要接受挑戰(zhàn)兴使,如果想要盡快優(yōu)秀系宜,就要去尋找挑戰(zhàn)。 那么发魄,我現(xiàn)在正在接受挑戰(zhàn)盹牧,也就是說...
    我是我的光閱讀 356評論 0 1
  • callee的應用,用于寫遞歸函數(shù)欠母,調用自身
    200813閱讀 350評論 0 0